From: Dave Hart Date: Thu, 24 Aug 2023 14:06:05 +0000 (+0000) Subject: [Bug 3753] ntpd won't start with FIPS-enabled OpenSSL 3.x. X-Git-Tag: NTP_4_2_8P18_RC1~16^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4ce7c8108b3a6ea1586d8bd82a91afb0a8d85431;p=thirdparty%2Fntp.git [Bug 3753] ntpd won't start with FIPS-enabled OpenSSL 3.x. bk: 64e763cd0C_HD6Np7nPnpPnxoHTe2w --- diff --git a/ChangeLog b/ChangeLog index aa7444bda..e440aae2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -29,6 +29,7 @@ is disabled. * [Bug 3825] Don't touch HTML files unless building inside a BK repo. Fix the script checkHtmlFileDates. +* [Bug 3753] ntpd won't start with FIPS-enabled OpenSSL 3.x. * html/clockopt.html cleanup. * Add DSA, DSA-SHA, and SHA to tests/libntp/digests.c. diff --git a/include/ntp_md5.h b/include/ntp_md5.h index 8b5a7d0cb..c3d63a8da 100644 --- a/include/ntp_md5.h +++ b/include/ntp_md5.h @@ -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 */ diff --git a/include/ntp_stdlib.h b/include/ntp_stdlib.h index b44734cf0..8546d2fe0 100644 --- a/include/ntp_stdlib.h +++ b/include/ntp_stdlib.h @@ -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 /* + */ diff --git a/libntp/a_md5encrypt.c b/libntp/a_md5encrypt.c index 7a3729691..af4062d3c 100644 --- a/libntp/a_md5encrypt.c +++ b/libntp/a_md5encrypt.c @@ -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)); diff --git a/libntp/ssl_init.c b/libntp/ssl_init.c index dd66c78db..152fad073 100644 --- a/libntp/ssl_init.c +++ b/libntp/ssl_init.c @@ -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); } diff --git a/ntpd/ntp_crypto.c b/ntpd/ntp_crypto.c index 4a4207683..4f17957fc 100644 --- a/ntpd/ntp_crypto.c +++ b/ntpd/ntp_crypto.c @@ -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 diff --git a/ntpd/ntpd.c b/ntpd/ntpd.c index a47386d0d..09d2312b0 100644 --- a/ntpd/ntpd.c +++ b/ntpd/ntpd.c @@ -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.