xref: /netbsd-src/external/bsd/ntp/dist/libntp/ssl_init.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
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