Home | History | Annotate | Line # | Download | only in sntp
crypto.c revision 1.4.2.1
      1 /*	$NetBSD: crypto.c,v 1.4.2.1 2014/12/25 02:34:42 snj Exp $	*/
      2 
      3 #include <config.h>
      4 #include "crypto.h"
      5 #include <ctype.h>
      6 
      7 struct key *key_ptr;
      8 size_t key_cnt = 0;
      9 
     10 int
     11 make_mac(
     12 	char *pkt_data,
     13 	int pkt_size,
     14 	int mac_size,
     15 	struct key *cmp_key,
     16 	char * digest
     17 	)
     18 {
     19 	u_int		len = mac_size;
     20 	int		key_type;
     21 	EVP_MD_CTX	ctx;
     22 
     23 	if (cmp_key->key_len > 64)
     24 		return 0;
     25 	if (pkt_size % 4 != 0)
     26 		return 0;
     27 
     28 	INIT_SSL();
     29 	key_type = keytype_from_text(cmp_key->type, NULL);
     30 	EVP_DigestInit(&ctx, EVP_get_digestbynid(key_type));
     31 	EVP_DigestUpdate(&ctx, (u_char *)cmp_key->key_seq, (u_int)cmp_key->key_len);
     32 	EVP_DigestUpdate(&ctx, (u_char *)pkt_data, (u_int)pkt_size);
     33 	EVP_DigestFinal(&ctx, (u_char *)digest, &len);
     34 
     35 	return (int)len;
     36 }
     37 
     38 
     39 /* Generates a md5 digest of the key specified in keyid concatinated with the
     40  * ntp packet (exluding the MAC) and compares this digest to the digest in
     41  * the packet's MAC. If they're equal this function returns 1 (packet is
     42  * authentic) or else 0 (not authentic).
     43  */
     44 int
     45 auth_md5(
     46 	char *pkt_data,
     47 	int pkt_size,
     48 	int mac_size,
     49 	struct key *cmp_key
     50 	)
     51 {
     52 	int  hash_len;
     53 	int  authentic;
     54 	char digest[20];
     55 
     56 	if (mac_size > (int)sizeof(digest))
     57 		return 0;
     58 	hash_len = make_mac(pkt_data, pkt_size, sizeof(digest), cmp_key,
     59 			    digest);
     60 	if (!hash_len)
     61 		authentic = FALSE;
     62 	else
     63 		authentic = !memcmp(digest, pkt_data + pkt_size + 4,
     64 				    hash_len);
     65 	return authentic;
     66 }
     67 
     68 static int
     69 hex_val(
     70 	unsigned char x
     71 	)
     72 {
     73 	int val;
     74 
     75 	if ('0' <= x && x <= '9')
     76 		val = x - '0';
     77 	else if ('a' <= x && x <= 'f')
     78 		val = x - 'a' + 0xa;
     79 	else if ('A' <= x && x <= 'F')
     80 		val = x - 'A' + 0xA;
     81 	else
     82 		val = -1;
     83 
     84 	return val;
     85 }
     86 
     87 /* Load keys from the specified keyfile into the key structures.
     88  * Returns -1 if the reading failed, otherwise it returns the
     89  * number of keys it read
     90  */
     91 int
     92 auth_init(
     93 	const char *keyfile,
     94 	struct key **keys
     95 	)
     96 {
     97 	FILE *keyf = fopen(keyfile, "r");
     98 	struct key *prev = NULL;
     99 	int scan_cnt, line_cnt = 0;
    100 	char kbuf[200];
    101 	char keystring[129];
    102 
    103 	if (keyf == NULL) {
    104 		if (debug)
    105 			printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile);
    106 		return -1;
    107 	}
    108 	if (feof(keyf)) {
    109 		if (debug)
    110 			printf("sntp auth_init: Key file %s is empty!\n", keyfile);
    111 		fclose(keyf);
    112 		return -1;
    113 	}
    114 	key_cnt = 0;
    115 	while (!feof(keyf)) {
    116 		char * octothorpe;
    117 		struct key *act;
    118 		int goodline = 0;
    119 
    120 		if (NULL == fgets(kbuf, sizeof(kbuf), keyf))
    121 			continue;
    122 
    123 		kbuf[sizeof(kbuf) - 1] = '\0';
    124 		octothorpe = strchr(kbuf, '#');
    125 		if (octothorpe)
    126 			*octothorpe = '\0';
    127 		act = emalloc(sizeof(*act));
    128 		scan_cnt = sscanf(kbuf, "%d %9s %128s", &act->key_id, act->type, keystring);
    129 		if (scan_cnt == 3) {
    130 			int len = strlen(keystring);
    131 			if (len <= 20) {
    132 				act->key_len = len;
    133 				memcpy(act->key_seq, keystring, len + 1);
    134 				goodline = 1;
    135 			} else if ((len & 1) != 0) {
    136 				goodline = 0; /* it's bad */
    137 			} else {
    138 				int j;
    139 				goodline = 1;
    140 				act->key_len = len >> 1;
    141 				for (j = 0; j < len; j+=2) {
    142 					int val;
    143 					val = (hex_val(keystring[j]) << 4) |
    144 					       hex_val(keystring[j+1]);
    145 					if (val < 0) {
    146 						goodline = 0; /* it's bad */
    147 						break;
    148 					}
    149 					act->key_seq[j>>1] = (char)val;
    150 				}
    151 			}
    152 		}
    153 		if (goodline) {
    154 			act->next = NULL;
    155 			if (NULL == prev)
    156 				*keys = act;
    157 			else
    158 				prev->next = act;
    159 			prev = act;
    160 			key_cnt++;
    161 		} else {
    162 			msyslog(LOG_DEBUG, "auth_init: scanf %d items, skipping line %d.",
    163 				scan_cnt, line_cnt);
    164 			free(act);
    165 		}
    166 		line_cnt++;
    167 	}
    168 	fclose(keyf);
    169 
    170 	key_ptr = *keys;
    171 	return key_cnt;
    172 }
    173 
    174 /* Looks for the key with keyid key_id and sets the d_key pointer to the
    175  * address of the key. If no matching key is found the pointer is not touched.
    176  */
    177 void
    178 get_key(
    179 	int key_id,
    180 	struct key **d_key
    181 	)
    182 {
    183 	struct key *itr_key;
    184 
    185 	if (key_cnt == 0)
    186 		return;
    187 	for (itr_key = key_ptr; itr_key; itr_key = itr_key->next) {
    188 		if (itr_key->key_id == key_id) {
    189 			*d_key = itr_key;
    190 			break;
    191 		}
    192 	}
    193 	return;
    194 }
    195