Merge pull request #418 from bonzini/without-libgcrypt

allow choosing between libgcrypt, gnutls or embedded MD5
This commit is contained in:
Ronnie Sahlberg
2024-04-10 03:36:55 +10:00
committed by GitHub
3 changed files with 90 additions and 32 deletions

View File

@@ -78,8 +78,43 @@ AM_CONDITIONAL([BUILD_EXAMPLES],
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CHECK_LIB([gcrypt], [gcry_control]) AC_ARG_WITH([gnutls],
AM_CONDITIONAL([HAVE_LIBGCRYPT], [test $ac_cv_lib_gcrypt_gcry_control = yes]) [AS_HELP_STRING([--with-gnutls],
[Use gnutls to compute MD5])],
[WITH_GNUTLS=$withval],
[WITH_GNUTLS=auto])
AC_ARG_WITH([libgcrypt],
[AS_HELP_STRING([--with-libgcrypt],
[Use libgcrypt to compute MD5])],
[WITH_LIBGCRYPT=$withval],
[WITH_LIBGCRYPT=auto])
if test "$WITH_GNUTLS" != no; then
AC_CHECK_LIB([gnutls], [gnutls_hash_init])
if test "$WITH_GNUTLS" = yes && test "$ac_cv_lib_gnutls_gnutls_hash_init" != yes; then
AC_MSG_ERROR([gnutls not found])
fi
WITH_GNUTLS=$ac_cv_lib_gnutls_gnutls_hash_init
fi
if test "$WITH_GNUTLS" = yes; then
WITH_LIBGCRYPT=no
fi
if test "$WITH_LIBGCRYPT" != no; then
AC_CHECK_LIB([gcrypt], [gcry_control])
if test "$WITH_LIBGCRYPT" = yes && test "$ac_cv_lib_gcrypt_gcry_control" != yes; then
AC_MSG_ERROR([libgcrypt not found])
fi
WITH_LIBGCRYPT=$ac_cv_lib_gcrypt_gcry_control
fi
NEED_MD5=no
if test "$WITH_GNUTLS" = no && test "$WITH_LIBGCRYPT" = no; then
NEED_MD5=yes
fi
AM_CONDITIONAL([NEED_MD5],
[expr "$NEED_MD5" : yes > /dev/null 2>&1])
# For MinGW. # For MinGW.
AC_CHECK_LIB([ws2_32], [gethostbyname]) AC_CHECK_LIB([ws2_32], [gethostbyname])

View File

@@ -12,7 +12,7 @@ if TARGET_OS_IS_WIN32
libiscsipriv_la_SOURCES += ../win32/win32_compat.c libiscsipriv_la_SOURCES += ../win32/win32_compat.c
endif endif
if !HAVE_LIBGCRYPT if NEED_MD5
libiscsipriv_la_SOURCES += md5.c libiscsipriv_la_SOURCES += md5.c
endif endif

View File

@@ -44,6 +44,10 @@
#include "iscsi-private.h" #include "iscsi-private.h"
#include "scsi-lowlevel.h" #include "scsi-lowlevel.h"
#include "md5.h" #include "md5.h"
#ifdef HAVE_LIBGNUTLS
#include <gnutls/crypto.h>
#endif
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
#include <gcrypt.h> #include <gcrypt.h>
#endif #endif
@@ -681,41 +685,61 @@ i2h(int i)
return i + '0'; return i + '0';
} }
#ifndef HAVE_LIBGCRYPT #if defined HAVE_LIBGNUTLS
typedef struct MD5Context *gcry_md_hd_t; #define md5_context_t gnutls_hash_hd_t
#define gcry_md_write MD5Update #define md5_open(hd) gnutls_hash_init(hd, GNUTLS_DIG_MD5)
#define GCRY_MD_MD5 1 #define md5_write gnutls_hash
#define md5_read gnutls_hash_output
static void gcry_md_open(gcry_md_hd_t *hd, int algo, unsigned int flags) static void md5_close(md5_context_t h)
{
unsigned char digest[16];
gnutls_hash_deinit(h, digest);
}
#elif defined HAVE_LIBGCRYPT
typedef gcry_md_hd_t md5_context_t;
#define md5_open(hd) gcry_md_open(hd, GCRY_MD_MD5, 0)
#define md5_write gcry_md_write
#define md5_close gcry_md_close
static void md5_read(md5_context_t h, uint8_t *result)
{
memcpy(result, gcry_md_read(h, 0), 16);
}
#else
typedef struct MD5Context *md5_context_t;
#define md5_write MD5Update
static void md5_open(md5_context_t *hd)
{ {
assert(algo == GCRY_MD_MD5 && flags == 0);
*hd = malloc(sizeof(struct MD5Context)); *hd = malloc(sizeof(struct MD5Context));
if (*hd) { if (*hd) {
MD5Init(*hd); MD5Init(*hd);
} }
} }
static void gcry_md_putc(gcry_md_hd_t h, unsigned char c) static void md5_read(md5_context_t h, uint8_t *result)
{
MD5Update(h, &c, 1);
}
static char *gcry_md_read(gcry_md_hd_t h, int algo)
{ {
unsigned char digest[16]; unsigned char digest[16];
assert(algo == 0 || algo == GCRY_MD_MD5);
MD5Final(digest, h); MD5Final(digest, h);
return memcpy(h->buf, digest, sizeof(digest)); memcpy(result, digest, sizeof(digest));
} }
static void gcry_md_close(gcry_md_hd_t h) static void md5_close(md5_context_t h)
{ {
memset(h, 0, sizeof(*h)); memset(h, 0, sizeof(*h));
free(h); free(h);
} }
#endif #endif
static inline void md5_putc(md5_context_t h, unsigned char c)
{
md5_write(h, &c, 1);
}
/* size of the challenge used for bidirectional chap */ /* size of the challenge used for bidirectional chap */
#define TARGET_CHAP_C_SIZE 32 #define TARGET_CHAP_C_SIZE 32
@@ -726,7 +750,7 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu
char * strp; char * strp;
unsigned char c, cc[2]; unsigned char c, cc[2];
unsigned char digest[CHAP_R_SIZE]; unsigned char digest[CHAP_R_SIZE];
gcry_md_hd_t ctx; md5_context_t ctx;
int i; int i;
if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG
@@ -739,22 +763,22 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu
return -1; return -1;
} }
gcry_md_open(&ctx, GCRY_MD_MD5, 0); md5_open(&ctx);
if (ctx == NULL) { if (ctx == NULL) {
iscsi_set_error(iscsi, "Cannot create MD5 algorithm"); iscsi_set_error(iscsi, "Cannot create MD5 algorithm");
return -1; return -1;
} }
gcry_md_putc(ctx, iscsi->chap_i); md5_putc(ctx, iscsi->chap_i);
gcry_md_write(ctx, (unsigned char *)iscsi->passwd, strlen(iscsi->passwd)); md5_write(ctx, (unsigned char *)iscsi->passwd, strlen(iscsi->passwd));
strp = iscsi->chap_c; strp = iscsi->chap_c;
while (*strp != 0) { while (*strp != 0) {
c = (h2i(strp[0]) << 4) | h2i(strp[1]); c = (h2i(strp[0]) << 4) | h2i(strp[1]);
strp += 2; strp += 2;
gcry_md_putc(ctx, c); md5_putc(ctx, c);
} }
memcpy(digest, gcry_md_read(ctx, 0), sizeof(digest)); md5_read(ctx, digest);
gcry_md_close(ctx); md5_close(ctx);
strncpy(str,"CHAP_R=0x",MAX_STRING_SIZE); strncpy(str,"CHAP_R=0x",MAX_STRING_SIZE);
if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)) if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str))
@@ -822,20 +846,19 @@ iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu
return -1; return -1;
} }
gcry_md_open(&ctx, GCRY_MD_MD5, 0); md5_open(&ctx);
if (ctx == NULL) { if (ctx == NULL) {
iscsi_set_error(iscsi, "Cannot create MD5 algorithm"); iscsi_set_error(iscsi, "Cannot create MD5 algorithm");
return -1; return -1;
} }
gcry_md_putc(ctx, iscsi->target_chap_i); md5_putc(ctx, iscsi->target_chap_i);
gcry_md_write(ctx, (unsigned char *)iscsi->target_passwd, md5_write(ctx, (unsigned char *)iscsi->target_passwd,
strlen(iscsi->target_passwd)); strlen(iscsi->target_passwd));
gcry_md_write(ctx, (unsigned char *)target_chap_c, md5_write(ctx, (unsigned char *)target_chap_c,
TARGET_CHAP_C_SIZE); TARGET_CHAP_C_SIZE);
memcpy(iscsi->target_chap_r, gcry_md_read(ctx, 0), md5_read(ctx, iscsi->target_chap_r);
sizeof(iscsi->target_chap_r)); md5_close(ctx);
gcry_md_close(ctx);
} }
return 0; return 0;