From 36441fabde4be126d6f3d3c2c5b84f212119667b Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 2 Sep 2021 11:44:15 +0200 Subject: [PATCH] hash: allow non-security MD5 use in FIPS mode gnutls running in the FIPS140-2 mode does not allow MD5 to be initialized, which breaks chronyd using MD5 to calculate reference ID of IPv6 addresses. Specify a new hash algorithm for non-security MD5 use and temporarily switch to the lax mode when initializing the hash function. --- hash.h | 1 + hash_gnutls.c | 8 ++++++++ hash_intmd5.c | 2 +- hash_nettle.c | 3 +++ hash_nss.c | 3 +++ hash_tomcrypt.c | 3 +++ test/unit/hash.c | 9 ++++++++- util.c | 2 +- 8 files changed, 28 insertions(+), 3 deletions(-) diff --git a/hash.h b/hash.h index 290710f..39abf27 100644 --- a/hash.h +++ b/hash.h @@ -44,6 +44,7 @@ typedef enum { HSH_SHA3_512 = 9, HSH_TIGER = 10, HSH_WHIRLPOOL = 11, + HSH_MD5_NONCRYPTO = 10000, /* For NTPv4 reference ID */ } HSH_Algorithm; extern int HSH_GetHashId(HSH_Algorithm algorithm); diff --git a/hash_gnutls.c b/hash_gnutls.c index 5c77a22..269fdd8 100644 --- a/hash_gnutls.c +++ b/hash_gnutls.c @@ -40,6 +40,7 @@ struct hash { }; static struct hash hashes[] = { + { HSH_MD5_NONCRYPTO, GNUTLS_DIG_MD5, NULL }, { HSH_MD5, GNUTLS_DIG_MD5, NULL }, { HSH_SHA1, GNUTLS_DIG_SHA1, NULL }, { HSH_SHA256, GNUTLS_DIG_SHA256, NULL }, @@ -77,7 +78,14 @@ HSH_GetHashId(HSH_Algorithm algorithm) if (hashes[id].handle) return id; + if (algorithm == HSH_MD5_NONCRYPTO) + GNUTLS_FIPS140_SET_LAX_MODE(); + r = gnutls_hash_init(&hashes[id].handle, hashes[id].type); + + if (algorithm == HSH_MD5_NONCRYPTO) + GNUTLS_FIPS140_SET_STRICT_MODE(); + if (r < 0) { DEBUG_LOG("Could not initialise %s : %s", "hash", gnutls_strerror(r)); hashes[id].handle = NULL; diff --git a/hash_intmd5.c b/hash_intmd5.c index 4d101ea..a64b735 100644 --- a/hash_intmd5.c +++ b/hash_intmd5.c @@ -39,7 +39,7 @@ int HSH_GetHashId(HSH_Algorithm algorithm) { /* only MD5 is supported */ - if (algorithm != HSH_MD5) + if (algorithm != HSH_MD5 && algorithm != HSH_MD5_NONCRYPTO) return -1; return 0; diff --git a/hash_nettle.c b/hash_nettle.c index dba1717..4a214f6 100644 --- a/hash_nettle.c +++ b/hash_nettle.c @@ -59,6 +59,9 @@ HSH_GetHashId(HSH_Algorithm algorithm) { int id, nid; + if (algorithm == HSH_MD5_NONCRYPTO) + algorithm = HSH_MD5; + for (id = 0; hashes[id].algorithm != 0; id++) { if (hashes[id].algorithm == algorithm) break; diff --git a/hash_nss.c b/hash_nss.c index fe26627..4302447 100644 --- a/hash_nss.c +++ b/hash_nss.c @@ -56,6 +56,9 @@ HSH_GetHashId(HSH_Algorithm algorithm) { int i; + if (algorithm == HSH_MD5_NONCRYPTO) + algorithm = HSH_MD5; + for (i = 0; hashes[i].algorithm != 0; i++) { if (hashes[i].algorithm == algorithm) break; diff --git a/hash_tomcrypt.c b/hash_tomcrypt.c index 5d126ca..9c425d2 100644 --- a/hash_tomcrypt.c +++ b/hash_tomcrypt.c @@ -71,6 +71,9 @@ HSH_GetHashId(HSH_Algorithm algorithm) { int i, h; + if (algorithm == HSH_MD5_NONCRYPTO) + algorithm = HSH_MD5; + for (i = 0; hashes[i].algorithm != 0; i++) { if (hashes[i].algorithm == algorithm) break; diff --git a/test/unit/hash.c b/test/unit/hash.c index d57c915..2f9ffef 100644 --- a/test/unit/hash.c +++ b/test/unit/hash.c @@ -38,6 +38,7 @@ test_unit(void) unsigned char data2[] = "12345678910"; unsigned char out[MAX_HASH_LENGTH]; struct hash_test tests[] = { + { "MD5-NC", "\xfc\x24\x97\x1b\x52\x66\xdc\x46\xef\xe0\xe8\x08\x46\x89\xb6\x88", 16 }, { "MD5", "\xfc\x24\x97\x1b\x52\x66\xdc\x46\xef\xe0\xe8\x08\x46\x89\xb6\x88", 16 }, { "SHA1", "\xd8\x85\xb3\x86\xce\xea\x93\xeb\x92\xcd\x7b\x94\xb9\x8d\xc2\x8e" "\x3e\x31\x13\xdd", 20}, @@ -77,9 +78,15 @@ test_unit(void) for (i = 0; tests[i].name[0] != '\0'; i++) { algorithm = UTI_HashNameToAlgorithm(tests[i].name); - TEST_CHECK(algorithm != 0); + if (strcmp(tests[i].name, "MD5-NC") == 0) { + TEST_CHECK(algorithm == 0); + algorithm = HSH_MD5_NONCRYPTO; + } else { + TEST_CHECK(algorithm != 0); + } hash_id = HSH_GetHashId(algorithm); if (hash_id < 0) { + TEST_CHECK(algorithm != HSH_MD5_NONCRYPTO); TEST_CHECK(algorithm != HSH_MD5); #ifdef FEAT_SECHASH TEST_CHECK(algorithm != HSH_SHA1); diff --git a/util.c b/util.c index 93d5ecb..2ae5deb 100644 --- a/util.c +++ b/util.c @@ -400,7 +400,7 @@ UTI_IPToRefid(const IPAddr *ip) return ip->addr.in4; case IPADDR_INET6: if (MD5_hash < 0) - MD5_hash = HSH_GetHashId(HSH_MD5); + MD5_hash = HSH_GetHashId(HSH_MD5_NONCRYPTO); if (MD5_hash < 0 || HSH_Hash(MD5_hash, (const unsigned char *)ip->addr.in6, sizeof (ip->addr.in6),