xref: /netbsd-src/external/bsd/ntp/dist/sntp/crypto.c (revision c2f76ff004a2cb67efe5b12d97bd3ef7fe89e18d)
1 /*	$NetBSD: crypto.c,v 1.2 2010/12/04 23:08:36 christos Exp $	*/
2 
3 #include "crypto.h"
4 
5 struct key *key_ptr;
6 size_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  */
13 int
14 auth_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  */
54 int
55 auth_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  */
158 void
159 get_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