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