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