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 */
22struct 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
45struct savekey *key_hash[HASHSIZE];
46
47u_long authkeynotfound;		/* keys not found */
48u_long authkeylookups;		/* calls to lookup keys */
49u_long authnumkeys;		/* number of active keys */
50u_long authkeyexpired;		/* key lifetime expirations */
51u_long authkeyuncached;		/* cache misses */
52u_long authnokey;		/* calls to encrypt with no key */
53u_long authencryptions;		/* calls to encrypt */
54u_long authdecryptions;		/* calls to decrypt */
55
56/*
57 * Storage for free key structures.  We malloc() such things but
58 * never free them.
59 */
60struct savekey *authfreekeys;
61int 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 */
68keyid_t	cache_keyid;		/* key identifier */
69u_char	*cache_key;		/* key pointer */
70u_int	cache_keylen;		/* key length */
71u_short cache_flags;		/* flags that wave */
72
73
74/*
75 * init_auth - initialize internal data
76 */
77void
78init_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 */
90struct savekey *
91auth_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 */
111int
112auth_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 */
135int
136authhavekey(
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 */
174int
175auth_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 */
196void
197authtrust(
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 */
273int
274authistrusted(
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
301void
302MD5auth_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 */
362void
363auth_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 */
400void
401auth_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 */
431int
432authencrypt(
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 */
463int
464authdecrypt(
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