xref: /freebsd/contrib/ntp/libntp/ssl_init.c (revision 96190b4fef3b4a0cc3ca0606b0c4e3e69a5e6717)
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 
27 EVP_MD_CTX *digest_ctx;
28 
29 
30 static void
31 atexit_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 
45 void
46 ssl_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 
62 void
63 ssl_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  */
89 int
90 keytype_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  */
198 const char *
199 keytype_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  */
240 char *
241 getpass_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