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