crypto.c revision 1.2
1/*	$NetBSD: crypto.c,v 1.2 2010/12/04 23:08:36 christos Exp $	*/
2
3#include "crypto.h"
4
5struct key *key_ptr;
6size_t key_cnt = 0;
7
8/* Generates a md5 digest of the ntp packet (exluding the MAC) concatinated
9 * with the key specified in keyid and compares this digest to the digest in
10 * the packet's MAC. If they're equal this function returns 1 (packet is
11 * authentic) or else 0 (not authentic).
12 */
13int
14auth_md5(
15	char *pkt_data,
16	int mac_size,
17	struct key *cmp_key
18	)
19{
20	size_t a;
21	char digest[16];
22	MD5_CTX ctx;
23	char *digest_data;
24
25	if (cmp_key->type != 'M')
26		return -1;
27
28	MD5Init(&ctx);
29
30	digest_data = emalloc(sizeof(char) * (LEN_PKT_NOMAC + cmp_key->key_len));
31
32	for (a = 0; a < LEN_PKT_NOMAC; a++)
33		digest_data[a] = pkt_data[a];
34
35	for (a = 0; a < (size_t)cmp_key->key_len; a++)
36		digest_data[LEN_PKT_NOMAC + a] = cmp_key->key_seq[a];
37
38	MD5Update(&ctx, (u_char *)digest_data, LEN_PKT_NOMAC + cmp_key->key_len);
39	MD5Final((u_char *)digest, &ctx);
40
41	free(digest_data);
42
43	for (a = 0; a < 16; a++)
44		if (digest[a] != pkt_data[LEN_PKT_MAC + a])
45			return 0;
46
47	return 1;
48}
49
50/* Load keys from the specified keyfile into the key structures.
51 * Returns -1 if the reading failed, otherwise it returns the
52 * number of keys it read
53 */
54int
55auth_init(
56	const char *keyfile,
57	struct key **keys
58	)
59{
60	FILE *keyf = fopen(keyfile, "r");
61	struct key *prev = NULL;
62	size_t a;
63	int line_limit;
64	int scan_cnt, line_cnt = 0;
65	char kbuf[96];
66
67	if (keyf == NULL) {
68		if (ENABLED_OPT(NORMALVERBOSE))
69			printf("sntp auth_init: Couldn't open key file %s for reading!\n", keyfile);
70
71		return -1;
72	}
73
74	line_cnt = 0;
75
76	if (feof(keyf)) {
77		if (ENABLED_OPT(NORMALVERBOSE))
78			printf("sntp auth_init: Key file %s is empty!\n", keyfile);
79		fclose(keyf);
80
81		return -1;
82	}
83
84	while (!feof(keyf)) {
85		struct key *act = emalloc(sizeof(struct key));
86		line_limit = 0;
87
88		fgets(kbuf, sizeof(kbuf), keyf);
89
90		for (a = 0; a < strlen(kbuf) && a < sizeof(kbuf); a++) {
91			if (kbuf[a] == '#') {
92				line_limit = a;
93				break;
94			}
95		}
96
97		if (line_limit != 0)
98			kbuf[line_limit] = '\0';
99
100#ifdef DEBUG
101		printf("sntp auth_init: fgets: %s", kbuf);
102#endif
103
104
105		if ((scan_cnt = sscanf(kbuf, "%i %c %16s", &act->key_id, &act->type, act->key_seq)) == 3) {
106			act->key_len = strlen(act->key_seq);
107			act->next = NULL;
108
109			if (NULL == prev)
110				*keys = act;
111			else
112				prev->next = act;
113			prev = act;
114
115			key_cnt++;
116
117#ifdef DEBUG
118			printf("sntp auth_init: key_id %i type %c with key %s\n", act->key_id, act->type, act->key_seq);
119#endif
120		} else {
121#ifdef DEBUG
122			printf("sntp auth_init: scanf read %i items, doesn't look good, skipping line %i.\n", scan_cnt, line_cnt);
123#endif
124
125			free(act);
126		}
127
128		line_cnt++;
129	}
130
131	fclose(keyf);
132
133#ifdef DEBUG
134	STDLINE
135	printf("sntp auth_init: Read %i keys from file %s:\n", line_cnt, keyfile);
136
137	{
138		struct key *kptr = *keys;
139
140		for (a = 0; a < key_cnt; a++) {
141			printf("key_id %i type %c with key %s (key length: %i)\n",
142			       kptr->key_id, kptr->type, kptr->key_seq, kptr->key_len);
143			kptr = kptr->next;
144		}
145	}
146	STDLINE
147#endif
148
149	key_cnt = line_cnt;
150	key_ptr = *keys;
151
152	return line_cnt;
153}
154
155/* Looks for the key with keyid key_id and sets the d_key pointer to the
156 * address of the key. If no matching key is found the pointer is not touched.
157 */
158void
159get_key(
160	int key_id,
161	struct key **d_key
162	)
163{
164	size_t a;
165	struct key *itr_key = key_ptr;
166
167	if (key_cnt == 0)
168		return;
169
170	for (a = 0; a < key_cnt && itr_key != NULL; a++) {
171		if (itr_key->key_id == key_id) {
172			*d_key = itr_key;
173			return;
174		}
175	}
176
177	return;
178}
179