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