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