1 /* $NetBSD: ssl_init.c,v 1.12 2018/09/29 21:52:33 christos Exp $ */ 2 3 /* 4 * ssl_init.c Common OpenSSL initialization code for the various 5 * programs which use it. 6 * 7 * Moved from ntpd/ntp_crypto.c crypto_setup() 8 */ 9 #ifdef HAVE_CONFIG_H 10 # include <config.h> 11 #endif 12 #include <ctype.h> 13 #include <ntp.h> 14 #include <ntp_debug.h> 15 #include <lib_strbuf.h> 16 17 #ifdef OPENSSL 18 # include <openssl/crypto.h> 19 # include <openssl/err.h> 20 # include <openssl/evp.h> 21 # include <openssl/opensslv.h> 22 # include "libssl_compat.h" 23 # ifdef HAVE_OPENSSL_CMAC_H 24 # include <openssl/cmac.h> 25 # define CMAC_LENGTH 16 26 # define CMAC "AES128CMAC" 27 # endif /*HAVE_OPENSSL_CMAC_H*/ 28 int ssl_init_done; 29 30 #if OPENSSL_VERSION_NUMBER < 0x10100000L 31 32 static void 33 atexit_ssl_cleanup(void) 34 { 35 if (!ssl_init_done) { 36 return; 37 } 38 39 ssl_init_done = FALSE; 40 EVP_cleanup(); 41 ERR_free_strings(); 42 } 43 44 void 45 ssl_init(void) 46 { 47 init_lib(); 48 49 if ( ! ssl_init_done) { 50 ERR_load_crypto_strings(); 51 OpenSSL_add_all_algorithms(); 52 atexit(&atexit_ssl_cleanup); 53 ssl_init_done = TRUE; 54 } 55 } 56 57 #else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ 58 59 void 60 ssl_init(void) 61 { 62 init_lib(); 63 ssl_init_done = TRUE; 64 } 65 66 #endif /* OPENSSL_VERSION_NUMBER */ 67 68 69 void 70 ssl_check_version(void) 71 { 72 u_long v; 73 74 v = OpenSSL_version_num(); 75 if ((v ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) { 76 msyslog(LOG_WARNING, 77 "OpenSSL version mismatch. Built against %lx, you have %lx", 78 (u_long)OPENSSL_VERSION_NUMBER, v); 79 fprintf(stderr, 80 "OpenSSL version mismatch. Built against %lx, you have %lx\n", 81 (u_long)OPENSSL_VERSION_NUMBER, v); 82 } 83 84 INIT_SSL(); 85 } 86 87 #else /* !OPENSSL */ 88 # define MD5_LENGTH 16 89 #endif /* OPENSSL */ 90 91 92 /* 93 * keytype_from_text returns OpenSSL NID for digest by name, and 94 * optionally the associated digest length. 95 * 96 * Used by ntpd authreadkeys(), ntpq and ntpdc keytype() 97 */ 98 int 99 keytype_from_text( 100 const char * text, 101 size_t * pdigest_len 102 ) 103 { 104 int key_type; 105 u_int digest_len; 106 #ifdef OPENSSL /* --*-- OpenSSL code --*-- */ 107 const u_long max_digest_len = MAX_MAC_LEN - sizeof(keyid_t); 108 char * upcased; 109 char * pch; 110 EVP_MD const * md; 111 112 /* 113 * OpenSSL digest short names are capitalized, so uppercase the 114 * digest name before passing to OBJ_sn2nid(). If it is not 115 * recognized but matches our CMAC string use NID_cmac, or if 116 * it begins with 'M' or 'm' use NID_md5 to be consistent with 117 * past behavior. 118 */ 119 INIT_SSL(); 120 121 /* get name in uppercase */ 122 LIB_GETBUF(upcased); 123 strlcpy(upcased, text, LIB_BUFLENGTH); 124 125 for (pch = upcased; '\0' != *pch; pch++) { 126 *pch = (char)toupper((unsigned char)*pch); 127 } 128 129 key_type = OBJ_sn2nid(upcased); 130 131 # ifdef ENABLE_CMAC 132 if (!key_type && !strncmp(CMAC, upcased, strlen(CMAC) + 1)) { 133 key_type = NID_cmac; 134 135 if (debug) { 136 fprintf(stderr, "%s:%d:%s():%s:key\n", 137 __FILE__, __LINE__, __func__, CMAC); 138 } 139 } 140 # endif /*ENABLE_CMAC*/ 141 #else 142 143 key_type = 0; 144 #endif 145 146 if (!key_type && 'm' == tolower((unsigned char)text[0])) { 147 key_type = NID_md5; 148 } 149 150 if (!key_type) { 151 return 0; 152 } 153 154 if (NULL != pdigest_len) { 155 #ifdef OPENSSL 156 md = EVP_get_digestbynid(key_type); 157 digest_len = (md) ? EVP_MD_size(md) : 0; 158 159 if (!md || digest_len <= 0) { 160 # ifdef ENABLE_CMAC 161 if (key_type == NID_cmac) { 162 digest_len = CMAC_LENGTH; 163 164 if (debug) { 165 fprintf(stderr, "%s:%d:%s():%s:len\n", 166 __FILE__, __LINE__, __func__, CMAC); 167 } 168 } else 169 # endif /*ENABLE_CMAC*/ 170 { 171 fprintf(stderr, 172 "key type %s is not supported by OpenSSL\n", 173 keytype_name(key_type)); 174 msyslog(LOG_ERR, 175 "key type %s is not supported by OpenSSL\n", 176 keytype_name(key_type)); 177 return 0; 178 } 179 } 180 181 if (digest_len > max_digest_len) { 182 fprintf(stderr, 183 "key type %s %u octet digests are too big, max %lu\n", 184 keytype_name(key_type), digest_len, 185 max_digest_len); 186 msyslog(LOG_ERR, 187 "key type %s %u octet digests are too big, max %lu", 188 keytype_name(key_type), digest_len, 189 max_digest_len); 190 return 0; 191 } 192 #else 193 digest_len = MD5_LENGTH; 194 #endif 195 *pdigest_len = digest_len; 196 } 197 198 return key_type; 199 } 200 201 202 /* 203 * keytype_name returns OpenSSL short name for digest by NID. 204 * 205 * Used by ntpq and ntpdc keytype() 206 */ 207 const char * 208 keytype_name( 209 int nid 210 ) 211 { 212 static const char unknown_type[] = "(unknown key type)"; 213 const char *name; 214 215 #ifdef OPENSSL 216 INIT_SSL(); 217 name = OBJ_nid2sn(nid); 218 219 # ifdef ENABLE_CMAC 220 if (NID_cmac == nid) { 221 name = CMAC; 222 223 if (debug) { 224 fprintf(stderr, "%s:%d:%s():%s:nid\n", 225 __FILE__, __LINE__, __func__, CMAC); 226 } 227 } else 228 # endif /*ENABLE_CMAC*/ 229 if (NULL == name) { 230 name = unknown_type; 231 } 232 #else /* !OPENSSL follows */ 233 if (NID_md5 == nid) 234 name = "MD5"; 235 else 236 name = unknown_type; 237 #endif 238 return name; 239 } 240 241 242 /* 243 * Use getpassphrase() if configure.ac detected it, as Suns that 244 * have it truncate the password in getpass() to 8 characters. 245 */ 246 #ifdef HAVE_GETPASSPHRASE 247 # define getpass(str) getpassphrase(str) 248 #endif 249 250 /* 251 * getpass_keytype() -- shared between ntpq and ntpdc, only vaguely 252 * related to the rest of ssl_init.c. 253 */ 254 char * 255 getpass_keytype( 256 int keytype 257 ) 258 { 259 char pass_prompt[64 + 11 + 1]; /* 11 for " Password: " */ 260 261 snprintf(pass_prompt, sizeof(pass_prompt), 262 "%.64s Password: ", keytype_name(keytype)); 263 264 return getpass(pass_prompt); 265 } 266 267