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