]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 3753] ntpd won't start with FIPS-enabled OpenSSL 3.x.
authorDave Hart <hart@ntp.org>
Thu, 24 Aug 2023 14:06:05 +0000 (14:06 +0000)
committerDave Hart <hart@ntp.org>
Thu, 24 Aug 2023 14:06:05 +0000 (14:06 +0000)
bk: 64e763cd0C_HD6Np7nPnpPnxoHTe2w

ChangeLog
include/ntp_md5.h
include/ntp_stdlib.h
libntp/a_md5encrypt.c
libntp/ssl_init.c
ntpd/ntp_crypto.c
ntpd/ntpd.c

index aa7444bda81a54e8b9063c2ba0f1f87c4bb8f3d3..e440aae2e204581c2adfa6810750580b2a57aa17 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -29,6 +29,7 @@
              is disabled.  <burnicki@ntp.org>
 * [Bug 3825] Don't touch HTML files unless building inside a BK repo.
              Fix the script checkHtmlFileDates.  <burnicki@ntp.org>
+* [Bug 3753] ntpd won't start with FIPS-enabled OpenSSL 3.x. <hart@ntp.org>
 * html/clockopt.html cleanup.  <stenn@ntp.org>
 * Add DSA, DSA-SHA, and SHA to tests/libntp/digests.c. <hart@ntp.org>
 
index 8b5a7d0cbb49604dde0ff0bad19403f627e0b9cb..c3d63a8da146a36b46a8310e3b6028499204a703 100644 (file)
@@ -33,7 +33,8 @@
   typedef MD5_CTX                      EVP_MD_CTX;
 
 # define NID_md5                       4       /* from openssl/objects.h */
-# define EVP_MAX_MD_SIZE               64      /* from openssl/evp.h */
+# define MD5_LENGTH                    16
+# define EVP_MAX_MD_SIZE               MD5_LENGTH
 # define EVP_MD_CTX_free(c)            free(c)
 # define EVP_MD_CTX_new()              calloc(1, sizeof(MD5_CTX))
 # define EVP_get_digestbynid(t)                NULL
@@ -47,7 +48,7 @@
 # define EVP_DigestFinal(c, d, pdl)    \
        do {                            \
                MD5Final((d), (c));     \
-               *(pdl) = 16;            \
+               *(pdl) = MD5_LENGTH;    \
        } while (0)
 # endif        /* !OPENSSL */
 #endif /* NTP_MD5_H */
index b44734cf05592069cf16f088d7fb820e0d6598e4..8546d2fe049fddc262fe9974a4841c00bb17271c 100644 (file)
@@ -250,11 +250,13 @@ extern    int     ssl_init_done;
                        ssl_init();             \
        } while (0)
 #else  /* !OPENSSL follows */
+#define ssl_check_version()    do {} while (0)
 #define        INIT_SSL()              do {} while (0)
 #endif
-extern int     keytype_from_text       (const char *,  size_t *);
-extern const char *keytype_name        (int);
-extern char *  getpass_keytype         (int);
+extern int     keytype_from_text       (const char *text,
+                                        size_t *pdigest_len);
+extern const char *keytype_name        (int type);
+extern char *  getpass_keytype         (int type);
 
 /* strl-obsd.c */
 #ifndef HAVE_STRLCPY           /* + */
index 7a372969123fd584ed3d1ecf2a8969dd198a35a2..af4062d3c237621f18ed660dd6c0f0d07a226e20 100644 (file)
@@ -40,6 +40,60 @@ cmac_ctx_size(
 #endif /* OPENSSL && ENABLE_CMAC */
 
 
+static EVP_MD_CTX *
+get_md_ctx(
+       int             type,
+       int/*BOOL*/     for_auth
+       )
+{
+#ifndef OPENSSL
+       return emalloc(sizeof(MD5_CTX));
+#else
+       EVP_MD_CTX *    ctx;
+#  if OPENSSL_VERSION_NUMBER >= 0x30000000L
+       EVP_MD *        md;
+#  endif
+       const char *    md_name;
+
+       ctx = EVP_MD_CTX_new();
+       md_name = OBJ_nid2sn(type);
+
+#  if OPENSSL_VERSION_NUMBER >= 0x30000000L
+       /*
+        * See section FIPS Provider:
+        * https://www.openssl.org/docs/man3.0/man7/crypto.html
+        * for property query strings
+        */
+       if (!for_auth && NID_md5 == type) {
+               md = EVP_MD_fetch(NULL, md_name, "fips=no");
+       } else {
+               md = EVP_MD_fetch(NULL, md_name, "");
+       }
+       if (NULL == md) {
+               msyslog(LOG_ERR, "Could not load digest %s", md_name);
+               exit(1);
+       }
+       if (!EVP_DigestInit_ex(ctx, md, NULL)) {
+               msyslog(LOG_ERR, "%s init failed", md_name);
+               exit(1);
+       }
+       EVP_MD_free(md);
+#  else        /* OPENSSL_VERSION_NUMBER < 0x30000000L follows */
+#    ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
+       if (!for_auth && NID_md5 == type) {
+               EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+       }
+#    endif
+       if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(type), NULL)) {
+               msyslog(LOG_ERR, "%s init failed", md_name);
+               exit(1);
+       }
+#  endif       /* OPENSSL_VERSION_NUMBER */
+       return ctx;
+#endif /* OPENSSL */
+}
+
+
 static size_t
 make_mac(
        const rwbuffT * digest,
@@ -99,26 +153,13 @@ make_mac(
                        CMAC_CTX_free(ctx);
        }
        else
-#   endif /*ENABLE_CMAC*/
+#   endif /* ENABLE_CMAC */
        {       /* generic MAC handling */
-               EVP_MD_CTX *    ctx   = EVP_MD_CTX_new();
+               EVP_MD_CTX *    ctx;
                u_int           uilen = 0;
 
-               if ( ! ctx) {
-                       msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest CTX new failed.",
-                               OBJ_nid2sn(ktype));
-                       goto mac_fail;
-               }
-
-          #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
-               /* make sure MD5 is allowd */
-               EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
-          #endif
-               /* [Bug 3457] DON'T use plain EVP_DigestInit! It would
-                * kill the flags! */
-               if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(ktype), NULL)) {
-                       msyslog(LOG_ERR, "MAC encrypt: MAC %s Digest Init failed.",
-                               OBJ_nid2sn(ktype));
+               ctx = get_md_ctx(ktype, TRUE);
+               if (NULL == ctx) {
                        goto mac_fail;
                }
                if ((size_t)EVP_MD_CTX_size(ctx) > digest->len) {
@@ -150,32 +191,23 @@ make_mac(
 
 #else /* !OPENSSL follows */
 
-       if (ktype == NID_md5)
-       {
-               EVP_MD_CTX *    ctx   = EVP_MD_CTX_new();
-               u_int           uilen = 0;
+       if (NID_md5 == ktype) {
+               EVP_MD_CTX *    ctx = emalloc(sizeof(MD5_CTX));
+               size_t          len = 0;
 
-               if (digest->len < 16) {
+               if (digest->len < MD5_LENGTH) {
                        msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 buf too small.");
+               } else {
+                       MD5Init(ctx);
+                       MD5Update(ctx, (const void *)key->buf, key->len);
+                       MD5Update(ctx, (const void *)msg->buf, msg->len);
+                       MD5Final(digest->buf, ctx);
+                       len = MD5_LENGTH;
                }
-               else if ( ! ctx) {
-                       msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 Digest CTX new failed.");
-               }
-               else if (!EVP_DigestInit(ctx, EVP_get_digestbynid(ktype))) {
-                       msyslog(LOG_ERR, "%s", "MAC encrypt: MAC md5 Digest INIT failed.");
-               }
-               else {
-                       EVP_DigestUpdate(ctx, key->buf, key->len);
-                       EVP_DigestUpdate(ctx, msg->buf, msg->len);
-                       EVP_DigestFinal(ctx, digest->buf, &uilen);
-               }
-               if (ctx)
-                       EVP_MD_CTX_free(ctx);
-               retlen = (size_t)uilen;
-       }
-       else
-       {
-               msyslog(LOG_ERR, "MAC encrypt: invalid key type %d"  , ktype);
+               free(ctx);
+               retlen = len;
+       } else {
+               msyslog(LOG_ERR, "MAC encrypt: invalid key type %d", ktype);
        }
 
 #endif /* !OPENSSL */
@@ -261,30 +293,17 @@ addr2refid(sockaddr_u *addr)
 {
        u_char          digest[EVP_MAX_MD_SIZE];
        u_int32         addr_refid;
-       EVP_MD_CTX      *ctx;
+       EVP_MD_CTX *    ctx;
        u_int           len;
 
-       if (IS_IPV4(addr))
+       if (IS_IPV4(addr)) {
                return (NSRCADR(addr));
-
-       INIT_SSL();
-
-       ctx = EVP_MD_CTX_new();
-#   ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
-       /* MD5 is not used as a crypto hash here. */
-       EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
-#   endif
-       /* [Bug 3457] DON'T use plain EVP_DigestInit! It would kill the
-        * flags! */
-       if (!EVP_DigestInit_ex(ctx, EVP_md5(), NULL)) {
-               msyslog(LOG_ERR,
-                   "MD5 init failed");
-               EVP_MD_CTX_free(ctx);   /* pedantic... but safe */
-               exit(1);
        }
-
-       EVP_DigestUpdate(ctx, (u_char *)PSOCK_ADDR6(addr),
-           sizeof(struct in6_addr));
+       INIT_SSL();
+       /* MD5 is not used for authentication here. */
+       ctx = get_md_ctx(NID_md5, FALSE);
+       EVP_DigestUpdate(ctx, (u_char *)&SOCK_ADDR6(addr),
+                        sizeof(SOCK_ADDR6(addr)));
        EVP_DigestFinal(ctx, digest, &len);
        EVP_MD_CTX_free(ctx);
        memcpy(&addr_refid, digest, sizeof(addr_refid));
index dd66c78db52889482c5c7426e33f1089b712e059..152fad07333c3cf7b48e1dbb8c4b6727c5ef2660 100644 (file)
@@ -26,7 +26,6 @@
 int ssl_init_done;
 
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
-
 static void
 atexit_ssl_cleanup(void)
 {
@@ -38,6 +37,7 @@ atexit_ssl_cleanup(void)
        EVP_cleanup();
        ERR_free_strings();
 }
+#endif /* OpenSSL < 1.1 */
 
 void
 ssl_init(void)
@@ -45,40 +45,32 @@ ssl_init(void)
        init_lib();
 
        if ( ! ssl_init_done) {
-           ERR_load_crypto_strings();
-           OpenSSL_add_all_algorithms();
-           atexit(&atexit_ssl_cleanup);
-           ssl_init_done = TRUE;
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+               ERR_load_crypto_strings();
+               OpenSSL_add_all_algorithms();
+               atexit(&atexit_ssl_cleanup);
+#endif /* OpenSSL < 1.1 */
+               ssl_init_done = TRUE;
        }
 }
 
-#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
-
-void
-ssl_init(void)
-{
-       init_lib();
-       ssl_init_done = TRUE;
-}
-
-#endif /* OPENSSL_VERSION_NUMBER */
-
 
 void
 ssl_check_version(void)
 {
        u_long  v;
+       char *  buf;
 
        v = OpenSSL_version_num();
        if ((v ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) {
-               msyslog(LOG_WARNING,
-                   "OpenSSL version mismatch. Built against %lx, you have %lx",
-                   (u_long)OPENSSL_VERSION_NUMBER, v);
-               fprintf(stderr,
-                   "OpenSSL version mismatch. Built against %lx, you have %lx\n",
-                   (u_long)OPENSSL_VERSION_NUMBER, v);
+               LIB_GETBUF(buf);
+               snprintf(buf, LIB_BUFLENGTH, 
+                        "OpenSSL version mismatch."
+                        "Built against %lx, you have %lx\n",
+                        (u_long)OPENSSL_VERSION_NUMBER, v);
+               msyslog(LOG_WARNING, "%s", buf);
+               fputs(buf, stderr);
        }
-
        INIT_SSL();
 }
 
@@ -204,7 +196,7 @@ keytype_from_text(
  */
 const char *
 keytype_name(
-       int nid
+       int type
        )
 {
        static const char unknown_type[] = "(unknown key type)";
@@ -212,10 +204,10 @@ keytype_name(
 
 #ifdef OPENSSL
        INIT_SSL();
-       name = OBJ_nid2sn(nid);
+       name = OBJ_nid2sn(type);
 
 #   ifdef ENABLE_CMAC
-       if (NID_cmac == nid) {
+       if (NID_cmac == type) {
                name = CMAC;
        } else
 #   endif /*ENABLE_CMAC*/
@@ -223,7 +215,7 @@ keytype_name(
                name = unknown_type;
        }
 #else  /* !OPENSSL follows */
-       if (NID_md5 == nid)
+       if (NID_md5 == type)
                name = "MD5";
        else
                name = unknown_type;
@@ -246,13 +238,13 @@ keytype_name(
  */
 char *
 getpass_keytype(
-       int     keytype
+       int     type
        )
 {
        char    pass_prompt[64 + 11 + 1]; /* 11 for " Password: " */
 
        snprintf(pass_prompt, sizeof(pass_prompt),
-                "%.64s Password: ", keytype_name(keytype));
+                "%.64s Password: ", keytype_name(type));
 
        return getpass(pass_prompt);
 }
index 4a4207683331eebc007872d8605649f050cbf755..4f17957fca748cd159aab7b8066f060c89242ead 100644 (file)
@@ -3909,7 +3909,6 @@ crypto_setup(void)
                    "crypto_setup: spurious crypto command");
                return;
        }
-       ssl_check_version();
 
        /*
         * Load required random seed file and seed the random number
index a47386d0dfe9a23ece5f27c41117f0b2066b0a69..09d2312b0541ae142c84e6ecdf95c6af05224a4b 100644 (file)
@@ -913,10 +913,13 @@ ntpdmain(
        msyslog(LOG_NOTICE, "available at https://www.nwtime.org/support");
        msyslog(LOG_NOTICE, "----------------------------------------------------");
 #ifdef DEBUG
-       msyslog(LOG_NOTICE, "DEBUG behavior is enabled - a violation of any");
-       msyslog(LOG_NOTICE, "diagnostic assertion will cause %s to abort", progname);
+       msyslog(LOG_NOTICE, "DEBUG behavior is enabled - a violation of any"
+                           " diagnostic assertion will cause %s to abort", 
+                           progname);
 #endif
 
+       ssl_check_version();
+
        /*
         * Install trap handlers to log errors and assertion failures.
         * Default handlers print to stderr which doesn't work if detached.