1*eabc0478Schristos /* $NetBSD: ssl_init.c,v 1.14 2024/08/18 20:47:13 christos Exp $ */ 2abb0f93cSkardel 3abb0f93cSkardel /* 4abb0f93cSkardel * ssl_init.c Common OpenSSL initialization code for the various 5abb0f93cSkardel * programs which use it. 6abb0f93cSkardel * 7abb0f93cSkardel * Moved from ntpd/ntp_crypto.c crypto_setup() 8abb0f93cSkardel */ 9abb0f93cSkardel #ifdef HAVE_CONFIG_H 10abb0f93cSkardel # include <config.h> 11abb0f93cSkardel #endif 12abb0f93cSkardel #include <ctype.h> 13abb0f93cSkardel #include <ntp.h> 14abb0f93cSkardel #include <ntp_debug.h> 15abb0f93cSkardel #include <lib_strbuf.h> 16abb0f93cSkardel 17abb0f93cSkardel #ifdef OPENSSL 1879045f13Schristos # include <openssl/crypto.h> 1979045f13Schristos # include <openssl/err.h> 2079045f13Schristos # include <openssl/evp.h> 2179045f13Schristos # include <openssl/opensslv.h> 2203cfe0ffSchristos # include "libssl_compat.h" 2379045f13Schristos # ifdef HAVE_OPENSSL_CMAC_H 2479045f13Schristos # include <openssl/cmac.h> 254eea345dSchristos # define CMAC_LENGTH 16 264eea345dSchristos # define CMAC "AES128CMAC" 2779045f13Schristos # endif /*HAVE_OPENSSL_CMAC_H*/ 28abb0f93cSkardel 29*eabc0478Schristos EVP_MD_CTX *digest_ctx; 30*eabc0478Schristos 312950cc38Schristos 32ccc794f0Schristos static void 332950cc38Schristos atexit_ssl_cleanup(void) 342950cc38Schristos { 35*eabc0478Schristos if (NULL == digest_ctx) { 362950cc38Schristos return; 374eea345dSchristos } 38*eabc0478Schristos EVP_MD_CTX_free(digest_ctx); 39*eabc0478Schristos digest_ctx = NULL; 40*eabc0478Schristos #if OPENSSL_VERSION_NUMBER < 0x10100000L 412950cc38Schristos EVP_cleanup(); 422950cc38Schristos ERR_free_strings(); 43*eabc0478Schristos #endif /* OpenSSL < 1.1 */ 44abb0f93cSkardel } 45abb0f93cSkardel 46*eabc0478Schristos 47ccc794f0Schristos void 48ccc794f0Schristos ssl_init(void) 49ccc794f0Schristos { 50ccc794f0Schristos init_lib(); 51ccc794f0Schristos 52*eabc0478Schristos if (NULL == digest_ctx) { 53*eabc0478Schristos #if OPENSSL_VERSION_NUMBER < 0x10100000L 54ccc794f0Schristos ERR_load_crypto_strings(); 55ccc794f0Schristos OpenSSL_add_all_algorithms(); 56*eabc0478Schristos #endif /* OpenSSL < 1.1 */ 57*eabc0478Schristos digest_ctx = EVP_MD_CTX_new(); 58*eabc0478Schristos INSIST(digest_ctx != NULL); 59ccc794f0Schristos atexit(&atexit_ssl_cleanup); 60ccc794f0Schristos } 61ccc794f0Schristos } 62ccc794f0Schristos 63abb0f93cSkardel 64abb0f93cSkardel void 65abb0f93cSkardel ssl_check_version(void) 66abb0f93cSkardel { 67ccc794f0Schristos u_long v; 68*eabc0478Schristos char * buf; 69ccc794f0Schristos 70ccc794f0Schristos v = OpenSSL_version_num(); 71ccc794f0Schristos if ((v ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) { 72*eabc0478Schristos LIB_GETBUF(buf); 73*eabc0478Schristos snprintf(buf, LIB_BUFLENGTH, 74*eabc0478Schristos "OpenSSL version mismatch." 75*eabc0478Schristos "Built against %lx, you have %lx\n", 76ccc794f0Schristos (u_long)OPENSSL_VERSION_NUMBER, v); 77*eabc0478Schristos msyslog(LOG_WARNING, "%s", buf); 78*eabc0478Schristos fputs(buf, stderr); 79abb0f93cSkardel } 80abb0f93cSkardel INIT_SSL(); 81abb0f93cSkardel } 82abb0f93cSkardel #endif /* OPENSSL */ 83abb0f93cSkardel 84abb0f93cSkardel 85abb0f93cSkardel /* 86abb0f93cSkardel * keytype_from_text returns OpenSSL NID for digest by name, and 87abb0f93cSkardel * optionally the associated digest length. 88abb0f93cSkardel * 89abb0f93cSkardel * Used by ntpd authreadkeys(), ntpq and ntpdc keytype() 90abb0f93cSkardel */ 91abb0f93cSkardel int 92abb0f93cSkardel keytype_from_text( 93abb0f93cSkardel const char * text, 94abb0f93cSkardel size_t * pdigest_len 95abb0f93cSkardel ) 96abb0f93cSkardel { 97abb0f93cSkardel int key_type; 98abb0f93cSkardel u_int digest_len; 994eea345dSchristos #ifdef OPENSSL /* --*-- OpenSSL code --*-- */ 100*eabc0478Schristos const u_long max_digest_len = MAX_MDG_LEN; 101abb0f93cSkardel char * upcased; 102abb0f93cSkardel char * pch; 1034eea345dSchristos EVP_MD const * md; 104abb0f93cSkardel 105abb0f93cSkardel /* 106abb0f93cSkardel * OpenSSL digest short names are capitalized, so uppercase the 107abb0f93cSkardel * digest name before passing to OBJ_sn2nid(). If it is not 1084eea345dSchristos * recognized but matches our CMAC string use NID_cmac, or if 1094eea345dSchristos * it begins with 'M' or 'm' use NID_md5 to be consistent with 1104eea345dSchristos * past behavior. 111abb0f93cSkardel */ 112abb0f93cSkardel INIT_SSL(); 1134eea345dSchristos 1144eea345dSchristos /* get name in uppercase */ 115abb0f93cSkardel LIB_GETBUF(upcased); 1162950cc38Schristos strlcpy(upcased, text, LIB_BUFLENGTH); 1174eea345dSchristos 1184eea345dSchristos for (pch = upcased; '\0' != *pch; pch++) { 119e19314b7Schristos *pch = (char)toupper((unsigned char)*pch); 1204eea345dSchristos } 1214eea345dSchristos 122abb0f93cSkardel key_type = OBJ_sn2nid(upcased); 1234eea345dSchristos 12479045f13Schristos # ifdef ENABLE_CMAC 1254eea345dSchristos if (!key_type && !strncmp(CMAC, upcased, strlen(CMAC) + 1)) { 1264eea345dSchristos key_type = NID_cmac; 1274eea345dSchristos 1284eea345dSchristos if (debug) { 1294eea345dSchristos fprintf(stderr, "%s:%d:%s():%s:key\n", 1304eea345dSchristos __FILE__, __LINE__, __func__, CMAC); 1314eea345dSchristos } 1324eea345dSchristos } 13379045f13Schristos # endif /*ENABLE_CMAC*/ 134abb0f93cSkardel #else 1354eea345dSchristos 136abb0f93cSkardel key_type = 0; 137abb0f93cSkardel #endif 138abb0f93cSkardel 1394eea345dSchristos if (!key_type && 'm' == tolower((unsigned char)text[0])) { 140abb0f93cSkardel key_type = NID_md5; 1414eea345dSchristos } 142abb0f93cSkardel 1434eea345dSchristos if (!key_type) { 144abb0f93cSkardel return 0; 1454eea345dSchristos } 146abb0f93cSkardel 147abb0f93cSkardel if (NULL != pdigest_len) { 148abb0f93cSkardel #ifdef OPENSSL 1494eea345dSchristos md = EVP_get_digestbynid(key_type); 1504eea345dSchristos digest_len = (md) ? EVP_MD_size(md) : 0; 15103cfe0ffSchristos 1524eea345dSchristos if (!md || digest_len <= 0) { 15379045f13Schristos # ifdef ENABLE_CMAC 1544eea345dSchristos if (key_type == NID_cmac) { 1554eea345dSchristos digest_len = CMAC_LENGTH; 1564eea345dSchristos 1574eea345dSchristos if (debug) { 1584eea345dSchristos fprintf(stderr, "%s:%d:%s():%s:len\n", 1594eea345dSchristos __FILE__, __LINE__, __func__, CMAC); 1604eea345dSchristos } 16179045f13Schristos } else 16279045f13Schristos # endif /*ENABLE_CMAC*/ 16379045f13Schristos { 1644eea345dSchristos fprintf(stderr, 1654eea345dSchristos "key type %s is not supported by OpenSSL\n", 1664eea345dSchristos keytype_name(key_type)); 1674eea345dSchristos msyslog(LOG_ERR, 1684eea345dSchristos "key type %s is not supported by OpenSSL\n", 1694eea345dSchristos keytype_name(key_type)); 1704eea345dSchristos return 0; 1714eea345dSchristos } 1724eea345dSchristos } 1734eea345dSchristos 1742950cc38Schristos if (digest_len > max_digest_len) { 175abb0f93cSkardel fprintf(stderr, 1763123f114Skardel "key type %s %u octet digests are too big, max %lu\n", 177abb0f93cSkardel keytype_name(key_type), digest_len, 1783123f114Skardel max_digest_len); 179abb0f93cSkardel msyslog(LOG_ERR, 1802950cc38Schristos "key type %s %u octet digests are too big, max %lu", 181abb0f93cSkardel keytype_name(key_type), digest_len, 1823123f114Skardel max_digest_len); 183abb0f93cSkardel return 0; 184abb0f93cSkardel } 185abb0f93cSkardel #else 1864eea345dSchristos digest_len = MD5_LENGTH; 187abb0f93cSkardel #endif 188abb0f93cSkardel *pdigest_len = digest_len; 189abb0f93cSkardel } 190abb0f93cSkardel 191abb0f93cSkardel return key_type; 192abb0f93cSkardel } 193abb0f93cSkardel 194abb0f93cSkardel 195abb0f93cSkardel /* 196abb0f93cSkardel * keytype_name returns OpenSSL short name for digest by NID. 197abb0f93cSkardel * 198abb0f93cSkardel * Used by ntpq and ntpdc keytype() 199abb0f93cSkardel */ 200abb0f93cSkardel const char * 201abb0f93cSkardel keytype_name( 202*eabc0478Schristos int type 203abb0f93cSkardel ) 204abb0f93cSkardel { 205abb0f93cSkardel static const char unknown_type[] = "(unknown key type)"; 206abb0f93cSkardel const char *name; 207abb0f93cSkardel 208abb0f93cSkardel #ifdef OPENSSL 209abb0f93cSkardel INIT_SSL(); 210*eabc0478Schristos name = OBJ_nid2sn(type); 2114eea345dSchristos 21279045f13Schristos # ifdef ENABLE_CMAC 213*eabc0478Schristos if (NID_cmac == type) { 2144eea345dSchristos name = CMAC; 2154eea345dSchristos } else 21679045f13Schristos # endif /*ENABLE_CMAC*/ 2174eea345dSchristos if (NULL == name) { 218abb0f93cSkardel name = unknown_type; 2194eea345dSchristos } 220abb0f93cSkardel #else /* !OPENSSL follows */ 221*eabc0478Schristos if (NID_md5 == type) 222abb0f93cSkardel name = "MD5"; 223abb0f93cSkardel else 224abb0f93cSkardel name = unknown_type; 225abb0f93cSkardel #endif 226abb0f93cSkardel return name; 227abb0f93cSkardel } 228abb0f93cSkardel 2293123f114Skardel 2303123f114Skardel /* 2313123f114Skardel * Use getpassphrase() if configure.ac detected it, as Suns that 2323123f114Skardel * have it truncate the password in getpass() to 8 characters. 2333123f114Skardel */ 2343123f114Skardel #ifdef HAVE_GETPASSPHRASE 2353123f114Skardel # define getpass(str) getpassphrase(str) 2363123f114Skardel #endif 2373123f114Skardel 2383123f114Skardel /* 2393123f114Skardel * getpass_keytype() -- shared between ntpq and ntpdc, only vaguely 2403123f114Skardel * related to the rest of ssl_init.c. 2413123f114Skardel */ 2423123f114Skardel char * 2433123f114Skardel getpass_keytype( 244*eabc0478Schristos int type 2453123f114Skardel ) 2463123f114Skardel { 2473123f114Skardel char pass_prompt[64 + 11 + 1]; /* 11 for " Password: " */ 2483123f114Skardel 2493123f114Skardel snprintf(pass_prompt, sizeof(pass_prompt), 250*eabc0478Schristos "%.64s Password: ", keytype_name(type)); 2513123f114Skardel 2523123f114Skardel return getpass(pass_prompt); 2533123f114Skardel } 2544eea345dSchristos 255