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