crypto.c revision 1.14
1/*	$NetBSD: crypto.c,v 1.14 2018/04/07 00:19:53 christos Exp $	*/
2
3/*
4 * HMS: we need to test:
5 * - OpenSSL versions, if we are building with them
6 * - our versions
7 *
8 * We may need to test with(out) OPENSSL separately.
9 */
10
11#include <config.h>
12#include "crypto.h"
13#include <ctype.h>
14#include "isc/string.h"
15#include "ntp_md5.h"
16
17/* HMS: We may not have OpenSSL, but we have our own AES-128-CMAC */
18#define  CMAC		"AES128CMAC"
19#ifdef OPENSSL
20# include "openssl/cmac.h"
21# define  AES_128_KEY_SIZE	16
22#endif /* OPENSSL */
23
24#ifndef EVP_MAX_MD_SIZE
25# define EVP_MAX_MD_SIZE 32
26#endif
27
28struct key *key_ptr;
29size_t key_cnt = 0;
30
31typedef struct key Key_T;
32
33static u_int
34compute_mac(
35	u_char		digest[EVP_MAX_MD_SIZE],
36	char const *	macname,
37	void const *	pkt_data,
38	u_int		pkt_size,
39	void const *	key_data,
40	u_int		key_size
41	)
42{
43	u_int		len  = 0;
44	size_t		slen = 0;
45	int		key_type;
46
47	INIT_SSL();
48	key_type = keytype_from_text(macname, NULL);
49
50#ifdef OPENSSL
51	/* Check if CMAC key type specific code required */
52	if (key_type == NID_cmac) {
53		CMAC_CTX *	ctx    = NULL;
54		u_char		keybuf[AES_128_KEY_SIZE];
55
56		/* adjust key size (zero padded buffer) if necessary */
57		if (AES_128_KEY_SIZE > key_size) {
58			memcpy(keybuf, key_data, key_size);
59			memset((keybuf + key_size), 0,
60			       (AES_128_KEY_SIZE - key_size));
61			key_data = keybuf;
62		}
63
64		if (!(ctx = CMAC_CTX_new())) {
65			msyslog(LOG_ERR, "make_mac: CMAC %s CTX new failed.",   CMAC);
66		}
67		else if (!CMAC_Init(ctx, key_data, AES_128_KEY_SIZE,
68				    EVP_aes_128_cbc(), NULL)) {
69			msyslog(LOG_ERR, "make_mac: CMAC %s Init failed.",      CMAC);
70		}
71		else if (!CMAC_Update(ctx, pkt_data, (size_t)pkt_size)) {
72			msyslog(LOG_ERR, "make_mac: CMAC %s Update failed.",    CMAC);
73		}
74		else if (!CMAC_Final(ctx, digest, &slen)) {
75			msyslog(LOG_ERR, "make_mac: CMAC %s Final failed.",     CMAC);
76			slen = 0;
77		}
78		len = (u_int)slen;
79
80		CMAC_CTX_cleanup(ctx);
81		/* Test our AES-128-CMAC implementation */
82
83	} else	/* MD5 MAC handling */
84#endif
85	{
86		EVP_MD_CTX *	ctx;
87
88		if (!(ctx = EVP_MD_CTX_new())) {
89			msyslog(LOG_ERR, "make_mac: MAC %s Digest CTX new failed.",
90				macname);
91			goto mac_fail;
92		}
93#ifdef OPENSSL	/* OpenSSL 1 supports return codes 0 fail, 1 okay */
94#	    ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
95		EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
96#	    endif
97		/* [Bug 3457] DON'T use plain EVP_DigestInit! It would
98		 *  kill the flags! */
99		if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(key_type), NULL)) {
100			msyslog(LOG_ERR, "make_mac: MAC %s Digest Init failed.",
101				macname);
102			goto mac_fail;
103		}
104		if (!EVP_DigestUpdate(ctx, key_data, key_size)) {
105			msyslog(LOG_ERR, "make_mac: MAC %s Digest Update key failed.",
106				macname);
107			goto mac_fail;
108		}
109		if (!EVP_DigestUpdate(ctx, pkt_data, pkt_size)) {
110			msyslog(LOG_ERR, "make_mac: MAC %s Digest Update data failed.",
111				macname);
112			goto mac_fail;
113		}
114		if (!EVP_DigestFinal(ctx, digest, &len)) {
115			msyslog(LOG_ERR, "make_mac: MAC %s Digest Final failed.",
116				macname);
117			len = 0;
118		}
119#else /* !OPENSSL */
120		EVP_DigestInit(ctx, EVP_get_digestbynid(key_type));
121		EVP_DigestUpdate(ctx, key_data, key_size);
122		EVP_DigestUpdate(ctx, pkt_data, pkt_size);
123		EVP_DigestFinal(ctx, digest, &len);
124#endif
125	  mac_fail:
126		EVP_MD_CTX_free(ctx);
127	}
128
129	return len;
130}
131
132int
133make_mac(
134	const void *	pkt_data,
135	int		pkt_size,
136	int		mac_size,
137	Key_T const *	cmp_key,
138	void * 		digest
139	)
140{
141	u_int		len;
142	u_char		dbuf[EVP_MAX_MD_SIZE];
143
144	if (cmp_key->key_len > 64 || mac_size <= 0)
145		return 0;
146	if (pkt_size % 4 != 0)
147		return 0;
148
149	len = compute_mac(dbuf, cmp_key->typen,
150			  pkt_data, (u_int)pkt_size,
151			  cmp_key->key_seq, (u_int)cmp_key->key_len);
152
153
154	if (len) {
155		if (len > (u_int)mac_size)
156			len = (u_int)mac_size;
157		memcpy(digest, dbuf, len);
158	}
159	return (int)len;
160}
161
162
163/* Generates a md5 digest of the key specified in keyid concatenated with the
164 * ntp packet (exluding the MAC) and compares this digest to the digest in
165 * the packet's MAC. If they're equal this function returns 1 (packet is
166 * authentic) or else 0 (not authentic).
167 */
168int
169auth_md5(
170	void const *	pkt_data,
171	int 		pkt_size,
172	int		mac_size,
173	Key_T const *	cmp_key
174	)
175{
176	u_int		len       = 0;
177	u_char const *	pkt_ptr   = pkt_data;
178	u_char		dbuf[EVP_MAX_MD_SIZE];
179
180	if (mac_size <= 0 || (size_t)mac_size > sizeof(dbuf))
181		return FALSE;
182
183	len = compute_mac(dbuf, cmp_key->typen,
184			  pkt_ptr, (u_int)pkt_size,
185			  cmp_key->key_seq, (u_int)cmp_key->key_len);
186
187	pkt_ptr += pkt_size + 4;
188	if (len > (u_int)mac_size)
189		len = (u_int)mac_size;
190
191	/* isc_tsmemcmp will be better when its easy to link with.  sntp
192	 * is a 1-shot program, so snooping for timing attacks is
193	 * Harder.
194	 */
195	return ((u_int)mac_size == len) && !memcmp(dbuf, pkt_ptr, len);
196}
197
198static int
199hex_val(
200	unsigned char x
201	)
202{
203	int val;
204
205	if ('0' <= x && x <= '9')
206		val = x - '0';
207	else if ('a' <= x && x <= 'f')
208		val = x - 'a' + 0xa;
209	else if ('A' <= x && x <= 'F')
210		val = x - 'A' + 0xA;
211	else
212		val = -1;
213
214	return val;
215}
216
217/* Load keys from the specified keyfile into the key structures.
218 * Returns -1 if the reading failed, otherwise it returns the
219 * number of keys it read
220 */
221int
222auth_init(
223	const char *keyfile,
224	struct key **keys
225	)
226{
227	FILE *keyf = fopen(keyfile, "r");
228	struct key *prev = NULL;
229	int scan_cnt, line_cnt = 1;
230	char kbuf[200];
231	char keystring[129];
232
233	/* HMS: Is it OK to do this later, after we know we have a key file? */
234	INIT_SSL();
235
236	if (keyf == NULL) {
237		if (debug)
238			printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile);
239		return -1;
240	}
241	if (feof(keyf)) {
242		if (debug)
243			printf("sntp auth_init: Key file %s is empty!\n", keyfile);
244		fclose(keyf);
245		return -1;
246	}
247	key_cnt = 0;
248	while (!feof(keyf)) {
249		char * octothorpe;
250		struct key *act;
251		int goodline = 0;
252
253		if (NULL == fgets(kbuf, sizeof(kbuf), keyf))
254			continue;
255
256		kbuf[sizeof(kbuf) - 1] = '\0';
257		octothorpe = strchr(kbuf, '#');
258		if (octothorpe)
259			*octothorpe = '\0';
260		act = emalloc(sizeof(*act));
261		/* keep width 15 = sizeof struct key.typen - 1 synced */
262		scan_cnt = sscanf(kbuf, "%d %15s %128s",
263					&act->key_id, act->typen, keystring);
264		if (scan_cnt == 3) {
265			int len = strlen(keystring);
266			goodline = 1;	/* assume best for now */
267			if (len <= 20) {
268				act->key_len = len;
269				memcpy(act->key_seq, keystring, len + 1);
270			} else if ((len & 1) != 0) {
271				goodline = 0; /* it's bad */
272			} else {
273				int j;
274				act->key_len = len >> 1;
275				for (j = 0; j < len; j+=2) {
276					int val;
277					val = (hex_val(keystring[j]) << 4) |
278					       hex_val(keystring[j+1]);
279					if (val < 0) {
280						goodline = 0; /* it's bad */
281						break;
282					}
283					act->key_seq[j>>1] = (char)val;
284				}
285			}
286			act->typei = keytype_from_text(act->typen, NULL);
287			if (0 == act->typei) {
288				printf("%s: line %d: key %d, %s not supported - ignoring\n",
289					keyfile, line_cnt,
290					act->key_id, act->typen);
291				goodline = 0; /* it's bad */
292			}
293		}
294		if (goodline) {
295			act->next = NULL;
296			if (NULL == prev)
297				*keys = act;
298			else
299				prev->next = act;
300			prev = act;
301			key_cnt++;
302		} else {
303			if (debug) {
304				printf("auth_init: scanf %d items, skipping line %d.",
305					scan_cnt, line_cnt);
306			}
307			free(act);
308		}
309		line_cnt++;
310	}
311	fclose(keyf);
312
313	key_ptr = *keys;
314	return key_cnt;
315}
316
317/* Looks for the key with keyid key_id and sets the d_key pointer to the
318 * address of the key. If no matching key is found the pointer is not touched.
319 */
320void
321get_key(
322	int key_id,
323	struct key **d_key
324	)
325{
326	struct key *itr_key;
327
328	if (key_cnt == 0)
329		return;
330	for (itr_key = key_ptr; itr_key; itr_key = itr_key->next) {
331		if (itr_key->key_id == key_id) {
332			*d_key = itr_key;
333			break;
334		}
335	}
336	return;
337}
338