4 * authkeys.c - routines to manage the storage of authentication keys
13 #include "ntp_types.h"
17 #include "ntp_string.h"
18 #include "ntp_malloc.h"
19 #include "ntp_stdlib.h"
22 * Structure to store keys in in the hash table.
27 long bogon
; /* Make sure nonempty */
28 u_char MD5_key
[32]; /* MD5 key */
30 keyid_t keyid
; /* key identifier */
31 u_short flags
; /* flags that wave */
32 u_long lifetime
; /* remaining lifetime */
33 int keylen
; /* key length */
36 #define KEY_TRUSTED 0x001 /* this key is trusted */
37 #define KEY_MD5 0x200 /* this is a MD5 type key */
40 * The hash table. This is indexed by the low order bits of the
41 * keyid. We make this fairly big for potentially busy servers.
44 #define HASHMASK ((HASHSIZE)-1)
45 #define KEYHASH(keyid) ((keyid) & HASHMASK)
47 struct savekey
*key_hash
[HASHSIZE
];
49 u_long authkeynotfound
; /* keys not found */
50 u_long authkeylookups
; /* calls to lookup keys */
51 u_long authnumkeys
; /* number of active keys */
52 u_long authkeyexpired
; /* key lifetime expirations */
53 u_long authkeyuncached
; /* cache misses */
54 u_long authnokey
; /* calls to encrypt with no key */
55 u_long authencryptions
; /* calls to encrypt */
56 u_long authdecryptions
; /* calls to decrypt */
59 * Storage for free key structures. We malloc() such things but
62 struct savekey
*authfreekeys
;
65 #define MEMINC 12 /* number of new free ones to get */
68 * The key cache. We cache the last key we looked at here.
70 keyid_t cache_keyid
; /* key identifier */
71 u_char
*cache_key
; /* key pointer */
72 u_int cache_keylen
; /* key length */
73 u_short cache_flags
; /* flags that wave */
77 * init_auth - initialize internal data
83 * Initialize hash table and free list
85 memset((char *)key_hash
, 0, sizeof key_hash
);
90 * auth_findkey - find a key in the hash table
99 sk
= key_hash
[KEYHASH(keyno
)];
101 if (keyno
== sk
->keyid
)
111 * auth_havekey - return one if the key is known
120 if (keyno
== 0 || (keyno
== cache_keyid
))
123 sk
= key_hash
[KEYHASH(keyno
)];
125 if (keyno
== sk
->keyid
)
135 * authhavekey - return one and cache the key, if known and trusted.
145 if (keyno
== 0 || keyno
== cache_keyid
)
149 sk
= key_hash
[KEYHASH(keyno
)];
151 if (keyno
== sk
->keyid
)
158 } else if (!(sk
->flags
& KEY_TRUSTED
)) {
162 cache_keyid
= sk
->keyid
;
163 cache_flags
= sk
->flags
;
164 if (sk
->flags
& KEY_MD5
) {
165 cache_key
= sk
->k
.MD5_key
;
166 cache_keylen
= sk
->keylen
;
174 * auth_moremem - get some more free key structures
182 sk
= (struct savekey
*)calloc(MEMINC
, sizeof(struct savekey
));
186 for (i
= MEMINC
; i
> 0; i
--) {
187 sk
->next
= authfreekeys
;
190 authnumfreekeys
+= MEMINC
;
191 return (authnumfreekeys
);
196 * authtrust - declare a key to be trusted/untrusted
208 printf("authtrust: keyid %08x life %lu\n", keyno
, trust
);
210 sk
= key_hash
[KEYHASH(keyno
)];
212 if (keyno
== sk
->keyid
)
217 if (sk
== 0 && !trust
)
221 if (cache_keyid
== keyno
) {
227 sk
->flags
|= KEY_TRUSTED
;
229 sk
->lifetime
= current_time
+ trust
;
235 sk
->flags
&= ~KEY_TRUSTED
; {
238 skp
= key_hash
[KEYHASH(keyno
)];
240 key_hash
[KEYHASH(keyno
)] = sk
->next
;
242 while (skp
->next
!= sk
)
244 skp
->next
= sk
->next
;
248 sk
->next
= authfreekeys
;
255 if (authnumfreekeys
== 0)
256 if (auth_moremem() == 0)
260 authfreekeys
= sk
->next
;
264 sk
->flags
= KEY_TRUSTED
;
265 sk
->next
= key_hash
[KEYHASH(keyno
)];
266 key_hash
[KEYHASH(keyno
)] = sk
;
273 * authistrusted - determine whether a key is trusted
282 if (keyno
== cache_keyid
)
283 return ((cache_flags
& KEY_TRUSTED
) != 0);
286 sk
= key_hash
[KEYHASH(keyno
)];
288 if (keyno
== sk
->keyid
)
295 } else if (!(sk
->flags
& KEY_TRUSTED
)) {
313 * See if we already have the key. If so just stick in the
316 sk
= key_hash
[KEYHASH(keyno
)];
318 if (keyno
== sk
->keyid
) {
319 strncpy((char *)sk
->k
.MD5_key
, (const char *)key
,
320 sizeof(sk
->k
.MD5_key
));
321 if ((sk
->keylen
= len
) > sizeof(sk
->k
.MD5_key
))
322 sk
->keylen
= sizeof(sk
->k
.MD5_key
);
324 sk
->flags
|= KEY_MD5
;
325 if (cache_keyid
== keyno
) {
335 * Need to allocate new structure. Do it.
337 if (authnumfreekeys
== 0) {
338 if (auth_moremem() == 0)
343 authfreekeys
= sk
->next
;
346 strncpy((char *)sk
->k
.MD5_key
, (const char *)key
,
347 sizeof(sk
->k
.MD5_key
));
348 if ((sk
->keylen
= len
) > sizeof(sk
->k
.MD5_key
))
349 sk
->keylen
= sizeof(sk
->k
.MD5_key
);
354 sk
->next
= key_hash
[KEYHASH(keyno
)];
355 key_hash
[KEYHASH(keyno
)] = sk
;
361 * auth_delkeys - delete all known keys, in preparation for rereading
362 * the keys file (presumably)
368 struct savekey
**skp
;
371 for (i
= 0; i
< HASHSIZE
; i
++) {
372 skp
= &(key_hash
[i
]);
375 * Leave autokey keys alone.
377 while (sk
!= 0 && sk
->keyid
<= NTP_MAXKEY
) {
379 * Don't lose info as to which keys are trusted.
381 if (sk
->flags
& KEY_TRUSTED
) {
383 memset(&sk
->k
, 0, sizeof(sk
->k
));
390 sk
->next
= authfreekeys
;
400 * auth_agekeys - delete keys whose lifetimes have expired
409 for (i
= 0; i
< HASHSIZE
; i
++) {
410 sk
= skp
= key_hash
[i
];
413 if (sk
->lifetime
> 0 && current_time
>
415 authtrust(sk
->keyid
, 0);
423 printf("auth_agekeys: at %lu keys %lu expired %lu\n",
424 current_time
, authnumkeys
, authkeyexpired
);
429 * authencrypt - generate message authenticator
431 * Returns length of authenticator field, zero if key not found.
442 * A zero key identifier means the sender has not verified
443 * the last message was correctly authenticated. The MAC
444 * consists of a single word with value zero.
447 pkt
[length
/ 4] = htonl(keyno
);
451 if (!authhavekey(keyno
))
454 if (cache_flags
& KEY_MD5
)
455 return (MD5authencrypt(cache_key
, pkt
, length
));
461 * authdecrypt - verify message authenticator
463 * Returns one if authenticator valid, zero if invalid or key not found.
475 * A zero key identifier means the sender has not verified
476 * the last message was correctly authenticated. Nevertheless,
477 * the authenticator itself is considered valid.
483 if (!authhavekey(keyno
) || size
< 4)
486 if (cache_flags
& KEY_MD5
)
487 return (MD5authdecrypt(cache_key
, pkt
, length
, size
));