xref: /freebsd/contrib/ntp/libntp/authkeys.c (revision f0574f5cf69e168cc4ea71ebbe5fdec9ec9a3dfe)
1c0b746e5SOllivier Robert /*
2c0b746e5SOllivier Robert  * authkeys.c - routines to manage the storage of authentication keys
3c0b746e5SOllivier Robert  */
4c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H
5c0b746e5SOllivier Robert # include <config.h>
6c0b746e5SOllivier Robert #endif
7c0b746e5SOllivier Robert 
82b15cb3dSCy Schubert #include <math.h>
9c0b746e5SOllivier Robert #include <stdio.h>
10c0b746e5SOllivier Robert 
11c0b746e5SOllivier Robert #include "ntp.h"
122b15cb3dSCy Schubert #include "ntp_fp.h"
13c0b746e5SOllivier Robert #include "ntpd.h"
142b15cb3dSCy Schubert #include "ntp_lists.h"
15c0b746e5SOllivier Robert #include "ntp_string.h"
16c0b746e5SOllivier Robert #include "ntp_malloc.h"
17c0b746e5SOllivier Robert #include "ntp_stdlib.h"
1868ba7e87SXin LI #include "ntp_keyacc.h"
19c0b746e5SOllivier Robert 
20c0b746e5SOllivier Robert /*
21c0b746e5SOllivier Robert  * Structure to store keys in in the hash table.
22c0b746e5SOllivier Robert  */
232b15cb3dSCy Schubert typedef struct savekey symkey;
242b15cb3dSCy Schubert 
25c0b746e5SOllivier Robert struct savekey {
262b15cb3dSCy Schubert 	symkey *	hlink;		/* next in hash bucket */
272b15cb3dSCy Schubert 	DECL_DLIST_LINK(symkey, llink);	/* for overall & free lists */
282b15cb3dSCy Schubert 	u_char *	secret;		/* shared secret */
2968ba7e87SXin LI 	KeyAccT *	keyacclist;	/* Private key access list */
30c0b746e5SOllivier Robert 	u_long		lifetime;	/* remaining lifetime */
312b15cb3dSCy Schubert 	keyid_t		keyid;		/* key identifier */
322b15cb3dSCy Schubert 	u_short		type;		/* OpenSSL digest NID */
334990d495SXin LI 	size_t		secretsize;	/* secret octets */
342b15cb3dSCy Schubert 	u_short		flags;		/* KEY_ flags that wave */
35c0b746e5SOllivier Robert };
36c0b746e5SOllivier Robert 
372b15cb3dSCy Schubert /* define the payload region of symkey beyond the list pointers */
382b15cb3dSCy Schubert #define symkey_payload	secret
39c0b746e5SOllivier Robert 
402b15cb3dSCy Schubert #define	KEY_TRUSTED	0x001	/* this key is trusted */
412b15cb3dSCy Schubert 
422b15cb3dSCy Schubert #ifdef DEBUG
432b15cb3dSCy Schubert typedef struct symkey_alloc_tag symkey_alloc;
442b15cb3dSCy Schubert 
452b15cb3dSCy Schubert struct symkey_alloc_tag {
462b15cb3dSCy Schubert 	symkey_alloc *	link;
472b15cb3dSCy Schubert 	void *		mem;		/* enable free() atexit */
482b15cb3dSCy Schubert };
492b15cb3dSCy Schubert 
502b15cb3dSCy Schubert symkey_alloc *	authallocs;
512b15cb3dSCy Schubert #endif	/* DEBUG */
522b15cb3dSCy Schubert 
5368ba7e87SXin LI static u_short	auth_log2(size_t);
542b15cb3dSCy Schubert static void		auth_resize_hashtable(void);
554990d495SXin LI static void		allocsymkey(keyid_t,	u_short,
564990d495SXin LI 				    u_short, u_long, size_t, u_char *, KeyAccT *);
574990d495SXin LI static void		freesymkey(symkey *);
582b15cb3dSCy Schubert #ifdef DEBUG
592b15cb3dSCy Schubert static void		free_auth_mem(void);
602b15cb3dSCy Schubert #endif
612b15cb3dSCy Schubert 
622b15cb3dSCy Schubert symkey	key_listhead;		/* list of all in-use keys */;
63c0b746e5SOllivier Robert /*
64c0b746e5SOllivier Robert  * The hash table. This is indexed by the low order bits of the
65c0b746e5SOllivier Robert  * keyid. We make this fairly big for potentially busy servers.
66c0b746e5SOllivier Robert  */
672b15cb3dSCy Schubert #define	DEF_AUTHHASHSIZE	64
683311ff84SXin LI /*#define	HASHMASK	((HASHSIZE)-1)*/
692b15cb3dSCy Schubert #define	KEYHASH(keyid)	((keyid) & authhashmask)
70c0b746e5SOllivier Robert 
712b15cb3dSCy Schubert int	authhashdisabled;
722b15cb3dSCy Schubert u_short	authhashbuckets = DEF_AUTHHASHSIZE;
732b15cb3dSCy Schubert u_short authhashmask = DEF_AUTHHASHSIZE - 1;
742b15cb3dSCy Schubert symkey **key_hash;
75c0b746e5SOllivier Robert 
76c0b746e5SOllivier Robert u_long authkeynotfound;		/* keys not found */
77c0b746e5SOllivier Robert u_long authkeylookups;		/* calls to lookup keys */
78c0b746e5SOllivier Robert u_long authnumkeys;		/* number of active keys */
79c0b746e5SOllivier Robert u_long authkeyexpired;		/* key lifetime expirations */
80c0b746e5SOllivier Robert u_long authkeyuncached;		/* cache misses */
81c0b746e5SOllivier Robert u_long authnokey;		/* calls to encrypt with no key */
82c0b746e5SOllivier Robert u_long authencryptions;		/* calls to encrypt */
83c0b746e5SOllivier Robert u_long authdecryptions;		/* calls to decrypt */
84c0b746e5SOllivier Robert 
85c0b746e5SOllivier Robert /*
862b15cb3dSCy Schubert  * Storage for free symkey structures.  We malloc() such things but
87c0b746e5SOllivier Robert  * never free them.
88c0b746e5SOllivier Robert  */
892b15cb3dSCy Schubert symkey *authfreekeys;
90c0b746e5SOllivier Robert int authnumfreekeys;
91c0b746e5SOllivier Robert 
922b15cb3dSCy Schubert #define	MEMINC	16		/* number of new free ones to get */
93c0b746e5SOllivier Robert 
94c0b746e5SOllivier Robert /*
95c0b746e5SOllivier Robert  * The key cache. We cache the last key we looked at here.
964990d495SXin LI  * Note: this should hold the last *trusted* key. Also the
974990d495SXin LI  * cache is only loaded when the digest type / MAC algorithm
984990d495SXin LI  * is valid.
99c0b746e5SOllivier Robert  */
100224ba2bdSOllivier Robert keyid_t	cache_keyid;		/* key identifier */
1012b15cb3dSCy Schubert u_char *cache_secret;		/* secret */
1024990d495SXin LI size_t	cache_secretsize;	/* secret length */
1032b15cb3dSCy Schubert int	cache_type;		/* OpenSSL digest NID */
104c0b746e5SOllivier Robert u_short cache_flags;		/* flags that wave */
10568ba7e87SXin LI KeyAccT *cache_keyacclist;	/* key access list */
106c0b746e5SOllivier Robert 
1074990d495SXin LI /* --------------------------------------------------------------------
1084990d495SXin LI  * manage key access lists
1094990d495SXin LI  * --------------------------------------------------------------------
1104990d495SXin LI  */
1114990d495SXin LI /* allocate and populate new access node and pushes it on the list.
1124990d495SXin LI  * Returns the new head.
1134990d495SXin LI  */
1144990d495SXin LI KeyAccT*
1154990d495SXin LI keyacc_new_push(
1164990d495SXin LI 	KeyAccT          * head,
1174990d495SXin LI 	const sockaddr_u * addr
1184990d495SXin LI 	)
1194990d495SXin LI {
1204990d495SXin LI 	KeyAccT *	node = emalloc(sizeof(KeyAccT));
1214990d495SXin LI 
1224990d495SXin LI 	memcpy(&node->addr, addr, sizeof(sockaddr_u));
1234990d495SXin LI 	node->next = head;
1244990d495SXin LI 	return node;
1254990d495SXin LI }
1264990d495SXin LI 
1274990d495SXin LI /* ----------------------------------------------------------------- */
1284990d495SXin LI /* pop and deallocate the first node of a list of access nodes, if
1294990d495SXin LI  * the list is not empty. Returns the tail of the list.
1304990d495SXin LI  */
1314990d495SXin LI KeyAccT*
1324990d495SXin LI keyacc_pop_free(
1334990d495SXin LI 	KeyAccT *head
1344990d495SXin LI 	)
1354990d495SXin LI {
1364990d495SXin LI 	KeyAccT *	next = NULL;
1374990d495SXin LI 	if (head) {
1384990d495SXin LI 		next = head->next;
1394990d495SXin LI 		free(head);
1404990d495SXin LI 	}
1414990d495SXin LI 	return next;
1424990d495SXin LI }
1434990d495SXin LI 
1444990d495SXin LI /* ----------------------------------------------------------------- */
1454990d495SXin LI /* deallocate the list; returns an empty list. */
1464990d495SXin LI KeyAccT*
1474990d495SXin LI keyacc_all_free(
1484990d495SXin LI 	KeyAccT * head
1494990d495SXin LI 	)
1504990d495SXin LI {
1514990d495SXin LI 	while (head)
1524990d495SXin LI 		head = keyacc_pop_free(head);
1534990d495SXin LI 	return head;
1544990d495SXin LI }
1554990d495SXin LI 
1564990d495SXin LI /* ----------------------------------------------------------------- */
1574990d495SXin LI /* scan a list to see if it contains a given address. Return the
1584990d495SXin LI  * default result value in case of an empty list.
1594990d495SXin LI  */
1604990d495SXin LI int /*BOOL*/
1614990d495SXin LI keyacc_contains(
1624990d495SXin LI 	const KeyAccT    *head,
1634990d495SXin LI 	const sockaddr_u *addr,
1644990d495SXin LI 	int               defv)
1654990d495SXin LI {
1664990d495SXin LI 	if (head) {
1674990d495SXin LI 		do {
1684990d495SXin LI 			if (SOCK_EQ(&head->addr, addr))
1694990d495SXin LI 				return TRUE;
1704990d495SXin LI 		} while (NULL != (head = head->next));
1714990d495SXin LI 		return FALSE;
1724990d495SXin LI 	} else {
1734990d495SXin LI 		return !!defv;
1744990d495SXin LI 	}
1754990d495SXin LI }
1764990d495SXin LI 
177c0b746e5SOllivier Robert 
178c0b746e5SOllivier Robert /*
179c0b746e5SOllivier Robert  * init_auth - initialize internal data
180c0b746e5SOllivier Robert  */
181c0b746e5SOllivier Robert void
182c0b746e5SOllivier Robert init_auth(void)
183c0b746e5SOllivier Robert {
1842b15cb3dSCy Schubert 	size_t newalloc;
1852b15cb3dSCy Schubert 
186c0b746e5SOllivier Robert 	/*
187c0b746e5SOllivier Robert 	 * Initialize hash table and free list
188c0b746e5SOllivier Robert 	 */
1892b15cb3dSCy Schubert 	newalloc = authhashbuckets * sizeof(key_hash[0]);
1902b15cb3dSCy Schubert 
1912b15cb3dSCy Schubert 	key_hash = erealloc(key_hash, newalloc);
1922b15cb3dSCy Schubert 	memset(key_hash, '\0', newalloc);
1932b15cb3dSCy Schubert 
1942b15cb3dSCy Schubert 	INIT_DLIST(key_listhead, llink);
1952b15cb3dSCy Schubert 
1962b15cb3dSCy Schubert #ifdef DEBUG
1972b15cb3dSCy Schubert 	atexit(&free_auth_mem);
1982b15cb3dSCy Schubert #endif
1992b15cb3dSCy Schubert }
2002b15cb3dSCy Schubert 
2012b15cb3dSCy Schubert 
2022b15cb3dSCy Schubert /*
2032b15cb3dSCy Schubert  * free_auth_mem - assist in leak detection by freeing all dynamic
2042b15cb3dSCy Schubert  *		   allocations from this module.
2052b15cb3dSCy Schubert  */
2062b15cb3dSCy Schubert #ifdef DEBUG
2072b15cb3dSCy Schubert static void
2082b15cb3dSCy Schubert free_auth_mem(void)
2092b15cb3dSCy Schubert {
2102b15cb3dSCy Schubert 	symkey *	sk;
2112b15cb3dSCy Schubert 	symkey_alloc *	alloc;
2122b15cb3dSCy Schubert 	symkey_alloc *	next_alloc;
2132b15cb3dSCy Schubert 
2142b15cb3dSCy Schubert 	while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) {
2154990d495SXin LI 		freesymkey(sk);
2162b15cb3dSCy Schubert 	}
2172b15cb3dSCy Schubert 	free(key_hash);
2182b15cb3dSCy Schubert 	key_hash = NULL;
2192b15cb3dSCy Schubert 	cache_keyid = 0;
2202b15cb3dSCy Schubert 	cache_flags = 0;
22168ba7e87SXin LI 	cache_keyacclist = NULL;
2222b15cb3dSCy Schubert 	for (alloc = authallocs; alloc != NULL; alloc = next_alloc) {
2232b15cb3dSCy Schubert 		next_alloc = alloc->link;
2242b15cb3dSCy Schubert 		free(alloc->mem);
2252b15cb3dSCy Schubert 	}
2262b15cb3dSCy Schubert 	authfreekeys = NULL;
2272b15cb3dSCy Schubert 	authnumfreekeys = 0;
2282b15cb3dSCy Schubert }
2292b15cb3dSCy Schubert #endif	/* DEBUG */
2302b15cb3dSCy Schubert 
2312b15cb3dSCy Schubert 
2322b15cb3dSCy Schubert /*
2332b15cb3dSCy Schubert  * auth_moremem - get some more free key structures
2342b15cb3dSCy Schubert  */
2352b15cb3dSCy Schubert void
2362b15cb3dSCy Schubert auth_moremem(
2372b15cb3dSCy Schubert 	int	keycount
2382b15cb3dSCy Schubert 	)
2392b15cb3dSCy Schubert {
2402b15cb3dSCy Schubert 	symkey *	sk;
2412b15cb3dSCy Schubert 	int		i;
2422b15cb3dSCy Schubert #ifdef DEBUG
2432b15cb3dSCy Schubert 	void *		base;
2442b15cb3dSCy Schubert 	symkey_alloc *	allocrec;
2452b15cb3dSCy Schubert # define MOREMEM_EXTRA_ALLOC	(sizeof(*allocrec))
2462b15cb3dSCy Schubert #else
2472b15cb3dSCy Schubert # define MOREMEM_EXTRA_ALLOC	(0)
2482b15cb3dSCy Schubert #endif
2492b15cb3dSCy Schubert 
2502b15cb3dSCy Schubert 	i = (keycount > 0)
2512b15cb3dSCy Schubert 		? keycount
2522b15cb3dSCy Schubert 		: MEMINC;
253*f0574f5cSXin LI 	sk = eallocarrayxz(i, sizeof(*sk), MOREMEM_EXTRA_ALLOC);
2542b15cb3dSCy Schubert #ifdef DEBUG
2552b15cb3dSCy Schubert 	base = sk;
2562b15cb3dSCy Schubert #endif
2572b15cb3dSCy Schubert 	authnumfreekeys += i;
2582b15cb3dSCy Schubert 
2592b15cb3dSCy Schubert 	for (; i > 0; i--, sk++) {
2602b15cb3dSCy Schubert 		LINK_SLIST(authfreekeys, sk, llink.f);
2612b15cb3dSCy Schubert 	}
2622b15cb3dSCy Schubert 
2632b15cb3dSCy Schubert #ifdef DEBUG
2642b15cb3dSCy Schubert 	allocrec = (void *)sk;
2652b15cb3dSCy Schubert 	allocrec->mem = base;
2662b15cb3dSCy Schubert 	LINK_SLIST(authallocs, allocrec, link);
2672b15cb3dSCy Schubert #endif
2682b15cb3dSCy Schubert }
2692b15cb3dSCy Schubert 
2702b15cb3dSCy Schubert 
2712b15cb3dSCy Schubert /*
2722b15cb3dSCy Schubert  * auth_prealloc_symkeys
2732b15cb3dSCy Schubert  */
2742b15cb3dSCy Schubert void
2752b15cb3dSCy Schubert auth_prealloc_symkeys(
2762b15cb3dSCy Schubert 	int	keycount
2772b15cb3dSCy Schubert 	)
2782b15cb3dSCy Schubert {
2792b15cb3dSCy Schubert 	int	allocated;
2802b15cb3dSCy Schubert 	int	additional;
2812b15cb3dSCy Schubert 
2822b15cb3dSCy Schubert 	allocated = authnumkeys + authnumfreekeys;
2832b15cb3dSCy Schubert 	additional = keycount - allocated;
2842b15cb3dSCy Schubert 	if (additional > 0)
2852b15cb3dSCy Schubert 		auth_moremem(additional);
2862b15cb3dSCy Schubert 	auth_resize_hashtable();
2872b15cb3dSCy Schubert }
2882b15cb3dSCy Schubert 
2892b15cb3dSCy Schubert 
29068ba7e87SXin LI static u_short
29168ba7e87SXin LI auth_log2(size_t x)
2922b15cb3dSCy Schubert {
29368ba7e87SXin LI 	/*
29468ba7e87SXin LI 	** bithack to calculate floor(log2(x))
29568ba7e87SXin LI 	**
29668ba7e87SXin LI 	** This assumes
29768ba7e87SXin LI 	**   - (sizeof(size_t) is a power of two
29868ba7e87SXin LI 	**   - CHAR_BITS is a power of two
29968ba7e87SXin LI 	**   - returning zero for arguments <= 0 is OK.
30068ba7e87SXin LI 	**
30168ba7e87SXin LI 	** Does only shifts, masks and sums in integer arithmetic in
30268ba7e87SXin LI 	** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for
30368ba7e87SXin LI 	** 32bit/64bit size_t)
30468ba7e87SXin LI 	*/
30568ba7e87SXin LI 	int	s;
30668ba7e87SXin LI 	int	r = 0;
30768ba7e87SXin LI 	size_t  m = ~(size_t)0;
30868ba7e87SXin LI 
30968ba7e87SXin LI 	for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) {
31068ba7e87SXin LI 		m <<= s;
31168ba7e87SXin LI 		if (x & m)
31268ba7e87SXin LI 			r += s;
31368ba7e87SXin LI 		else
31468ba7e87SXin LI 			x <<= s;
31568ba7e87SXin LI 	}
31668ba7e87SXin LI 	return (u_short)r;
3172b15cb3dSCy Schubert }
3182b15cb3dSCy Schubert 
3194990d495SXin LI static void
3204990d495SXin LI authcache_flush_id(
3214990d495SXin LI 	keyid_t id
3224990d495SXin LI 	)
3234990d495SXin LI {
3244990d495SXin LI 	if (cache_keyid == id) {
3254990d495SXin LI 		cache_keyid = 0;
3264990d495SXin LI 		cache_type = 0;
3274990d495SXin LI 		cache_flags = 0;
3284990d495SXin LI 		cache_secret = NULL;
3294990d495SXin LI 		cache_secretsize = 0;
3304990d495SXin LI 		cache_keyacclist = NULL;
3314990d495SXin LI 	}
3324990d495SXin LI }
3334990d495SXin LI 
3342b15cb3dSCy Schubert 
3352b15cb3dSCy Schubert /*
3362b15cb3dSCy Schubert  * auth_resize_hashtable
3372b15cb3dSCy Schubert  *
3382b15cb3dSCy Schubert  * Size hash table to average 4 or fewer entries per bucket initially,
3392b15cb3dSCy Schubert  * within the bounds of at least 4 and no more than 15 bits for the hash
3402b15cb3dSCy Schubert  * table index.  Populate the hash table.
3412b15cb3dSCy Schubert  */
3422b15cb3dSCy Schubert static void
3432b15cb3dSCy Schubert auth_resize_hashtable(void)
3442b15cb3dSCy Schubert {
3452b15cb3dSCy Schubert 	u_long		totalkeys;
3462b15cb3dSCy Schubert 	u_short		hashbits;
3472b15cb3dSCy Schubert 	u_short		hash;
3482b15cb3dSCy Schubert 	size_t		newalloc;
3492b15cb3dSCy Schubert 	symkey *	sk;
3502b15cb3dSCy Schubert 
3512b15cb3dSCy Schubert 	totalkeys = authnumkeys + authnumfreekeys;
35268ba7e87SXin LI 	hashbits = auth_log2(totalkeys / 4) + 1;
3532b15cb3dSCy Schubert 	hashbits = max(4, hashbits);
3542b15cb3dSCy Schubert 	hashbits = min(15, hashbits);
3552b15cb3dSCy Schubert 
3562b15cb3dSCy Schubert 	authhashbuckets = 1 << hashbits;
3572b15cb3dSCy Schubert 	authhashmask = authhashbuckets - 1;
3582b15cb3dSCy Schubert 	newalloc = authhashbuckets * sizeof(key_hash[0]);
3592b15cb3dSCy Schubert 
3602b15cb3dSCy Schubert 	key_hash = erealloc(key_hash, newalloc);
3612b15cb3dSCy Schubert 	memset(key_hash, '\0', newalloc);
3622b15cb3dSCy Schubert 
3632b15cb3dSCy Schubert 	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
3642b15cb3dSCy Schubert 		hash = KEYHASH(sk->keyid);
3652b15cb3dSCy Schubert 		LINK_SLIST(key_hash[hash], sk, hlink);
3662b15cb3dSCy Schubert 	ITER_DLIST_END()
3672b15cb3dSCy Schubert }
3682b15cb3dSCy Schubert 
3692b15cb3dSCy Schubert 
3702b15cb3dSCy Schubert /*
3712b15cb3dSCy Schubert  * allocsymkey - common code to allocate and link in symkey
3722b15cb3dSCy Schubert  *
3732b15cb3dSCy Schubert  * secret must be allocated with a free-compatible allocator.  It is
3742b15cb3dSCy Schubert  * owned by the referring symkey structure, and will be free()d by
3752b15cb3dSCy Schubert  * freesymkey().
3762b15cb3dSCy Schubert  */
3772b15cb3dSCy Schubert static void
3782b15cb3dSCy Schubert allocsymkey(
3792b15cb3dSCy Schubert 	keyid_t		id,
3802b15cb3dSCy Schubert 	u_short		flags,
3812b15cb3dSCy Schubert 	u_short		type,
3822b15cb3dSCy Schubert 	u_long		lifetime,
3834990d495SXin LI 	size_t		secretsize,
38468ba7e87SXin LI 	u_char *	secret,
38568ba7e87SXin LI 	KeyAccT *	ka
3862b15cb3dSCy Schubert 	)
3872b15cb3dSCy Schubert {
3882b15cb3dSCy Schubert 	symkey *	sk;
3894990d495SXin LI 	symkey **	bucket;
3904990d495SXin LI 
3914990d495SXin LI 	bucket = &key_hash[KEYHASH(id)];
3924990d495SXin LI 
3932b15cb3dSCy Schubert 
3942b15cb3dSCy Schubert 	if (authnumfreekeys < 1)
3952b15cb3dSCy Schubert 		auth_moremem(-1);
3962b15cb3dSCy Schubert 	UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f);
3972b15cb3dSCy Schubert 	DEBUG_ENSURE(sk != NULL);
3982b15cb3dSCy Schubert 	sk->keyid = id;
3992b15cb3dSCy Schubert 	sk->flags = flags;
4002b15cb3dSCy Schubert 	sk->type = type;
4012b15cb3dSCy Schubert 	sk->secretsize = secretsize;
4022b15cb3dSCy Schubert 	sk->secret = secret;
40368ba7e87SXin LI 	sk->keyacclist = ka;
4042b15cb3dSCy Schubert 	sk->lifetime = lifetime;
4052b15cb3dSCy Schubert 	LINK_SLIST(*bucket, sk, hlink);
4062b15cb3dSCy Schubert 	LINK_TAIL_DLIST(key_listhead, sk, llink);
4072b15cb3dSCy Schubert 	authnumfreekeys--;
4082b15cb3dSCy Schubert 	authnumkeys++;
4092b15cb3dSCy Schubert }
4102b15cb3dSCy Schubert 
4112b15cb3dSCy Schubert 
4122b15cb3dSCy Schubert /*
4132b15cb3dSCy Schubert  * freesymkey - common code to remove a symkey and recycle its entry.
4142b15cb3dSCy Schubert  */
4152b15cb3dSCy Schubert static void
4162b15cb3dSCy Schubert freesymkey(
4174990d495SXin LI 	symkey *	sk
4182b15cb3dSCy Schubert 	)
4192b15cb3dSCy Schubert {
4204990d495SXin LI 	symkey **	bucket;
4212b15cb3dSCy Schubert 	symkey *	unlinked;
4222b15cb3dSCy Schubert 
4234990d495SXin LI 	if (NULL == sk)
4244990d495SXin LI 		return;
4254990d495SXin LI 
4264990d495SXin LI 	authcache_flush_id(sk->keyid);
4274990d495SXin LI 	keyacc_all_free(sk->keyacclist);
4284990d495SXin LI 
4294990d495SXin LI 	bucket = &key_hash[KEYHASH(sk->keyid)];
4302b15cb3dSCy Schubert 	if (sk->secret != NULL) {
4312b15cb3dSCy Schubert 		memset(sk->secret, '\0', sk->secretsize);
4322b15cb3dSCy Schubert 		free(sk->secret);
4332b15cb3dSCy Schubert 	}
4342b15cb3dSCy Schubert 	UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey);
4352b15cb3dSCy Schubert 	DEBUG_ENSURE(sk == unlinked);
4362b15cb3dSCy Schubert 	UNLINK_DLIST(sk, llink);
4372b15cb3dSCy Schubert 	memset((char *)sk + offsetof(symkey, symkey_payload), '\0',
4382b15cb3dSCy Schubert 	       sizeof(*sk) - offsetof(symkey, symkey_payload));
4392b15cb3dSCy Schubert 	LINK_SLIST(authfreekeys, sk, llink.f);
4402b15cb3dSCy Schubert 	authnumkeys--;
4412b15cb3dSCy Schubert 	authnumfreekeys++;
442c0b746e5SOllivier Robert }
443c0b746e5SOllivier Robert 
444c0b746e5SOllivier Robert 
445c0b746e5SOllivier Robert /*
446c0b746e5SOllivier Robert  * auth_findkey - find a key in the hash table
447c0b746e5SOllivier Robert  */
448c0b746e5SOllivier Robert struct savekey *
449c0b746e5SOllivier Robert auth_findkey(
4502b15cb3dSCy Schubert 	keyid_t		id
451c0b746e5SOllivier Robert 	)
452c0b746e5SOllivier Robert {
4532b15cb3dSCy Schubert 	symkey *	sk;
454c0b746e5SOllivier Robert 
4554990d495SXin LI 	for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink)
4564990d495SXin LI 		if (id == sk->keyid)
4572b15cb3dSCy Schubert 			return sk;
4582b15cb3dSCy Schubert 	return NULL;
459c0b746e5SOllivier Robert }
460c0b746e5SOllivier Robert 
461c0b746e5SOllivier Robert 
462c0b746e5SOllivier Robert /*
4634990d495SXin LI  * auth_havekey - return TRUE if the key id is zero or known. The
4644990d495SXin LI  * key needs not to be trusted.
465c0b746e5SOllivier Robert  */
466c0b746e5SOllivier Robert int
467c0b746e5SOllivier Robert auth_havekey(
4682b15cb3dSCy Schubert 	keyid_t		id
469c0b746e5SOllivier Robert 	)
470c0b746e5SOllivier Robert {
4714990d495SXin LI 	return
4724990d495SXin LI 	    (0           == id) ||
4734990d495SXin LI 	    (cache_keyid == id) ||
4744990d495SXin LI 	    (NULL        != auth_findkey(id));
475c0b746e5SOllivier Robert }
476c0b746e5SOllivier Robert 
477c0b746e5SOllivier Robert 
478c0b746e5SOllivier Robert /*
4792b15cb3dSCy Schubert  * authhavekey - return TRUE and cache the key, if zero or both known
4802b15cb3dSCy Schubert  *		 and trusted.
481c0b746e5SOllivier Robert  */
482c0b746e5SOllivier Robert int
483c0b746e5SOllivier Robert authhavekey(
4842b15cb3dSCy Schubert 	keyid_t		id
485c0b746e5SOllivier Robert 	)
486c0b746e5SOllivier Robert {
4872b15cb3dSCy Schubert 	symkey *	sk;
488c0b746e5SOllivier Robert 
489c0b746e5SOllivier Robert 	authkeylookups++;
4904990d495SXin LI 	if (0 == id || cache_keyid == id)
4914990d495SXin LI 		return !!(KEY_TRUSTED & cache_flags);
492c0b746e5SOllivier Robert 
493c0b746e5SOllivier Robert 	/*
4944990d495SXin LI 	 * Search the bin for the key. If not found, or found but the key
4954990d495SXin LI 	 * type is zero, somebody marked it trusted without specifying a
4964990d495SXin LI 	 * key or key type. In this case consider the key missing.
497c0b746e5SOllivier Robert 	 */
4982b15cb3dSCy Schubert 	authkeyuncached++;
4994990d495SXin LI 	sk = auth_findkey(id);
5004990d495SXin LI 	if ((sk == NULL) || (sk->type == 0)) {
5012b15cb3dSCy Schubert 		authkeynotfound++;
5022b15cb3dSCy Schubert 		return FALSE;
503c0b746e5SOllivier Robert 	}
5042b15cb3dSCy Schubert 
5052b15cb3dSCy Schubert 	/*
5064990d495SXin LI 	 * If the key is not trusted, the key is not considered found.
5072b15cb3dSCy Schubert 	 */
5082b15cb3dSCy Schubert 	if ( ! (KEY_TRUSTED & sk->flags)) {
5092b15cb3dSCy Schubert 		authnokey++;
5102b15cb3dSCy Schubert 		return FALSE;
5112b15cb3dSCy Schubert 	}
5122b15cb3dSCy Schubert 
5132b15cb3dSCy Schubert 	/*
5142b15cb3dSCy Schubert 	 * The key is found and trusted. Initialize the key cache.
5152b15cb3dSCy Schubert 	 */
5162b15cb3dSCy Schubert 	cache_keyid = sk->keyid;
5172b15cb3dSCy Schubert 	cache_type = sk->type;
5182b15cb3dSCy Schubert 	cache_flags = sk->flags;
5192b15cb3dSCy Schubert 	cache_secret = sk->secret;
5202b15cb3dSCy Schubert 	cache_secretsize = sk->secretsize;
52168ba7e87SXin LI 	cache_keyacclist = sk->keyacclist;
5222b15cb3dSCy Schubert 
5232b15cb3dSCy Schubert 	return TRUE;
524c0b746e5SOllivier Robert }
525c0b746e5SOllivier Robert 
526c0b746e5SOllivier Robert 
527c0b746e5SOllivier Robert /*
528c0b746e5SOllivier Robert  * authtrust - declare a key to be trusted/untrusted
529c0b746e5SOllivier Robert  */
530c0b746e5SOllivier Robert void
531c0b746e5SOllivier Robert authtrust(
5322b15cb3dSCy Schubert 	keyid_t		id,
533224ba2bdSOllivier Robert 	u_long		trust
534c0b746e5SOllivier Robert 	)
535c0b746e5SOllivier Robert {
5362b15cb3dSCy Schubert 	symkey *	sk;
5372b15cb3dSCy Schubert 	u_long		lifetime;
538c0b746e5SOllivier Robert 
5392b15cb3dSCy Schubert 	/*
5402b15cb3dSCy Schubert 	 * Search bin for key; if it does not exist and is untrusted,
5412b15cb3dSCy Schubert 	 * forget it.
5422b15cb3dSCy Schubert 	 */
5434990d495SXin LI 
5444990d495SXin LI 	sk = auth_findkey(id);
5454990d495SXin LI 	if (!trust && sk == NULL)
546c0b746e5SOllivier Robert 		return;
547c0b746e5SOllivier Robert 
5482b15cb3dSCy Schubert 	/*
5492b15cb3dSCy Schubert 	 * There are two conditions remaining. Either it does not
5502b15cb3dSCy Schubert 	 * exist and is to be trusted or it does exist and is or is
5512b15cb3dSCy Schubert 	 * not to be trusted.
5522b15cb3dSCy Schubert 	 */
5532b15cb3dSCy Schubert 	if (sk != NULL) {
5542b15cb3dSCy Schubert 		/*
5554990d495SXin LI 		 * Key exists. If it is to be trusted, say so and update
5564990d495SXin LI 		 * its lifetime. If no longer trusted, return it to the
5574990d495SXin LI 		 * free list. Flush the cache first to be sure there are
5584990d495SXin LI 		 * no discrepancies.
5592b15cb3dSCy Schubert 		 */
5604990d495SXin LI 		authcache_flush_id(id);
561c0b746e5SOllivier Robert 		if (trust > 0) {
562c0b746e5SOllivier Robert 			sk->flags |= KEY_TRUSTED;
563c0b746e5SOllivier Robert 			if (trust > 1)
564c0b746e5SOllivier Robert 				sk->lifetime = current_time + trust;
565c0b746e5SOllivier Robert 			else
566c0b746e5SOllivier Robert 				sk->lifetime = 0;
5674990d495SXin LI 		} else {
5684990d495SXin LI 			freesymkey(sk);
569c0b746e5SOllivier Robert 		}
5702b15cb3dSCy Schubert 		return;
5712b15cb3dSCy Schubert 	}
572c0b746e5SOllivier Robert 
5732b15cb3dSCy Schubert 	/*
5742b15cb3dSCy Schubert 	 * keyid is not present, but the is to be trusted.  We allocate
5752b15cb3dSCy Schubert 	 * a new key, but do not specify a key type or secret.
5762b15cb3dSCy Schubert 	 */
5772b15cb3dSCy Schubert 	if (trust > 1) {
5782b15cb3dSCy Schubert 		lifetime = current_time + trust;
579c0b746e5SOllivier Robert 	} else {
5802b15cb3dSCy Schubert 		lifetime = 0;
581c0b746e5SOllivier Robert 	}
5824990d495SXin LI 	allocsymkey(id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL);
583c0b746e5SOllivier Robert }
584c0b746e5SOllivier Robert 
585c0b746e5SOllivier Robert 
586c0b746e5SOllivier Robert /*
587c0b746e5SOllivier Robert  * authistrusted - determine whether a key is trusted
588c0b746e5SOllivier Robert  */
589c0b746e5SOllivier Robert int
590c0b746e5SOllivier Robert authistrusted(
5914990d495SXin LI 	keyid_t		id
592c0b746e5SOllivier Robert 	)
593c0b746e5SOllivier Robert {
5942b15cb3dSCy Schubert 	symkey *	sk;
595c0b746e5SOllivier Robert 
5964990d495SXin LI 	if (id == cache_keyid)
5972b15cb3dSCy Schubert 		return !!(KEY_TRUSTED & cache_flags);
598c0b746e5SOllivier Robert 
599c0b746e5SOllivier Robert 	authkeyuncached++;
6004990d495SXin LI 	sk = auth_findkey(id);
6014990d495SXin LI 	if (sk == NULL || !(KEY_TRUSTED & sk->flags)) {
602c0b746e5SOllivier Robert 		authkeynotfound++;
6032b15cb3dSCy Schubert 		return FALSE;
604c0b746e5SOllivier Robert 	}
6052b15cb3dSCy Schubert 	return TRUE;
606c0b746e5SOllivier Robert }
607c0b746e5SOllivier Robert 
60868ba7e87SXin LI 
60968ba7e87SXin LI /*
61068ba7e87SXin LI  * authistrustedip - determine if the IP is OK for the keyid
61168ba7e87SXin LI  */
61268ba7e87SXin LI  int
61368ba7e87SXin LI  authistrustedip(
61468ba7e87SXin LI  	keyid_t		keyno,
61568ba7e87SXin LI 	sockaddr_u *	sau
61668ba7e87SXin LI 	)
61768ba7e87SXin LI {
61868ba7e87SXin LI 	symkey *	sk;
61968ba7e87SXin LI 
6204990d495SXin LI 	/* That specific key was already used to authenticate the
6214990d495SXin LI 	 * packet. Therefore, the key *must* exist...  There's a chance
6224990d495SXin LI 	 * that is not trusted, though.
6234990d495SXin LI 	 */
6244990d495SXin LI 	if (keyno == cache_keyid) {
6254990d495SXin LI 		return (KEY_TRUSTED & cache_flags) &&
6264990d495SXin LI 		    keyacc_contains(cache_keyacclist, sau, TRUE);
6274990d495SXin LI 	} else {
62868ba7e87SXin LI 		authkeyuncached++;
6294990d495SXin LI 		sk = auth_findkey(keyno);
6304990d495SXin LI 		INSIST(NULL != sk);
6314990d495SXin LI 		return (KEY_TRUSTED & sk->flags) &&
6324990d495SXin LI 		    keyacc_contains(sk->keyacclist, sau, TRUE);
63368ba7e87SXin LI 	}
63468ba7e87SXin LI }
63568ba7e87SXin LI 
6363311ff84SXin LI /* Note: There are two locations below where 'strncpy()' is used. While
6373311ff84SXin LI  * this function is a hazard by itself, it's essential that it is used
6383311ff84SXin LI  * here. Bug 1243 involved that the secret was filled with NUL bytes
6393311ff84SXin LI  * after the first NUL encountered, and 'strlcpy()' simply does NOT have
6403311ff84SXin LI  * this behaviour. So disabling the fix and reverting to the buggy
6413311ff84SXin LI  * behaviour due to compatibility issues MUST also fill with NUL and
6423311ff84SXin LI  * this needs 'strncpy'. Also, the secret is managed as a byte blob of a
6433311ff84SXin LI  * given size, and eventually truncating it and replacing the last byte
6443311ff84SXin LI  * with a NUL would be a bug.
6453311ff84SXin LI  * perlinger@ntp.org 2015-10-10
6463311ff84SXin LI  */
647c0b746e5SOllivier Robert void
648c0b746e5SOllivier Robert MD5auth_setkey(
649224ba2bdSOllivier Robert 	keyid_t keyno,
6502b15cb3dSCy Schubert 	int	keytype,
651c0b746e5SOllivier Robert 	const u_char *key,
6524990d495SXin LI 	size_t secretsize,
65368ba7e87SXin LI 	KeyAccT *ka
654c0b746e5SOllivier Robert 	)
655c0b746e5SOllivier Robert {
6562b15cb3dSCy Schubert 	symkey *	sk;
6572b15cb3dSCy Schubert 	u_char *	secret;
658c0b746e5SOllivier Robert 
6592b15cb3dSCy Schubert 	DEBUG_ENSURE(keytype <= USHRT_MAX);
6604990d495SXin LI 	DEBUG_ENSURE(secretsize < 4 * 1024);
661c0b746e5SOllivier Robert 	/*
662c0b746e5SOllivier Robert 	 * See if we already have the key.  If so just stick in the
663c0b746e5SOllivier Robert 	 * new value.
664c0b746e5SOllivier Robert 	 */
6654990d495SXin LI 	sk = auth_findkey(keyno);
6664990d495SXin LI 	if (sk != NULL && keyno == sk->keyid) {
6679034852cSGleb Smirnoff 			/* TALOS-CAN-0054: make sure we have a new buffer! */
6689034852cSGleb Smirnoff 		if (NULL != sk->secret) {
6699034852cSGleb Smirnoff 			memset(sk->secret, 0, sk->secretsize);
6709034852cSGleb Smirnoff 			free(sk->secret);
6719034852cSGleb Smirnoff 		}
6724990d495SXin LI 		sk->secret = emalloc(secretsize + 1);
6732b15cb3dSCy Schubert 		sk->type = (u_short)keytype;
6744990d495SXin LI 		sk->secretsize = secretsize;
6754990d495SXin LI 		/* make sure access lists don't leak here! */
6764990d495SXin LI 		if (ka != sk->keyacclist) {
6774990d495SXin LI 			keyacc_all_free(sk->keyacclist);
67868ba7e87SXin LI 			sk->keyacclist = ka;
6794990d495SXin LI 		}
6802b15cb3dSCy Schubert #ifndef DISABLE_BUG1243_FIX
6812b15cb3dSCy Schubert 		memcpy(sk->secret, key, secretsize);
6822b15cb3dSCy Schubert #else
6833311ff84SXin LI 		/* >MUST< use 'strncpy()' here! See above! */
6843311ff84SXin LI 		strncpy((char *)sk->secret, (const char *)key,
6852b15cb3dSCy Schubert 			secretsize);
6862b15cb3dSCy Schubert #endif
6874990d495SXin LI 		authcache_flush_id(keyno);
688c0b746e5SOllivier Robert 		return;
689c0b746e5SOllivier Robert 	}
690c0b746e5SOllivier Robert 
691c0b746e5SOllivier Robert 	/*
692c0b746e5SOllivier Robert 	 * Need to allocate new structure.  Do it.
693c0b746e5SOllivier Robert 	 */
6944990d495SXin LI 	secret = emalloc(secretsize + 1);
6952b15cb3dSCy Schubert #ifndef DISABLE_BUG1243_FIX
6962b15cb3dSCy Schubert 	memcpy(secret, key, secretsize);
6972b15cb3dSCy Schubert #else
6983311ff84SXin LI 	/* >MUST< use 'strncpy()' here! See above! */
6993311ff84SXin LI 	strncpy((char *)secret, (const char *)key, secretsize);
7002b15cb3dSCy Schubert #endif
7014990d495SXin LI 	allocsymkey(keyno, 0, (u_short)keytype, 0,
7024990d495SXin LI 		    secretsize, secret, ka);
7032b15cb3dSCy Schubert #ifdef DEBUG
7042b15cb3dSCy Schubert 	if (debug >= 4) {
7052b15cb3dSCy Schubert 		size_t	j;
7062b15cb3dSCy Schubert 
7072b15cb3dSCy Schubert 		printf("auth_setkey: key %d type %d len %d ", (int)keyno,
7082b15cb3dSCy Schubert 		    keytype, (int)secretsize);
7094990d495SXin LI 		for (j = 0; j < secretsize; j++) {
7102b15cb3dSCy Schubert 			printf("%02x", secret[j]);
7114990d495SXin LI 		}
7122b15cb3dSCy Schubert 		printf("\n");
7132b15cb3dSCy Schubert 	}
7142b15cb3dSCy Schubert #endif
715c0b746e5SOllivier Robert }
716c0b746e5SOllivier Robert 
717c0b746e5SOllivier Robert 
718c0b746e5SOllivier Robert /*
7192b15cb3dSCy Schubert  * auth_delkeys - delete non-autokey untrusted keys, and clear all info
7202b15cb3dSCy Schubert  *                except the trusted bit of non-autokey trusted keys, in
7212b15cb3dSCy Schubert  *		  preparation for rereading the keys file.
722c0b746e5SOllivier Robert  */
723c0b746e5SOllivier Robert void
724c0b746e5SOllivier Robert auth_delkeys(void)
725c0b746e5SOllivier Robert {
7262b15cb3dSCy Schubert 	symkey *	sk;
727c0b746e5SOllivier Robert 
7282b15cb3dSCy Schubert 	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
7292b15cb3dSCy Schubert 		if (sk->keyid > NTP_MAXKEY) {	/* autokey */
7302b15cb3dSCy Schubert 			continue;
7312b15cb3dSCy Schubert 		}
7322b15cb3dSCy Schubert 
733c0b746e5SOllivier Robert 		/*
7349034852cSGleb Smirnoff 		 * Don't lose info as to which keys are trusted. Make
7359034852cSGleb Smirnoff 		 * sure there are no dangling pointers!
736c0b746e5SOllivier Robert 		 */
7372b15cb3dSCy Schubert 		if (KEY_TRUSTED & sk->flags) {
7382b15cb3dSCy Schubert 			if (sk->secret != NULL) {
7399034852cSGleb Smirnoff 				memset(sk->secret, 0, sk->secretsize);
7402b15cb3dSCy Schubert 				free(sk->secret);
7419034852cSGleb Smirnoff 				sk->secret = NULL; /* TALOS-CAN-0054 */
7422b15cb3dSCy Schubert 			}
7434990d495SXin LI 			sk->keyacclist = keyacc_all_free(sk->keyacclist);
7442b15cb3dSCy Schubert 			sk->secretsize = 0;
745c0b746e5SOllivier Robert 			sk->lifetime = 0;
746c0b746e5SOllivier Robert 		} else {
7474990d495SXin LI 			freesymkey(sk);
748c0b746e5SOllivier Robert 		}
7492b15cb3dSCy Schubert 	ITER_DLIST_END()
750c0b746e5SOllivier Robert }
7512b15cb3dSCy Schubert 
752c0b746e5SOllivier Robert 
753c0b746e5SOllivier Robert /*
754c0b746e5SOllivier Robert  * auth_agekeys - delete keys whose lifetimes have expired
755c0b746e5SOllivier Robert  */
756c0b746e5SOllivier Robert void
757c0b746e5SOllivier Robert auth_agekeys(void)
758c0b746e5SOllivier Robert {
7592b15cb3dSCy Schubert 	symkey *	sk;
760c0b746e5SOllivier Robert 
7612b15cb3dSCy Schubert 	ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey)
7622b15cb3dSCy Schubert 		if (sk->lifetime > 0 && current_time > sk->lifetime) {
7634990d495SXin LI 			freesymkey(sk);
764c0b746e5SOllivier Robert 			authkeyexpired++;
765c0b746e5SOllivier Robert 		}
7662b15cb3dSCy Schubert 	ITER_DLIST_END()
7672b15cb3dSCy Schubert 	DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n",
7682b15cb3dSCy Schubert 		    current_time, authnumkeys, authkeyexpired));
769c0b746e5SOllivier Robert }
7702b15cb3dSCy Schubert 
771c0b746e5SOllivier Robert 
772c0b746e5SOllivier Robert /*
773c0b746e5SOllivier Robert  * authencrypt - generate message authenticator
774c0b746e5SOllivier Robert  *
775c0b746e5SOllivier Robert  * Returns length of authenticator field, zero if key not found.
776c0b746e5SOllivier Robert  */
7773311ff84SXin LI size_t
778c0b746e5SOllivier Robert authencrypt(
779224ba2bdSOllivier Robert 	keyid_t		keyno,
780c0b746e5SOllivier Robert 	u_int32 *	pkt,
7813311ff84SXin LI 	size_t		length
782c0b746e5SOllivier Robert 	)
7833311ff84SXin LI {
784c0b746e5SOllivier Robert 	/*
785c0b746e5SOllivier Robert 	 * A zero key identifier means the sender has not verified
786c0b746e5SOllivier Robert 	 * the last message was correctly authenticated. The MAC
787c0b746e5SOllivier Robert 	 * consists of a single word with value zero.
788c0b746e5SOllivier Robert 	 */
789c0b746e5SOllivier Robert 	authencryptions++;
790224ba2bdSOllivier Robert 	pkt[length / 4] = htonl(keyno);
7912b15cb3dSCy Schubert 	if (0 == keyno) {
7922b15cb3dSCy Schubert 		return 4;
793c0b746e5SOllivier Robert 	}
7942b15cb3dSCy Schubert 	if (!authhavekey(keyno)) {
7952b15cb3dSCy Schubert 		return 0;
796c0b746e5SOllivier Robert 	}
797c0b746e5SOllivier Robert 
7982b15cb3dSCy Schubert 	return MD5authencrypt(cache_type, cache_secret, pkt, length);
7992b15cb3dSCy Schubert }
8002b15cb3dSCy Schubert 
8012b15cb3dSCy Schubert 
802c0b746e5SOllivier Robert /*
803c0b746e5SOllivier Robert  * authdecrypt - verify message authenticator
804c0b746e5SOllivier Robert  *
8052b15cb3dSCy Schubert  * Returns TRUE if authenticator valid, FALSE if invalid or not found.
806c0b746e5SOllivier Robert  */
807c0b746e5SOllivier Robert int
808c0b746e5SOllivier Robert authdecrypt(
809224ba2bdSOllivier Robert 	keyid_t		keyno,
810c0b746e5SOllivier Robert 	u_int32 *	pkt,
8113311ff84SXin LI 	size_t		length,
8123311ff84SXin LI 	size_t		size
813c0b746e5SOllivier Robert 	)
814c0b746e5SOllivier Robert {
815c0b746e5SOllivier Robert 	/*
816c0b746e5SOllivier Robert 	 * A zero key identifier means the sender has not verified
8172b15cb3dSCy Schubert 	 * the last message was correctly authenticated.  For our
8182b15cb3dSCy Schubert 	 * purpose this is an invalid authenticator.
819c0b746e5SOllivier Robert 	 */
820c0b746e5SOllivier Robert 	authdecryptions++;
8212b15cb3dSCy Schubert 	if (0 == keyno || !authhavekey(keyno) || size < 4) {
8222b15cb3dSCy Schubert 		return FALSE;
8232b15cb3dSCy Schubert 	}
824c0b746e5SOllivier Robert 
8252b15cb3dSCy Schubert 	return MD5authdecrypt(cache_type, cache_secret, pkt, length,
8262b15cb3dSCy Schubert 			      size);
827c0b746e5SOllivier Robert }
828