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