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