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