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