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
atexit_ssl_cleanup(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
ssl_init(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
ssl_check_version(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
keytype_from_text(const char * text,size_t * pdigest_len)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 *
keytype_name(int type)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 *
getpass_keytype(int type)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