xref: /freebsd/contrib/ntp/libntp/authkeys.c (revision 39beb93c3f8bdbf72a61fda42300b5ebed7390c8)
1 /*
2  * authkeys.c - routines to manage the storage of authentication keys
3  */
4 
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8 
9 #include <stdio.h>
10 
11 #include "ntp_types.h"
12 #include "ntp_fp.h"
13 #include "ntp.h"
14 #include "ntpd.h"
15 #include "ntp_string.h"
16 #include "ntp_malloc.h"
17 #include "ntp_stdlib.h"
18 
19 /*
20  * Structure to store keys in in the hash table.
21  */
22 struct savekey {
23 	struct savekey *next;
24 	union {
25 		long bogon;		/* Make sure nonempty */
26 		u_char MD5_key[32];	/* MD5 key */
27 	} k;
28 	keyid_t keyid;		/* key identifier */
29 	u_short flags;		/* flags that wave */
30 	u_long lifetime;	/* remaining lifetime */
31 	int keylen;		/* key length */
32 };
33 
34 #define	KEY_TRUSTED	0x001	/* this key is trusted */
35 #define	KEY_MD5		0x200	/* this is a MD5 type key */
36 
37 /*
38  * The hash table. This is indexed by the low order bits of the
39  * keyid. We make this fairly big for potentially busy servers.
40  */
41 #define	HASHSIZE	64
42 #define	HASHMASK	((HASHSIZE)-1)
43 #define	KEYHASH(keyid)	((keyid) & HASHMASK)
44 
45 struct savekey *key_hash[HASHSIZE];
46 
47 u_long authkeynotfound;		/* keys not found */
48 u_long authkeylookups;		/* calls to lookup keys */
49 u_long authnumkeys;		/* number of active keys */
50 u_long authkeyexpired;		/* key lifetime expirations */
51 u_long authkeyuncached;		/* cache misses */
52 u_long authnokey;		/* calls to encrypt with no key */
53 u_long authencryptions;		/* calls to encrypt */
54 u_long authdecryptions;		/* calls to decrypt */
55 
56 /*
57  * Storage for free key structures.  We malloc() such things but
58  * never free them.
59  */
60 struct savekey *authfreekeys;
61 int authnumfreekeys;
62 
63 #define	MEMINC	12		/* number of new free ones to get */
64 
65 /*
66  * The key cache. We cache the last key we looked at here.
67  */
68 keyid_t	cache_keyid;		/* key identifier */
69 u_char	*cache_key;		/* key pointer */
70 u_int	cache_keylen;		/* key length */
71 u_short cache_flags;		/* flags that wave */
72 
73 
74 /*
75  * init_auth - initialize internal data
76  */
77 void
78 init_auth(void)
79 {
80 	/*
81 	 * Initialize hash table and free list
82 	 */
83 	memset((char *)key_hash, 0, sizeof key_hash);
84 }
85 
86 
87 /*
88  * auth_findkey - find a key in the hash table
89  */
90 struct savekey *
91 auth_findkey(
92 	keyid_t keyno
93 	)
94 {
95 	struct savekey *sk;
96 
97 	sk = key_hash[KEYHASH(keyno)];
98 	while (sk != 0) {
99 		if (keyno == sk->keyid)
100 			return (sk);
101 
102 		sk = sk->next;
103 	}
104 	return (0);
105 }
106 
107 
108 /*
109  * auth_havekey - return one if the key is known
110  */
111 int
112 auth_havekey(
113 	keyid_t keyno
114 	)
115 {
116 	struct savekey *sk;
117 
118 	if (keyno == 0 || (keyno == cache_keyid))
119 		return (1);
120 
121 	sk = key_hash[KEYHASH(keyno)];
122 	while (sk != 0) {
123 		if (keyno == sk->keyid)
124 			return (1);
125 
126 		sk = sk->next;
127 	}
128 	return (0);
129 }
130 
131 
132 /*
133  * authhavekey - return one and cache the key, if known and trusted.
134  */
135 int
136 authhavekey(
137 	keyid_t keyno
138 	)
139 {
140 	struct savekey *sk;
141 
142 	authkeylookups++;
143 	if (keyno == 0 || keyno == cache_keyid)
144 		return (1);
145 
146 	authkeyuncached++;
147 	sk = key_hash[KEYHASH(keyno)];
148 	while (sk != 0) {
149 		if (keyno == sk->keyid)
150 		    break;
151 		sk = sk->next;
152 	}
153 	if (sk == 0) {
154 		authkeynotfound++;
155 		return (0);
156 	} else if (!(sk->flags & KEY_TRUSTED)) {
157 		authnokey++;
158 		return (0);
159 	}
160 	cache_keyid = sk->keyid;
161 	cache_flags = sk->flags;
162 	if (sk->flags & KEY_MD5) {
163 		cache_key = sk->k.MD5_key;
164 		cache_keylen = sk->keylen;
165 		return (1);
166 	}
167 	return (0);
168 }
169 
170 
171 /*
172  * auth_moremem - get some more free key structures
173  */
174 int
175 auth_moremem(void)
176 {
177 	struct savekey *sk;
178 	int i;
179 
180 	sk = (struct savekey *)calloc(MEMINC, sizeof(struct savekey));
181 	if (sk == 0)
182 		return (0);
183 
184 	for (i = MEMINC; i > 0; i--) {
185 		sk->next = authfreekeys;
186 		authfreekeys = sk++;
187 	}
188 	authnumfreekeys += MEMINC;
189 	return (authnumfreekeys);
190 }
191 
192 
193 /*
194  * authtrust - declare a key to be trusted/untrusted
195  */
196 void
197 authtrust(
198 	keyid_t keyno,
199 	u_long trust
200 	)
201 {
202 	struct savekey *sk;
203 
204 #ifdef DEBUG
205 	if (debug > 2)
206 		printf("authtrust: keyid %08x life %lu\n", keyno, trust);
207 #endif
208 	sk = key_hash[KEYHASH(keyno)];
209 	while (sk != 0) {
210 		if (keyno == sk->keyid)
211 		    break;
212 		sk = sk->next;
213 	}
214 
215 	if (sk == 0 && !trust)
216 		return;
217 
218 	if (sk != 0) {
219 		if (cache_keyid == keyno) {
220 			cache_flags = 0;
221 			cache_keyid = 0;
222 		}
223 
224 		if (trust > 0) {
225 			sk->flags |= KEY_TRUSTED;
226 			if (trust > 1)
227 				sk->lifetime = current_time + trust;
228 			else
229 				sk->lifetime = 0;
230 			return;
231 		}
232 
233 		sk->flags &= ~KEY_TRUSTED; {
234 			struct savekey *skp;
235 
236 			skp = key_hash[KEYHASH(keyno)];
237 			if (skp == sk) {
238 				key_hash[KEYHASH(keyno)] = sk->next;
239 			} else {
240 				while (skp->next != sk)
241 				    skp = skp->next;
242 				skp->next = sk->next;
243 			}
244 			authnumkeys--;
245 
246 			sk->next = authfreekeys;
247 			authfreekeys = sk;
248 			authnumfreekeys++;
249 		}
250 		return;
251 	}
252 
253 	if (authnumfreekeys == 0)
254 	    if (auth_moremem() == 0)
255 		return;
256 
257 	sk = authfreekeys;
258 	authfreekeys = sk->next;
259 	authnumfreekeys--;
260 
261 	sk->keyid = keyno;
262 	sk->flags = KEY_TRUSTED;
263 	sk->next = key_hash[KEYHASH(keyno)];
264 	key_hash[KEYHASH(keyno)] = sk;
265 	authnumkeys++;
266 	return;
267 }
268 
269 
270 /*
271  * authistrusted - determine whether a key is trusted
272  */
273 int
274 authistrusted(
275 	keyid_t keyno
276 	)
277 {
278 	struct savekey *sk;
279 
280 	if (keyno == cache_keyid)
281 	    return ((cache_flags & KEY_TRUSTED) != 0);
282 
283 	authkeyuncached++;
284 	sk = key_hash[KEYHASH(keyno)];
285 	while (sk != 0) {
286 		if (keyno == sk->keyid)
287 		    break;
288 		sk = sk->next;
289 	}
290 	if (sk == 0) {
291 		authkeynotfound++;
292 		return (0);
293 	} else if (!(sk->flags & KEY_TRUSTED)) {
294 		authkeynotfound++;
295 		return (0);
296 	}
297 	return (1);
298 }
299 
300 
301 void
302 MD5auth_setkey(
303 	keyid_t keyno,
304 	const u_char *key,
305 	const int len
306 	)
307 {
308 	struct savekey *sk;
309 
310 	/*
311 	 * See if we already have the key.  If so just stick in the
312 	 * new value.
313 	 */
314 	sk = key_hash[KEYHASH(keyno)];
315 	while (sk != 0) {
316 		if (keyno == sk->keyid) {
317 			strncpy((char *)sk->k.MD5_key, (const char *)key,
318 			    sizeof(sk->k.MD5_key));
319 			if ((sk->keylen = len) > sizeof(sk->k.MD5_key))
320 			    sk->keylen = sizeof(sk->k.MD5_key);
321 
322 			sk->flags |= KEY_MD5;
323 			if (cache_keyid == keyno) {
324 				cache_flags = 0;
325 				cache_keyid = 0;
326 			}
327 			return;
328 		}
329 		sk = sk->next;
330 	}
331 
332 	/*
333 	 * Need to allocate new structure.  Do it.
334 	 */
335 	if (authnumfreekeys == 0) {
336 		if (auth_moremem() == 0)
337 		    return;
338 	}
339 
340 	sk = authfreekeys;
341 	authfreekeys = sk->next;
342 	authnumfreekeys--;
343 
344 	strncpy((char *)sk->k.MD5_key, (const char *)key,
345 		sizeof(sk->k.MD5_key));
346 	if ((sk->keylen = len) > sizeof(sk->k.MD5_key))
347 	    sk->keylen = sizeof(sk->k.MD5_key);
348 
349 	sk->keyid = keyno;
350 	sk->flags = KEY_MD5;
351 	sk->lifetime = 0;
352 	sk->next = key_hash[KEYHASH(keyno)];
353 	key_hash[KEYHASH(keyno)] = sk;
354 	authnumkeys++;
355 	return;
356 }
357 
358 /*
359  * auth_delkeys - delete all known keys, in preparation for rereading
360  *		  the keys file (presumably)
361  */
362 void
363 auth_delkeys(void)
364 {
365 	struct savekey *sk;
366 	struct savekey **skp;
367 	int i;
368 
369 	for (i = 0; i < HASHSIZE; i++) {
370 		skp = &(key_hash[i]);
371 		sk = key_hash[i];
372 		/*
373 		 * Leave autokey keys alone.
374 		 */
375 		while (sk != 0 && sk->keyid <= NTP_MAXKEY) {
376 			/*
377 			 * Don't lose info as to which keys are trusted.
378 			 */
379 			if (sk->flags & KEY_TRUSTED) {
380 				skp = &(sk->next);
381 				memset(&sk->k, 0, sizeof(sk->k));
382 				sk->lifetime = 0;
383 				sk->keylen = 0;
384 				sk = sk->next;
385 			} else {
386 				*skp = sk->next;
387 				authnumkeys--;
388 				sk->next = authfreekeys;
389 				authfreekeys = sk;
390 				authnumfreekeys++;
391 				sk = *skp;
392 			}
393 		}
394 	}
395 }
396 
397 /*
398  * auth_agekeys - delete keys whose lifetimes have expired
399  */
400 void
401 auth_agekeys(void)
402 {
403 	struct savekey *sk;
404 	struct savekey *skp;
405 	int i;
406 
407 	for (i = 0; i < HASHSIZE; i++) {
408 		sk = skp = key_hash[i];
409 		while (sk != 0) {
410 			skp = sk->next;
411 			if (sk->lifetime > 0 && current_time >
412 			    sk->lifetime) {
413 				authtrust(sk->keyid, 0);
414 				authkeyexpired++;
415 			}
416 			sk = skp;
417 		}
418 	}
419 #ifdef DEBUG
420 	if (debug)
421 		printf("auth_agekeys: at %lu keys %lu expired %lu\n",
422 		    current_time, authnumkeys, authkeyexpired);
423 #endif
424 }
425 
426 /*
427  * authencrypt - generate message authenticator
428  *
429  * Returns length of authenticator field, zero if key not found.
430  */
431 int
432 authencrypt(
433 	keyid_t keyno,
434 	u_int32 *pkt,
435 	int length
436 	)
437 {
438 
439 	/*
440 	 * A zero key identifier means the sender has not verified
441 	 * the last message was correctly authenticated. The MAC
442 	 * consists of a single word with value zero.
443 	 */
444 	authencryptions++;
445 	pkt[length / 4] = htonl(keyno);
446 	if (keyno == 0) {
447 		return (4);
448 	}
449 	if (!authhavekey(keyno))
450 		return (0);
451 
452 	if (cache_flags & KEY_MD5)
453 		return (MD5authencrypt(cache_key, pkt, length));
454 
455 	return (0);
456 }
457 
458 /*
459  * authdecrypt - verify message authenticator
460  *
461  * Returns one if authenticator valid, zero if invalid or key not found.
462  */
463 int
464 authdecrypt(
465 	keyid_t keyno,
466 	u_int32 *pkt,
467 	int length,
468 	int size
469 	)
470 {
471 
472 	/*
473 	 * A zero key identifier means the sender has not verified
474 	 * the last message was correctly authenticated. Nevertheless,
475 	 * the authenticator itself is considered valid.
476 	 */
477 	authdecryptions++;
478 	if (keyno == 0)
479 		return (0);
480 
481 	if (!authhavekey(keyno) || size < 4)
482 		return (0);
483 
484 	if (cache_flags & KEY_MD5)
485 		return (MD5authdecrypt(cache_key, pkt, length, size));
486 
487 	return (0);
488 }
489