]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
hash: allow non-security MD5 use in FIPS mode
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 2 Sep 2021 09:44:15 +0000 (11:44 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 2 Sep 2021 13:17:08 +0000 (15:17 +0200)
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
hash_gnutls.c
hash_intmd5.c
hash_nettle.c
hash_nss.c
hash_tomcrypt.c
test/unit/hash.c
util.c

diff --git a/hash.h b/hash.h
index 290710f4c500b50a5315e14b329d6aedc31a47f3..39abf27cecd29987ead881b81184536459a74d6d 100644 (file)
--- 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);
index 5c77a226ac6c0d247ea82b9633b6432cd1537e99..269fdd8e76cab6f729914636b092df4a92e08cbf 100644 (file)
@@ -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;
index 4d101ea721c1887975799f6ed78ae0843029bb25..a64b7351cbf5b59383158e9745d52fd27698f725 100644 (file)
@@ -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;
index dba17171f7134faf5526aa0ac98fee7a0300186b..4a214f6ee51d5a006c09aa0b00903b452af3419f 100644 (file)
@@ -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;
index fe26627781663d0755ffcc697402566b6e70e960..4302447e4c17a4be02800d38a443d483ea33e782 100644 (file)
@@ -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;
index 5d126ca215565dc1836a4c37c9869c72860e1e31..9c425d2f5f49a775c6f7d97d08188db080859727 100644 (file)
@@ -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;
index d57c915ddf05494e8f7dfb2e9e78442b0c56dd7d..2f9ffef5a3bdf219894f937d87a3299a467883e5 100644 (file)
@@ -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 93d5ecb57047299ae57368f849d9b9973a03e8fc..2ae5deb3f6182296a72fb7dc9d6be4ff79e97971 100644 (file)
--- 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),