xref: /freebsd/contrib/ntp/sntp/crypto.c (revision a466cc55373fc3cf86837f09da729535b57e69a1)
109100258SXin LI /*
209100258SXin LI  * HMS: we need to test:
309100258SXin LI  * - OpenSSL versions, if we are building with them
409100258SXin LI  * - our versions
509100258SXin LI  *
609100258SXin LI  * We may need to test with(out) OPENSSL separately.
709100258SXin LI  */
809100258SXin LI 
92b15cb3dSCy Schubert #include <config.h>
102b15cb3dSCy Schubert #include "crypto.h"
112b15cb3dSCy Schubert #include <ctype.h>
124990d495SXin LI #include "isc/string.h"
13f0574f5cSXin LI #include "ntp_md5.h"
142b15cb3dSCy Schubert 
1509100258SXin LI #ifndef EVP_MAX_MD_SIZE
1609100258SXin LI # define EVP_MAX_MD_SIZE 32
1709100258SXin LI #endif
1809100258SXin LI 
192b15cb3dSCy Schubert struct key *key_ptr;
202b15cb3dSCy Schubert size_t key_cnt = 0;
212b15cb3dSCy Schubert 
2209100258SXin LI typedef struct key Key_T;
2309100258SXin LI 
2409100258SXin LI static u_int
2509100258SXin LI compute_mac(
2609100258SXin LI 	u_char		digest[EVP_MAX_MD_SIZE],
2709100258SXin LI 	char const *	macname,
2809100258SXin LI 	void const *	pkt_data,
2909100258SXin LI 	u_int		pkt_size,
3009100258SXin LI 	void const *	key_data,
3109100258SXin LI 	u_int		key_size
3209100258SXin LI 	)
3309100258SXin LI {
3409100258SXin LI 	u_int		len  = 0;
352d4e511cSCy Schubert #if defined(OPENSSL) && defined(ENABLE_CMAC)
3609100258SXin LI 	size_t		slen = 0;
372d4e511cSCy Schubert #endif
3809100258SXin LI 	int		key_type;
3909100258SXin LI 
4009100258SXin LI 	INIT_SSL();
4109100258SXin LI 	key_type = keytype_from_text(macname, NULL);
4209100258SXin LI 
434e1ef62aSXin LI #if defined(OPENSSL) && defined(ENABLE_CMAC)
4409100258SXin LI 	/* Check if CMAC key type specific code required */
4509100258SXin LI 	if (key_type == NID_cmac) {
4609100258SXin LI 		CMAC_CTX *	ctx    = NULL;
4709100258SXin LI 		u_char		keybuf[AES_128_KEY_SIZE];
4809100258SXin LI 
4909100258SXin LI 		/* adjust key size (zero padded buffer) if necessary */
5009100258SXin LI 		if (AES_128_KEY_SIZE > key_size) {
5109100258SXin LI 			memcpy(keybuf, key_data, key_size);
5209100258SXin LI 			memset((keybuf + key_size), 0,
5309100258SXin LI 			       (AES_128_KEY_SIZE - key_size));
5409100258SXin LI 			key_data = keybuf;
5509100258SXin LI 		}
5609100258SXin LI 
5709100258SXin LI 		if (!(ctx = CMAC_CTX_new())) {
5809100258SXin LI 			msyslog(LOG_ERR, "make_mac: CMAC %s CTX new failed.",   CMAC);
5909100258SXin LI 		}
6009100258SXin LI 		else if (!CMAC_Init(ctx, key_data, AES_128_KEY_SIZE,
6109100258SXin LI 				    EVP_aes_128_cbc(), NULL)) {
6209100258SXin LI 			msyslog(LOG_ERR, "make_mac: CMAC %s Init failed.",      CMAC);
6309100258SXin LI 		}
6409100258SXin LI 		else if (!CMAC_Update(ctx, pkt_data, (size_t)pkt_size)) {
6509100258SXin LI 			msyslog(LOG_ERR, "make_mac: CMAC %s Update failed.",    CMAC);
6609100258SXin LI 		}
6709100258SXin LI 		else if (!CMAC_Final(ctx, digest, &slen)) {
6809100258SXin LI 			msyslog(LOG_ERR, "make_mac: CMAC %s Final failed.",     CMAC);
6909100258SXin LI 			slen = 0;
7009100258SXin LI 		}
7109100258SXin LI 		len = (u_int)slen;
7209100258SXin LI 
73767173ceSCy Schubert 		if (ctx)
74767173ceSCy Schubert 			CMAC_CTX_free(ctx);
7509100258SXin LI 		/* Test our AES-128-CMAC implementation */
7609100258SXin LI 
7709100258SXin LI 	} else	/* MD5 MAC handling */
7809100258SXin LI #endif
7909100258SXin LI 	{
8009100258SXin LI 		EVP_MD_CTX *	ctx;
8109100258SXin LI 
8209100258SXin LI 		if (!(ctx = EVP_MD_CTX_new())) {
8309100258SXin LI 			msyslog(LOG_ERR, "make_mac: MAC %s Digest CTX new failed.",
8409100258SXin LI 				macname);
8509100258SXin LI 			goto mac_fail;
8609100258SXin LI 		}
8709100258SXin LI #ifdef OPENSSL	/* OpenSSL 1 supports return codes 0 fail, 1 okay */
8809100258SXin LI #	    ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
8909100258SXin LI 		EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
9009100258SXin LI #	    endif
9109100258SXin LI 		/* [Bug 3457] DON'T use plain EVP_DigestInit! It would
9209100258SXin LI 		 *  kill the flags! */
9309100258SXin LI 		if (!EVP_DigestInit_ex(ctx, EVP_get_digestbynid(key_type), NULL)) {
9409100258SXin LI 			msyslog(LOG_ERR, "make_mac: MAC %s Digest Init failed.",
9509100258SXin LI 				macname);
9609100258SXin LI 			goto mac_fail;
9709100258SXin LI 		}
9809100258SXin LI 		if (!EVP_DigestUpdate(ctx, key_data, key_size)) {
9909100258SXin LI 			msyslog(LOG_ERR, "make_mac: MAC %s Digest Update key failed.",
10009100258SXin LI 				macname);
10109100258SXin LI 			goto mac_fail;
10209100258SXin LI 		}
10309100258SXin LI 		if (!EVP_DigestUpdate(ctx, pkt_data, pkt_size)) {
10409100258SXin LI 			msyslog(LOG_ERR, "make_mac: MAC %s Digest Update data failed.",
10509100258SXin LI 				macname);
10609100258SXin LI 			goto mac_fail;
10709100258SXin LI 		}
10809100258SXin LI 		if (!EVP_DigestFinal(ctx, digest, &len)) {
10909100258SXin LI 			msyslog(LOG_ERR, "make_mac: MAC %s Digest Final failed.",
11009100258SXin LI 				macname);
11109100258SXin LI 			len = 0;
11209100258SXin LI 		}
11309100258SXin LI #else /* !OPENSSL */
114*a466cc55SCy Schubert 		(void)key_type; /* unused, so try to prevent compiler from croaks */
115*a466cc55SCy Schubert 		if (!EVP_DigestInit(ctx, EVP_get_digestbynid(key_type))) {
116*a466cc55SCy Schubert 			msyslog(LOG_ERR, "make_mac: MAC MD5 Digest Init failed.");
117*a466cc55SCy Schubert 			goto mac_fail;
118*a466cc55SCy Schubert 		}
11909100258SXin LI 		EVP_DigestUpdate(ctx, key_data, key_size);
12009100258SXin LI 		EVP_DigestUpdate(ctx, pkt_data, pkt_size);
12109100258SXin LI 		EVP_DigestFinal(ctx, digest, &len);
12209100258SXin LI #endif
12309100258SXin LI 	  mac_fail:
12409100258SXin LI 		EVP_MD_CTX_free(ctx);
12509100258SXin LI 	}
12609100258SXin LI 
12709100258SXin LI 	return len;
12809100258SXin LI }
12909100258SXin LI 
1302b15cb3dSCy Schubert int
1312b15cb3dSCy Schubert make_mac(
13268ba7e87SXin LI 	const void *	pkt_data,
1332b15cb3dSCy Schubert 	int		pkt_size,
1342b15cb3dSCy Schubert 	int		mac_size,
13509100258SXin LI 	Key_T const *	cmp_key,
13668ba7e87SXin LI 	void * 		digest
1372b15cb3dSCy Schubert 	)
1382b15cb3dSCy Schubert {
13909100258SXin LI 	u_int		len;
14009100258SXin LI 	u_char		dbuf[EVP_MAX_MD_SIZE];
1412b15cb3dSCy Schubert 
14209100258SXin LI 	if (cmp_key->key_len > 64 || mac_size <= 0)
1432b15cb3dSCy Schubert 		return 0;
1442b15cb3dSCy Schubert 	if (pkt_size % 4 != 0)
1452b15cb3dSCy Schubert 		return 0;
1462b15cb3dSCy Schubert 
14709100258SXin LI 	len = compute_mac(dbuf, cmp_key->typen,
14809100258SXin LI 			  pkt_data, (u_int)pkt_size,
14909100258SXin LI 			  cmp_key->key_seq, (u_int)cmp_key->key_len);
150f391d6bcSXin LI 
1512b15cb3dSCy Schubert 
15209100258SXin LI 	if (len) {
15309100258SXin LI 		if (len > (u_int)mac_size)
15409100258SXin LI 			len = (u_int)mac_size;
15509100258SXin LI 		memcpy(digest, dbuf, len);
15609100258SXin LI 	}
1572b15cb3dSCy Schubert 	return (int)len;
1582b15cb3dSCy Schubert }
1592b15cb3dSCy Schubert 
1602b15cb3dSCy Schubert 
16168ba7e87SXin LI /* Generates a md5 digest of the key specified in keyid concatenated with the
1622b15cb3dSCy Schubert  * ntp packet (exluding the MAC) and compares this digest to the digest in
1632b15cb3dSCy Schubert  * the packet's MAC. If they're equal this function returns 1 (packet is
1642b15cb3dSCy Schubert  * authentic) or else 0 (not authentic).
1652b15cb3dSCy Schubert  */
1662b15cb3dSCy Schubert int
1672b15cb3dSCy Schubert auth_md5(
16809100258SXin LI 	void const *	pkt_data,
1692b15cb3dSCy Schubert 	int 		pkt_size,
1702b15cb3dSCy Schubert 	int		mac_size,
17109100258SXin LI 	Key_T const *	cmp_key
1722b15cb3dSCy Schubert 	)
1732b15cb3dSCy Schubert {
17409100258SXin LI 	u_int		len       = 0;
17509100258SXin LI 	u_char const *	pkt_ptr   = pkt_data;
17609100258SXin LI 	u_char		dbuf[EVP_MAX_MD_SIZE];
17709100258SXin LI 
17809100258SXin LI 	if (mac_size <= 0 || (size_t)mac_size > sizeof(dbuf))
17909100258SXin LI 		return FALSE;
18009100258SXin LI 
18109100258SXin LI 	len = compute_mac(dbuf, cmp_key->typen,
18209100258SXin LI 			  pkt_ptr, (u_int)pkt_size,
18309100258SXin LI 			  cmp_key->key_seq, (u_int)cmp_key->key_len);
18409100258SXin LI 
18509100258SXin LI 	pkt_ptr += pkt_size + 4;
18609100258SXin LI 	if (len > (u_int)mac_size)
18709100258SXin LI 		len = (u_int)mac_size;
18809100258SXin LI 
18909100258SXin LI 	/* isc_tsmemcmp will be better when its easy to link with.  sntp
19009100258SXin LI 	 * is a 1-shot program, so snooping for timing attacks is
19109100258SXin LI 	 * Harder.
1924990d495SXin LI 	 */
19309100258SXin LI 	return ((u_int)mac_size == len) && !memcmp(dbuf, pkt_ptr, len);
1942b15cb3dSCy Schubert }
1952b15cb3dSCy Schubert 
1962b15cb3dSCy Schubert static int
1972b15cb3dSCy Schubert hex_val(
1982b15cb3dSCy Schubert 	unsigned char x
1992b15cb3dSCy Schubert 	)
2002b15cb3dSCy Schubert {
2012b15cb3dSCy Schubert 	int val;
2022b15cb3dSCy Schubert 
2032b15cb3dSCy Schubert 	if ('0' <= x && x <= '9')
2042b15cb3dSCy Schubert 		val = x - '0';
2052b15cb3dSCy Schubert 	else if ('a' <= x && x <= 'f')
2062b15cb3dSCy Schubert 		val = x - 'a' + 0xa;
2072b15cb3dSCy Schubert 	else if ('A' <= x && x <= 'F')
2082b15cb3dSCy Schubert 		val = x - 'A' + 0xA;
2092b15cb3dSCy Schubert 	else
2102b15cb3dSCy Schubert 		val = -1;
2112b15cb3dSCy Schubert 
2122b15cb3dSCy Schubert 	return val;
2132b15cb3dSCy Schubert }
2142b15cb3dSCy Schubert 
2152b15cb3dSCy Schubert /* Load keys from the specified keyfile into the key structures.
2162b15cb3dSCy Schubert  * Returns -1 if the reading failed, otherwise it returns the
2172b15cb3dSCy Schubert  * number of keys it read
2182b15cb3dSCy Schubert  */
2192b15cb3dSCy Schubert int
2202b15cb3dSCy Schubert auth_init(
2212b15cb3dSCy Schubert 	const char *keyfile,
2222b15cb3dSCy Schubert 	struct key **keys
2232b15cb3dSCy Schubert 	)
2242b15cb3dSCy Schubert {
2252b15cb3dSCy Schubert 	FILE *keyf = fopen(keyfile, "r");
2262b15cb3dSCy Schubert 	struct key *prev = NULL;
22709100258SXin LI 	int scan_cnt, line_cnt = 1;
2282b15cb3dSCy Schubert 	char kbuf[200];
2292b15cb3dSCy Schubert 	char keystring[129];
2302b15cb3dSCy Schubert 
23109100258SXin LI 	/* HMS: Is it OK to do this later, after we know we have a key file? */
23209100258SXin LI 	INIT_SSL();
23309100258SXin LI 
2342b15cb3dSCy Schubert 	if (keyf == NULL) {
2352b15cb3dSCy Schubert 		if (debug)
2362b15cb3dSCy Schubert 			printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile);
2372b15cb3dSCy Schubert 		return -1;
2382b15cb3dSCy Schubert 	}
2392b15cb3dSCy Schubert 	if (feof(keyf)) {
2402b15cb3dSCy Schubert 		if (debug)
2412b15cb3dSCy Schubert 			printf("sntp auth_init: Key file %s is empty!\n", keyfile);
2422b15cb3dSCy Schubert 		fclose(keyf);
2432b15cb3dSCy Schubert 		return -1;
2442b15cb3dSCy Schubert 	}
2452b15cb3dSCy Schubert 	key_cnt = 0;
2462b15cb3dSCy Schubert 	while (!feof(keyf)) {
2472b15cb3dSCy Schubert 		char * octothorpe;
2482b15cb3dSCy Schubert 		struct key *act;
2492b15cb3dSCy Schubert 		int goodline = 0;
2502b15cb3dSCy Schubert 
2512b15cb3dSCy Schubert 		if (NULL == fgets(kbuf, sizeof(kbuf), keyf))
2522b15cb3dSCy Schubert 			continue;
2532b15cb3dSCy Schubert 
2542b15cb3dSCy Schubert 		kbuf[sizeof(kbuf) - 1] = '\0';
2552b15cb3dSCy Schubert 		octothorpe = strchr(kbuf, '#');
2562b15cb3dSCy Schubert 		if (octothorpe)
2572b15cb3dSCy Schubert 			*octothorpe = '\0';
2582b15cb3dSCy Schubert 		act = emalloc(sizeof(*act));
25909100258SXin LI 		/* keep width 15 = sizeof struct key.typen - 1 synced */
26009100258SXin LI 		scan_cnt = sscanf(kbuf, "%d %15s %128s",
26109100258SXin LI 					&act->key_id, act->typen, keystring);
2622b15cb3dSCy Schubert 		if (scan_cnt == 3) {
2632b15cb3dSCy Schubert 			int len = strlen(keystring);
26409100258SXin LI 			goodline = 1;	/* assume best for now */
2652b15cb3dSCy Schubert 			if (len <= 20) {
2662b15cb3dSCy Schubert 				act->key_len = len;
2672b15cb3dSCy Schubert 				memcpy(act->key_seq, keystring, len + 1);
2682b15cb3dSCy Schubert 			} else if ((len & 1) != 0) {
2692b15cb3dSCy Schubert 				goodline = 0; /* it's bad */
2702b15cb3dSCy Schubert 			} else {
2712b15cb3dSCy Schubert 				int j;
2722b15cb3dSCy Schubert 				act->key_len = len >> 1;
2732b15cb3dSCy Schubert 				for (j = 0; j < len; j+=2) {
2742b15cb3dSCy Schubert 					int val;
2752b15cb3dSCy Schubert 					val = (hex_val(keystring[j]) << 4) |
2762b15cb3dSCy Schubert 					       hex_val(keystring[j+1]);
2772b15cb3dSCy Schubert 					if (val < 0) {
2782b15cb3dSCy Schubert 						goodline = 0; /* it's bad */
2792b15cb3dSCy Schubert 						break;
2802b15cb3dSCy Schubert 					}
2812b15cb3dSCy Schubert 					act->key_seq[j>>1] = (char)val;
2822b15cb3dSCy Schubert 				}
2832b15cb3dSCy Schubert 			}
28409100258SXin LI 			act->typei = keytype_from_text(act->typen, NULL);
28509100258SXin LI 			if (0 == act->typei) {
28609100258SXin LI 				printf("%s: line %d: key %d, %s not supported - ignoring\n",
28709100258SXin LI 					keyfile, line_cnt,
28809100258SXin LI 					act->key_id, act->typen);
28909100258SXin LI 				goodline = 0; /* it's bad */
29009100258SXin LI 			}
2912b15cb3dSCy Schubert 		}
2922b15cb3dSCy Schubert 		if (goodline) {
2932b15cb3dSCy Schubert 			act->next = NULL;
2942b15cb3dSCy Schubert 			if (NULL == prev)
2952b15cb3dSCy Schubert 				*keys = act;
2962b15cb3dSCy Schubert 			else
2972b15cb3dSCy Schubert 				prev->next = act;
2982b15cb3dSCy Schubert 			prev = act;
2992b15cb3dSCy Schubert 			key_cnt++;
3002b15cb3dSCy Schubert 		} else {
30109100258SXin LI 			if (debug) {
30209100258SXin LI 				printf("auth_init: scanf %d items, skipping line %d.",
3032b15cb3dSCy Schubert 					scan_cnt, line_cnt);
30409100258SXin LI 			}
3052b15cb3dSCy Schubert 			free(act);
3062b15cb3dSCy Schubert 		}
3072b15cb3dSCy Schubert 		line_cnt++;
3082b15cb3dSCy Schubert 	}
3092b15cb3dSCy Schubert 	fclose(keyf);
3102b15cb3dSCy Schubert 
3112b15cb3dSCy Schubert 	key_ptr = *keys;
3122b15cb3dSCy Schubert 	return key_cnt;
3132b15cb3dSCy Schubert }
3142b15cb3dSCy Schubert 
3152b15cb3dSCy Schubert /* Looks for the key with keyid key_id and sets the d_key pointer to the
3162b15cb3dSCy Schubert  * address of the key. If no matching key is found the pointer is not touched.
3172b15cb3dSCy Schubert  */
3182b15cb3dSCy Schubert void
3192b15cb3dSCy Schubert get_key(
3202b15cb3dSCy Schubert 	int key_id,
3212b15cb3dSCy Schubert 	struct key **d_key
3222b15cb3dSCy Schubert 	)
3232b15cb3dSCy Schubert {
3242b15cb3dSCy Schubert 	struct key *itr_key;
3252b15cb3dSCy Schubert 
3262b15cb3dSCy Schubert 	if (key_cnt == 0)
3272b15cb3dSCy Schubert 		return;
3282b15cb3dSCy Schubert 	for (itr_key = key_ptr; itr_key; itr_key = itr_key->next) {
3292b15cb3dSCy Schubert 		if (itr_key->key_id == key_id) {
3302b15cb3dSCy Schubert 			*d_key = itr_key;
3312b15cb3dSCy Schubert 			break;
3322b15cb3dSCy Schubert 		}
3332b15cb3dSCy Schubert 	}
3342b15cb3dSCy Schubert 	return;
3352b15cb3dSCy Schubert }
336