1 /* $NetBSD: ssl_init.c,v 1.10 2017/04/13 20:17:42 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 24 int ssl_init_done; 25 26 #if OPENSSL_VERSION_NUMBER < 0x10100000L 27 28 static void 29 atexit_ssl_cleanup(void) 30 { 31 if (!ssl_init_done) 32 return; 33 34 ssl_init_done = FALSE; 35 EVP_cleanup(); 36 ERR_free_strings(); 37 } 38 39 void 40 ssl_init(void) 41 { 42 init_lib(); 43 44 if ( ! ssl_init_done) { 45 ERR_load_crypto_strings(); 46 OpenSSL_add_all_algorithms(); 47 atexit(&atexit_ssl_cleanup); 48 ssl_init_done = TRUE; 49 } 50 } 51 52 #else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ 53 54 void 55 ssl_init(void) 56 { 57 init_lib(); 58 ssl_init_done = TRUE; 59 } 60 61 #endif /* OPENSSL_VERSION_NUMBER */ 62 63 64 void 65 ssl_check_version(void) 66 { 67 u_long v; 68 69 v = OpenSSL_version_num(); 70 if ((v ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) { 71 msyslog(LOG_WARNING, 72 "OpenSSL version mismatch. Built against %lx, you have %lx", 73 (u_long)OPENSSL_VERSION_NUMBER, v); 74 fprintf(stderr, 75 "OpenSSL version mismatch. Built against %lx, you have %lx\n", 76 (u_long)OPENSSL_VERSION_NUMBER, v); 77 } 78 79 INIT_SSL(); 80 } 81 82 #endif /* OPENSSL */ 83 84 85 /* 86 * keytype_from_text returns OpenSSL NID for digest by name, and 87 * optionally the associated digest length. 88 * 89 * Used by ntpd authreadkeys(), ntpq and ntpdc keytype() 90 */ 91 int 92 keytype_from_text( 93 const char *text, 94 size_t *pdigest_len 95 ) 96 { 97 int key_type; 98 u_int digest_len; 99 #ifdef OPENSSL 100 const u_long max_digest_len = MAX_MAC_LEN - sizeof(keyid_t); 101 u_char digest[EVP_MAX_MD_SIZE]; 102 char * upcased; 103 char * pch; 104 105 /* 106 * OpenSSL digest short names are capitalized, so uppercase the 107 * digest name before passing to OBJ_sn2nid(). If it is not 108 * recognized but begins with 'M' use NID_md5 to be consistent 109 * with past behavior. 110 */ 111 INIT_SSL(); 112 LIB_GETBUF(upcased); 113 strlcpy(upcased, text, LIB_BUFLENGTH); 114 for (pch = upcased; '\0' != *pch; pch++) 115 *pch = (char)toupper((unsigned char)*pch); 116 key_type = OBJ_sn2nid(upcased); 117 #else 118 key_type = 0; 119 #endif 120 121 if (!key_type && 'm' == tolower((unsigned char)text[0])) 122 key_type = NID_md5; 123 124 if (!key_type) 125 return 0; 126 127 if (NULL != pdigest_len) { 128 #ifdef OPENSSL 129 EVP_MD_CTX *ctx; 130 131 ctx = EVP_MD_CTX_new(); 132 EVP_DigestInit(ctx, EVP_get_digestbynid(key_type)); 133 EVP_DigestFinal(ctx, digest, &digest_len); 134 EVP_MD_CTX_free(ctx); 135 if (digest_len > max_digest_len) { 136 fprintf(stderr, 137 "key type %s %u octet digests are too big, max %lu\n", 138 keytype_name(key_type), digest_len, 139 max_digest_len); 140 msyslog(LOG_ERR, 141 "key type %s %u octet digests are too big, max %lu", 142 keytype_name(key_type), digest_len, 143 max_digest_len); 144 return 0; 145 } 146 #else 147 digest_len = 16; 148 #endif 149 *pdigest_len = digest_len; 150 } 151 152 return key_type; 153 } 154 155 156 /* 157 * keytype_name returns OpenSSL short name for digest by NID. 158 * 159 * Used by ntpq and ntpdc keytype() 160 */ 161 const char * 162 keytype_name( 163 int nid 164 ) 165 { 166 static const char unknown_type[] = "(unknown key type)"; 167 const char *name; 168 169 #ifdef OPENSSL 170 INIT_SSL(); 171 name = OBJ_nid2sn(nid); 172 if (NULL == name) 173 name = unknown_type; 174 #else /* !OPENSSL follows */ 175 if (NID_md5 == nid) 176 name = "MD5"; 177 else 178 name = unknown_type; 179 #endif 180 return name; 181 } 182 183 184 /* 185 * Use getpassphrase() if configure.ac detected it, as Suns that 186 * have it truncate the password in getpass() to 8 characters. 187 */ 188 #ifdef HAVE_GETPASSPHRASE 189 # define getpass(str) getpassphrase(str) 190 #endif 191 192 /* 193 * getpass_keytype() -- shared between ntpq and ntpdc, only vaguely 194 * related to the rest of ssl_init.c. 195 */ 196 char * 197 getpass_keytype( 198 int keytype 199 ) 200 { 201 char pass_prompt[64 + 11 + 1]; /* 11 for " Password: " */ 202 203 snprintf(pass_prompt, sizeof(pass_prompt), 204 "%.64s Password: ", keytype_name(keytype)); 205 206 return getpass(pass_prompt); 207 } 208