1 /* $NetBSD: authkeys.c,v 1.9 2016/01/08 21:35:38 christos Exp $ */ 2 3 /* 4 * authkeys.c - routines to manage the storage of authentication keys 5 */ 6 #ifdef HAVE_CONFIG_H 7 # include <config.h> 8 #endif 9 10 #include <math.h> 11 #include <stdio.h> 12 13 #include "ntp.h" 14 #include "ntp_fp.h" 15 #include "ntpd.h" 16 #include "ntp_lists.h" 17 #include "ntp_string.h" 18 #include "ntp_malloc.h" 19 #include "ntp_stdlib.h" 20 21 /* 22 * Structure to store keys in in the hash table. 23 */ 24 typedef struct savekey symkey; 25 26 struct savekey { 27 symkey * hlink; /* next in hash bucket */ 28 DECL_DLIST_LINK(symkey, llink); /* for overall & free lists */ 29 u_char * secret; /* shared secret */ 30 u_long lifetime; /* remaining lifetime */ 31 keyid_t keyid; /* key identifier */ 32 u_short type; /* OpenSSL digest NID */ 33 u_short secretsize; /* secret octets */ 34 u_short flags; /* KEY_ flags that wave */ 35 }; 36 37 /* define the payload region of symkey beyond the list pointers */ 38 #define symkey_payload secret 39 40 #define KEY_TRUSTED 0x001 /* this key is trusted */ 41 42 #ifdef DEBUG 43 typedef struct symkey_alloc_tag symkey_alloc; 44 45 struct symkey_alloc_tag { 46 symkey_alloc * link; 47 void * mem; /* enable free() atexit */ 48 }; 49 50 symkey_alloc * authallocs; 51 #endif /* DEBUG */ 52 53 static inline u_short auth_log2(double x); 54 static void auth_resize_hashtable(void); 55 static void allocsymkey(symkey **, keyid_t, u_short, 56 u_short, u_long, u_short, u_char *); 57 static void freesymkey(symkey *, symkey **); 58 #ifdef DEBUG 59 static void free_auth_mem(void); 60 #endif 61 62 symkey key_listhead; /* list of all in-use keys */; 63 /* 64 * The hash table. This is indexed by the low order bits of the 65 * keyid. We make this fairly big for potentially busy servers. 66 */ 67 #define DEF_AUTHHASHSIZE 64 68 /*#define HASHMASK ((HASHSIZE)-1)*/ 69 #define KEYHASH(keyid) ((keyid) & authhashmask) 70 71 int authhashdisabled; 72 u_short authhashbuckets = DEF_AUTHHASHSIZE; 73 u_short authhashmask = DEF_AUTHHASHSIZE - 1; 74 symkey **key_hash; 75 76 u_long authkeynotfound; /* keys not found */ 77 u_long authkeylookups; /* calls to lookup keys */ 78 u_long authnumkeys; /* number of active keys */ 79 u_long authkeyexpired; /* key lifetime expirations */ 80 u_long authkeyuncached; /* cache misses */ 81 u_long authnokey; /* calls to encrypt with no key */ 82 u_long authencryptions; /* calls to encrypt */ 83 u_long authdecryptions; /* calls to decrypt */ 84 85 /* 86 * Storage for free symkey structures. We malloc() such things but 87 * never free them. 88 */ 89 symkey *authfreekeys; 90 int authnumfreekeys; 91 92 #define MEMINC 16 /* number of new free ones to get */ 93 94 /* 95 * The key cache. We cache the last key we looked at here. 96 */ 97 keyid_t cache_keyid; /* key identifier */ 98 u_char *cache_secret; /* secret */ 99 u_short cache_secretsize; /* secret length */ 100 int cache_type; /* OpenSSL digest NID */ 101 u_short cache_flags; /* flags that wave */ 102 103 104 /* 105 * init_auth - initialize internal data 106 */ 107 void 108 init_auth(void) 109 { 110 size_t newalloc; 111 112 /* 113 * Initialize hash table and free list 114 */ 115 newalloc = authhashbuckets * sizeof(key_hash[0]); 116 117 key_hash = erealloc(key_hash, newalloc); 118 memset(key_hash, '\0', newalloc); 119 120 INIT_DLIST(key_listhead, llink); 121 122 #ifdef DEBUG 123 atexit(&free_auth_mem); 124 #endif 125 } 126 127 128 /* 129 * free_auth_mem - assist in leak detection by freeing all dynamic 130 * allocations from this module. 131 */ 132 #ifdef DEBUG 133 static void 134 free_auth_mem(void) 135 { 136 symkey * sk; 137 symkey_alloc * alloc; 138 symkey_alloc * next_alloc; 139 140 while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) { 141 freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]); 142 } 143 free(key_hash); 144 key_hash = NULL; 145 cache_keyid = 0; 146 cache_flags = 0; 147 for (alloc = authallocs; alloc != NULL; alloc = next_alloc) { 148 next_alloc = alloc->link; 149 free(alloc->mem); 150 } 151 authfreekeys = NULL; 152 authnumfreekeys = 0; 153 } 154 #endif /* DEBUG */ 155 156 157 /* 158 * auth_moremem - get some more free key structures 159 */ 160 void 161 auth_moremem( 162 int keycount 163 ) 164 { 165 symkey * sk; 166 int i; 167 #ifdef DEBUG 168 void * base; 169 symkey_alloc * allocrec; 170 # define MOREMEM_EXTRA_ALLOC (sizeof(*allocrec)) 171 #else 172 # define MOREMEM_EXTRA_ALLOC (0) 173 #endif 174 175 i = (keycount > 0) 176 ? keycount 177 : MEMINC; 178 sk = emalloc_zero(i * sizeof(*sk) + MOREMEM_EXTRA_ALLOC); 179 #ifdef DEBUG 180 base = sk; 181 #endif 182 authnumfreekeys += i; 183 184 for (; i > 0; i--, sk++) { 185 LINK_SLIST(authfreekeys, sk, llink.f); 186 } 187 188 #ifdef DEBUG 189 allocrec = (void *)sk; 190 allocrec->mem = base; 191 LINK_SLIST(authallocs, allocrec, link); 192 #endif 193 } 194 195 196 /* 197 * auth_prealloc_symkeys 198 */ 199 void 200 auth_prealloc_symkeys( 201 int keycount 202 ) 203 { 204 int allocated; 205 int additional; 206 207 allocated = authnumkeys + authnumfreekeys; 208 additional = keycount - allocated; 209 if (additional > 0) 210 auth_moremem(additional); 211 auth_resize_hashtable(); 212 } 213 214 215 static inline u_short 216 auth_log2(double x) 217 { 218 return (u_short)(log10(x) / log10(2)); 219 } 220 221 222 /* 223 * auth_resize_hashtable 224 * 225 * Size hash table to average 4 or fewer entries per bucket initially, 226 * within the bounds of at least 4 and no more than 15 bits for the hash 227 * table index. Populate the hash table. 228 */ 229 static void 230 auth_resize_hashtable(void) 231 { 232 u_long totalkeys; 233 u_short hashbits; 234 u_short hash; 235 size_t newalloc; 236 symkey * sk; 237 238 totalkeys = authnumkeys + authnumfreekeys; 239 hashbits = (totalkeys <= 4 ? 0 : auth_log2(totalkeys / 4.0)) + 1; 240 hashbits = max(4, hashbits); 241 hashbits = min(15, hashbits); 242 243 authhashbuckets = 1 << hashbits; 244 authhashmask = authhashbuckets - 1; 245 newalloc = authhashbuckets * sizeof(key_hash[0]); 246 247 key_hash = erealloc(key_hash, newalloc); 248 memset(key_hash, '\0', newalloc); 249 250 ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 251 hash = KEYHASH(sk->keyid); 252 LINK_SLIST(key_hash[hash], sk, hlink); 253 ITER_DLIST_END() 254 } 255 256 257 /* 258 * allocsymkey - common code to allocate and link in symkey 259 * 260 * secret must be allocated with a free-compatible allocator. It is 261 * owned by the referring symkey structure, and will be free()d by 262 * freesymkey(). 263 */ 264 static void 265 allocsymkey( 266 symkey ** bucket, 267 keyid_t id, 268 u_short flags, 269 u_short type, 270 u_long lifetime, 271 u_short secretsize, 272 u_char * secret 273 ) 274 { 275 symkey * sk; 276 277 if (authnumfreekeys < 1) 278 auth_moremem(-1); 279 UNLINK_HEAD_SLIST(sk, authfreekeys, llink.f); 280 DEBUG_ENSURE(sk != NULL); 281 sk->keyid = id; 282 sk->flags = flags; 283 sk->type = type; 284 sk->secretsize = secretsize; 285 sk->secret = secret; 286 sk->lifetime = lifetime; 287 LINK_SLIST(*bucket, sk, hlink); 288 LINK_TAIL_DLIST(key_listhead, sk, llink); 289 authnumfreekeys--; 290 authnumkeys++; 291 } 292 293 294 /* 295 * freesymkey - common code to remove a symkey and recycle its entry. 296 */ 297 static void 298 freesymkey( 299 symkey * sk, 300 symkey ** bucket 301 ) 302 { 303 symkey * unlinked; 304 305 if (sk->secret != NULL) { 306 memset(sk->secret, '\0', sk->secretsize); 307 free(sk->secret); 308 } 309 UNLINK_SLIST(unlinked, *bucket, sk, hlink, symkey); 310 DEBUG_ENSURE(sk == unlinked); 311 UNLINK_DLIST(sk, llink); 312 memset((char *)sk + offsetof(symkey, symkey_payload), '\0', 313 sizeof(*sk) - offsetof(symkey, symkey_payload)); 314 LINK_SLIST(authfreekeys, sk, llink.f); 315 authnumkeys--; 316 authnumfreekeys++; 317 } 318 319 320 /* 321 * auth_findkey - find a key in the hash table 322 */ 323 struct savekey * 324 auth_findkey( 325 keyid_t id 326 ) 327 { 328 symkey * sk; 329 330 for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) { 331 if (id == sk->keyid) { 332 return sk; 333 } 334 } 335 336 return NULL; 337 } 338 339 340 /* 341 * auth_havekey - return TRUE if the key id is zero or known 342 */ 343 int 344 auth_havekey( 345 keyid_t id 346 ) 347 { 348 symkey * sk; 349 350 if (0 == id || cache_keyid == id) { 351 return TRUE; 352 } 353 354 for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) { 355 if (id == sk->keyid) { 356 return TRUE; 357 } 358 } 359 360 return FALSE; 361 } 362 363 364 /* 365 * authhavekey - return TRUE and cache the key, if zero or both known 366 * and trusted. 367 */ 368 int 369 authhavekey( 370 keyid_t id 371 ) 372 { 373 symkey * sk; 374 375 authkeylookups++; 376 if (0 == id || cache_keyid == id) { 377 return TRUE; 378 } 379 380 /* 381 * Seach the bin for the key. If found and the key type 382 * is zero, somebody marked it trusted without specifying 383 * a key or key type. In this case consider the key missing. 384 */ 385 authkeyuncached++; 386 for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) { 387 if (id == sk->keyid) { 388 if (0 == sk->type) { 389 authkeynotfound++; 390 return FALSE; 391 } 392 break; 393 } 394 } 395 396 /* 397 * If the key is not found, or if it is found but not trusted, 398 * the key is not considered found. 399 */ 400 if (NULL == sk) { 401 authkeynotfound++; 402 return FALSE; 403 } 404 if (!(KEY_TRUSTED & sk->flags)) { 405 authnokey++; 406 return FALSE; 407 } 408 409 /* 410 * The key is found and trusted. Initialize the key cache. 411 */ 412 cache_keyid = sk->keyid; 413 cache_type = sk->type; 414 cache_flags = sk->flags; 415 cache_secret = sk->secret; 416 cache_secretsize = sk->secretsize; 417 418 return TRUE; 419 } 420 421 422 /* 423 * authtrust - declare a key to be trusted/untrusted 424 */ 425 void 426 authtrust( 427 keyid_t id, 428 u_long trust 429 ) 430 { 431 symkey ** bucket; 432 symkey * sk; 433 u_long lifetime; 434 435 /* 436 * Search bin for key; if it does not exist and is untrusted, 437 * forget it. 438 */ 439 bucket = &key_hash[KEYHASH(id)]; 440 for (sk = *bucket; sk != NULL; sk = sk->hlink) { 441 if (id == sk->keyid) 442 break; 443 } 444 if (!trust && NULL == sk) 445 return; 446 447 /* 448 * There are two conditions remaining. Either it does not 449 * exist and is to be trusted or it does exist and is or is 450 * not to be trusted. 451 */ 452 if (sk != NULL) { 453 if (cache_keyid == id) { 454 cache_flags = 0; 455 cache_keyid = 0; 456 } 457 458 /* 459 * Key exists. If it is to be trusted, say so and 460 * update its lifetime. 461 */ 462 if (trust > 0) { 463 sk->flags |= KEY_TRUSTED; 464 if (trust > 1) 465 sk->lifetime = current_time + trust; 466 else 467 sk->lifetime = 0; 468 return; 469 } 470 471 /* No longer trusted, return it to the free list. */ 472 freesymkey(sk, bucket); 473 return; 474 } 475 476 /* 477 * keyid is not present, but the is to be trusted. We allocate 478 * a new key, but do not specify a key type or secret. 479 */ 480 if (trust > 1) { 481 lifetime = current_time + trust; 482 } else { 483 lifetime = 0; 484 } 485 allocsymkey(bucket, id, KEY_TRUSTED, 0, lifetime, 0, NULL); 486 } 487 488 489 /* 490 * authistrusted - determine whether a key is trusted 491 */ 492 int 493 authistrusted( 494 keyid_t keyno 495 ) 496 { 497 symkey * sk; 498 symkey ** bucket; 499 500 if (keyno == cache_keyid) 501 return !!(KEY_TRUSTED & cache_flags); 502 503 authkeyuncached++; 504 bucket = &key_hash[KEYHASH(keyno)]; 505 for (sk = *bucket; sk != NULL; sk = sk->hlink) { 506 if (keyno == sk->keyid) 507 break; 508 } 509 if (NULL == sk || !(KEY_TRUSTED & sk->flags)) { 510 authkeynotfound++; 511 return FALSE; 512 } 513 return TRUE; 514 } 515 516 /* Note: There are two locations below where 'strncpy()' is used. While 517 * this function is a hazard by itself, it's essential that it is used 518 * here. Bug 1243 involved that the secret was filled with NUL bytes 519 * after the first NUL encountered, and 'strlcpy()' simply does NOT have 520 * this behaviour. So disabling the fix and reverting to the buggy 521 * behaviour due to compatibility issues MUST also fill with NUL and 522 * this needs 'strncpy'. Also, the secret is managed as a byte blob of a 523 * given size, and eventually truncating it and replacing the last byte 524 * with a NUL would be a bug. 525 * perlinger@ntp.org 2015-10-10 526 */ 527 void 528 MD5auth_setkey( 529 keyid_t keyno, 530 int keytype, 531 const u_char *key, 532 size_t len 533 ) 534 { 535 symkey * sk; 536 symkey ** bucket; 537 u_char * secret; 538 size_t secretsize; 539 540 DEBUG_ENSURE(keytype <= USHRT_MAX); 541 DEBUG_ENSURE(len < 4 * 1024); 542 /* 543 * See if we already have the key. If so just stick in the 544 * new value. 545 */ 546 bucket = &key_hash[KEYHASH(keyno)]; 547 for (sk = *bucket; sk != NULL; sk = sk->hlink) { 548 if (keyno == sk->keyid) { 549 /* TALOS-CAN-0054: make sure we have a new buffer! */ 550 if (NULL != sk->secret) { 551 memset(sk->secret, 0, sk->secretsize); 552 free(sk->secret); 553 } 554 sk->secret = emalloc(len); 555 sk->type = (u_short)keytype; 556 secretsize = len; 557 sk->secretsize = (u_short)secretsize; 558 #ifndef DISABLE_BUG1243_FIX 559 memcpy(sk->secret, key, secretsize); 560 #else 561 /* >MUST< use 'strncpy()' here! See above! */ 562 strncpy((char *)sk->secret, (const char *)key, 563 secretsize); 564 #endif 565 if (cache_keyid == keyno) { 566 cache_flags = 0; 567 cache_keyid = 0; 568 } 569 return; 570 } 571 } 572 573 /* 574 * Need to allocate new structure. Do it. 575 */ 576 secretsize = len; 577 secret = emalloc(secretsize); 578 #ifndef DISABLE_BUG1243_FIX 579 memcpy(secret, key, secretsize); 580 #else 581 /* >MUST< use 'strncpy()' here! See above! */ 582 strncpy((char *)secret, (const char *)key, secretsize); 583 #endif 584 allocsymkey(bucket, keyno, 0, (u_short)keytype, 0, 585 (u_short)secretsize, secret); 586 #ifdef DEBUG 587 if (debug >= 4) { 588 size_t j; 589 590 printf("auth_setkey: key %d type %d len %d ", (int)keyno, 591 keytype, (int)secretsize); 592 for (j = 0; j < secretsize; j++) 593 printf("%02x", secret[j]); 594 printf("\n"); 595 } 596 #endif 597 } 598 599 600 /* 601 * auth_delkeys - delete non-autokey untrusted keys, and clear all info 602 * except the trusted bit of non-autokey trusted keys, in 603 * preparation for rereading the keys file. 604 */ 605 void 606 auth_delkeys(void) 607 { 608 symkey * sk; 609 610 ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 611 if (sk->keyid > NTP_MAXKEY) { /* autokey */ 612 continue; 613 } 614 615 /* 616 * Don't lose info as to which keys are trusted. Make 617 * sure there are no dangling pointers! 618 */ 619 if (KEY_TRUSTED & sk->flags) { 620 if (sk->secret != NULL) { 621 memset(sk->secret, 0, sk->secretsize); 622 free(sk->secret); 623 sk->secret = NULL; /* TALOS-CAN-0054 */ 624 } 625 sk->secretsize = 0; 626 sk->lifetime = 0; 627 } else { 628 freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]); 629 } 630 ITER_DLIST_END() 631 } 632 633 634 /* 635 * auth_agekeys - delete keys whose lifetimes have expired 636 */ 637 void 638 auth_agekeys(void) 639 { 640 symkey * sk; 641 642 ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) 643 if (sk->lifetime > 0 && current_time > sk->lifetime) { 644 freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]); 645 authkeyexpired++; 646 } 647 ITER_DLIST_END() 648 DPRINTF(1, ("auth_agekeys: at %lu keys %lu expired %lu\n", 649 current_time, authnumkeys, authkeyexpired)); 650 } 651 652 653 /* 654 * authencrypt - generate message authenticator 655 * 656 * Returns length of authenticator field, zero if key not found. 657 */ 658 size_t 659 authencrypt( 660 keyid_t keyno, 661 u_int32 * pkt, 662 size_t length 663 ) 664 { 665 /* 666 * A zero key identifier means the sender has not verified 667 * the last message was correctly authenticated. The MAC 668 * consists of a single word with value zero. 669 */ 670 authencryptions++; 671 pkt[length / 4] = htonl(keyno); 672 if (0 == keyno) { 673 return 4; 674 } 675 if (!authhavekey(keyno)) { 676 return 0; 677 } 678 679 return MD5authencrypt(cache_type, cache_secret, pkt, length); 680 } 681 682 683 /* 684 * authdecrypt - verify message authenticator 685 * 686 * Returns TRUE if authenticator valid, FALSE if invalid or not found. 687 */ 688 int 689 authdecrypt( 690 keyid_t keyno, 691 u_int32 * pkt, 692 size_t length, 693 size_t size 694 ) 695 { 696 /* 697 * A zero key identifier means the sender has not verified 698 * the last message was correctly authenticated. For our 699 * purpose this is an invalid authenticator. 700 */ 701 authdecryptions++; 702 if (0 == keyno || !authhavekey(keyno) || size < 4) { 703 return FALSE; 704 } 705 706 return MD5authdecrypt(cache_type, cache_secret, pkt, length, 707 size); 708 } 709