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 27EVP_MD_CTX *digest_ctx; 28 29 30static void 31atexit_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 45void 46ssl_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 62void 63ssl_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 */ 89int 90keytype_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 */ 198const char * 199keytype_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 */ 240char * 241getpass_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