From 41a20fef10382a3d2c7f3260a8e0fba8a29d809a Mon Sep 17 00:00:00 2001 From: Peter Keresztes Schmidt Date: Jun 08 2020 11:35:03 +0000 Subject: util: replace NSS usage with OpenSSL Fixes: https://pagure.io/freeipa/issue/6857 Reviewed-By: Alexander Bokovoy Reviewed-By: Christian Heimes --- diff --git a/util/Makefile.am b/util/Makefile.am index 9ae9c8e..a240006 100644 --- a/util/Makefile.am +++ b/util/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS = 1.7 subdir-objects -AM_CPPFLAGS = $(CRYPTO_CFLAGS) $(KRB5_CFLAGS) $(LDAP_CFLAGS) $(NSS_CFLAGS) +AM_CPPFLAGS = $(CRYPTO_CFLAGS) $(KRB5_CFLAGS) $(LDAP_CFLAGS) noinst_LTLIBRARIES = libutil.la @@ -13,7 +13,7 @@ libutil_la_SOURCES = ipa_krb5.c \ ipa_pwd.h \ ipa_pwd_ntlm.c -libutil_la_LIBADD = $(CRYPTO_LIBS) $(KRB5_LIBS) $(LDAP_LIBS) $(NSS_LIBS) +libutil_la_LIBADD = $(CRYPTO_LIBS) $(KRB5_LIBS) $(LDAP_LIBS) check_PROGRAMS = t_pwd TESTS = $(check_PROGRAMS) diff --git a/util/ipa_pwd.c b/util/ipa_pwd.c index 0308735..0d3c351 100644 --- a/util/ipa_pwd.c +++ b/util/ipa_pwd.c @@ -24,15 +24,15 @@ #define _GNU_SOURCE #endif #include +#include #include #include #include #include -#include -#include -#include -#include #include +#include +#include +#include #include "ipa_pwd.h" #define GENERALIZED_TIME_LENGTH 15 @@ -160,31 +160,23 @@ static int ipapwd_gentime_cmp(const void *p1, const void *p2) #define SHA_SALT_LENGTH 8 -/* SHA*_LENGTH leghts come from nss3/hasht.h */ -#define SHA_HASH_MAX_LENGTH SHA512_LENGTH - -static int ipapwd_hash_type_to_alg(char *hash_type, - SECOidTag *hash_alg, - unsigned int *hash_alg_len) +static int ipapwd_hash_type_to_alg(const char *hash_type, + char **hash_alg_sn) { if (strncmp("{SSHA}", hash_type, 6) == 0) { - *hash_alg = SEC_OID_SHA1; - *hash_alg_len = SHA1_LENGTH; + *hash_alg_sn = SN_sha1; return 0; } if (strncmp("{SHA256}", hash_type, 8) == 0) { - *hash_alg = SEC_OID_SHA256; - *hash_alg_len = SHA256_LENGTH; + *hash_alg_sn = SN_sha256; return 0; } if (strncmp("{SHA384}", hash_type, 8) == 0) { - *hash_alg = SEC_OID_SHA384; - *hash_alg_len = SHA384_LENGTH; + *hash_alg_sn = SN_sha384; return 0; } if (strncmp("{SHA512}", hash_type, 8) == 0) { - *hash_alg = SEC_OID_SHA512; - *hash_alg_len = SHA512_LENGTH; + *hash_alg_sn = SN_sha512; return 0; } @@ -202,7 +194,7 @@ static int ipapwd_hash_type_to_alg(char *hash_type, * @return 0 on success, -1 on error. */ int ipapwd_hash_password(char *password, - char *hash_type, + const char *hash_type, unsigned char *salt, unsigned char **full_hash, unsigned int *full_hash_len) @@ -212,47 +204,53 @@ int ipapwd_hash_password(char *password, unsigned char *pwd = (unsigned char *)password; unsigned int pwdlen = strlen(password); unsigned char saltbuf[SHA_SALT_LENGTH]; - unsigned char hash[SHA_HASH_MAX_LENGTH]; + unsigned char hash[EVP_MAX_MD_SIZE] = { 0 }; unsigned int hash_len; - SECOidTag hash_alg; - unsigned int hash_alg_len; - PK11Context *ctx = NULL; + int ret; - NSS_NoDB_Init("."); + EVP_MD_CTX *ctx = NULL; + char *hash_alg_sn = NULL; + const EVP_MD* hash_alg = NULL; if (!salt) { - PK11_GenerateRandom(saltbuf, SHA_SALT_LENGTH); + RAND_bytes(saltbuf, SHA_SALT_LENGTH); salt = saltbuf; } - ret = ipapwd_hash_type_to_alg(hash_type, &hash_alg, &hash_alg_len); + ret = ipapwd_hash_type_to_alg(hash_type, &hash_alg_sn); if (ret) { return -1; } - ctx = PK11_CreateDigestContext(hash_alg); - if (ctx == NULL) { + hash_alg = EVP_get_digestbyname(hash_alg_sn); + if (!hash_alg) { return -1; } - memset(hash, 0, sizeof(hash)); + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + return -1; + } - ret = PK11_DigestBegin(ctx); - if (ret == SECSuccess) { - ret = PK11_DigestOp(ctx, pwd, pwdlen); + ret = EVP_DigestInit_ex(ctx, hash_alg, NULL); + if (ret) { + ret = EVP_DigestUpdate(ctx, pwd, pwdlen); } - if (ret == SECSuccess) { - ret = PK11_DigestOp(ctx, salt, SHA_SALT_LENGTH); + if (ret) { + ret = EVP_DigestUpdate(ctx, salt, SHA_SALT_LENGTH); } - if (ret == SECSuccess) { - ret = PK11_DigestFinal(ctx, hash, &hash_len, hash_alg_len); + if (ret) { + ret = EVP_DigestFinal_ex(ctx, hash, &hash_len); } - if (ret != SECSuccess) { + if (!ret) { ret = -1; goto done; } - if (hash_len != hash_alg_len) { + else + ret = 0; + + if (hash_len != (unsigned int) EVP_MD_CTX_size(ctx)) { ret = -1; goto done; } @@ -268,7 +266,7 @@ int ipapwd_hash_password(char *password, memset(fh + fhl, '\0', 1); done: - PK11_DestroyContext(ctx, 1); + EVP_MD_CTX_free(ctx); *full_hash = fh; *full_hash_len = fhl; return ret; @@ -290,14 +288,11 @@ static int ipapwd_cmp_password(char *password, char *historyString) char *hash_type; char *b64part; size_t b64_len; - SECItem *item; unsigned char *salt; unsigned char *hash = NULL; unsigned int hash_len; int ret; - NSS_NoDB_Init("."); - hash_type = historyString; b64part = strchr(historyString, '}'); if (!b64part) { @@ -306,27 +301,32 @@ static int ipapwd_cmp_password(char *password, char *historyString) b64part++; b64_len = strlen(b64part); - item = NSSBase64_DecodeBuffer(NULL, NULL, b64part, b64_len); - if (!item) { + unsigned char *item_data = (unsigned char *) OPENSSL_malloc(sizeof(char) * b64_len); + if (!item_data) { return -1; } - if (item->len <= SHA_SALT_LENGTH) { + + size_t item_len = EVP_DecodeBlock(item_data, (unsigned char *) b64part, b64_len); + if (!item_data) { + return -1; + } + if (item_len <= SHA_SALT_LENGTH) { ret = -1; goto done; } - salt = item->data + (item->len - SHA_SALT_LENGTH); + salt = item_data + (item_len - SHA_SALT_LENGTH); ret = ipapwd_hash_password(password, hash_type, salt, &hash, &hash_len); if (ret != 0) { goto done; } - if (hash_len != item->len) { + if (hash_len != item_len) { ret = 1; goto done; } - if (memcmp(item->data, hash, hash_len)) { + if (CRYPTO_memcmp(item_data, hash, hash_len)) { ret = 1; goto done; } @@ -334,7 +334,9 @@ static int ipapwd_cmp_password(char *password, char *historyString) ret = 0; done: - SECITEM_FreeItem(item, 1); + if (item_data) + OPENSSL_clear_free(item_data, sizeof(char) * b64_len); + free(hash); return ret; } @@ -359,33 +361,33 @@ static char *ipapwd_hash_to_history(time_t hash_time, { struct tm utctime; char timestr[GENERALIZED_TIME_LENGTH+1]; - SECItem item; - char *encoded; - char *history; + unsigned char *encoded = NULL; + char *history = NULL; int ret; - if (!gmtime_r(&hash_time, &utctime)) { - return NULL; - } + if (!gmtime_r(&hash_time, &utctime)) + goto cleanup; + strftime(timestr, GENERALIZED_TIME_LENGTH+1, "%Y%m%d%H%M%SZ", &utctime); - NSS_NoDB_Init("."); + encoded = (unsigned char *) malloc(4 * (hash_len * sizeof(*encoded) / 3) + 1); + if (!encoded) + goto cleanup; - item.type = siBuffer; - item.data = hash; - item.len = hash_len; - - encoded = NSSBase64_EncodeItem(NULL, NULL, 0, &item); - if (!encoded) { - return NULL; - } + ret = EVP_EncodeBlock(encoded, hash, hash_len); + if (ret < 1) + goto cleanup; ret = asprintf(&history, "%s%s%s", timestr, hash_type, encoded); if (ret == -1) { history = NULL; + goto cleanup; } - free(encoded); +cleanup: + if (encoded) + free(encoded); + return history; } diff --git a/util/ipa_pwd.h b/util/ipa_pwd.h index e0018a0..afe4fdf 100644 --- a/util/ipa_pwd.h +++ b/util/ipa_pwd.h @@ -61,7 +61,7 @@ struct ipapwd_policy { time_t ipapwd_gentime_to_time_t(char *timestr); int ipapwd_hash_password(char *password, - char *hash_type, + const char *hash_type, unsigned char *salt, unsigned char **full_hash, unsigned int *full_hash_len);