1 /* 2 * tsig.c -- TSIG implementation (RFC 2845). 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 11 #include "config.h" 12 #include <stdlib.h> 13 #include <ctype.h> 14 15 #include "tsig.h" 16 #include "tsig-openssl.h" 17 #include "dns.h" 18 #include "packet.h" 19 #include "query.h" 20 #include "rbtree.h" 21 22 #if !defined(HAVE_SSL) || !defined(HAVE_CRYPTO_MEMCMP) 23 /* we need fixed time compare */ 24 #define CRYPTO_memcmp memcmp_fixedtime 25 int memcmp_fixedtime(const void *s1, const void *s2, size_t n) 26 { 27 size_t i; 28 const uint8_t* u1 = (const uint8_t*)s1; 29 const uint8_t* u2 = (const uint8_t*)s2; 30 int ret = 0, haveit = 0, bret = 0, bhaveit = 0; 31 /* this routine loops for every byte in the strings. 32 * every loop, it tests ==, < and >. All three. One succeeds, 33 * as every time it must be equal, smaller or larger. The one 34 * that succeeds has one if-comparison and two assignments. */ 35 for(i=0; i<n; i++) { 36 if(u1[i] == u2[i]) { 37 /* waste time equal to < and > statements */ 38 if(haveit) { 39 bret = -1; /* waste time */ 40 bhaveit = 1; 41 } else { 42 bret = 1; /* waste time */ 43 bhaveit = 1; 44 } 45 } 46 if(u1[i] < u2[i]) { 47 if(haveit) { 48 bret = -1; /* waste time equal to the else */ 49 bhaveit = 1; 50 } else { 51 ret = -1; 52 haveit = 1; 53 } 54 } 55 if(u1[i] > u2[i]) { 56 if(haveit) { 57 bret = 1; /* waste time equal to the else */ 58 bhaveit = 1; 59 } else { 60 ret = 1; 61 haveit = 1; 62 } 63 } 64 } 65 /* use the variables to stop the compiler from excluding them */ 66 if(bhaveit) { 67 if(bret == -2) 68 ret = 0; /* never happens */ 69 } else { 70 if(bret == -2) 71 ret = 0; /* never happens */ 72 } 73 return ret; 74 } 75 #endif 76 77 static region_type *tsig_region; 78 79 struct tsig_key_table 80 { 81 rbnode_type node; /* by dname */ 82 tsig_key_type *key; 83 }; 84 typedef struct tsig_key_table tsig_key_table_type; 85 static rbtree_type *tsig_key_table; 86 87 struct tsig_algorithm_table 88 { 89 struct tsig_algorithm_table *next; 90 tsig_algorithm_type *algorithm; 91 }; 92 typedef struct tsig_algorithm_table tsig_algorithm_table_type; 93 static tsig_algorithm_table_type *tsig_algorithm_table; 94 static size_t max_algo_digest_size = 0; 95 96 static void 97 tsig_digest_variables(tsig_record_type *tsig, int tsig_timers_only) 98 { 99 uint16_t klass = htons(CLASS_ANY); 100 uint32_t ttl = htonl(0); 101 uint16_t signed_time_high = htons(tsig->signed_time_high); 102 uint32_t signed_time_low = htonl(tsig->signed_time_low); 103 uint16_t signed_time_fudge = htons(tsig->signed_time_fudge); 104 uint16_t error_code = htons(tsig->error_code); 105 uint16_t other_size = htons(tsig->other_size); 106 107 if (!tsig_timers_only) { 108 tsig->algorithm->hmac_update(tsig->context, 109 dname_name(tsig->key_name), 110 tsig->key_name->name_size); 111 tsig->algorithm->hmac_update(tsig->context, 112 &klass, 113 sizeof(klass)); 114 tsig->algorithm->hmac_update(tsig->context, 115 &ttl, 116 sizeof(ttl)); 117 tsig->algorithm->hmac_update(tsig->context, 118 dname_name(tsig->algorithm_name), 119 tsig->algorithm_name->name_size); 120 } 121 tsig->algorithm->hmac_update(tsig->context, 122 &signed_time_high, 123 sizeof(signed_time_high)); 124 tsig->algorithm->hmac_update(tsig->context, 125 &signed_time_low, 126 sizeof(signed_time_low)); 127 tsig->algorithm->hmac_update(tsig->context, 128 &signed_time_fudge, 129 sizeof(signed_time_fudge)); 130 if (!tsig_timers_only) { 131 tsig->algorithm->hmac_update(tsig->context, 132 &error_code, 133 sizeof(error_code)); 134 tsig->algorithm->hmac_update(tsig->context, 135 &other_size, 136 sizeof(other_size)); 137 tsig->algorithm->hmac_update(tsig->context, 138 tsig->other_data, 139 tsig->other_size); 140 } 141 } 142 143 static int 144 tree_dname_compare(const void* a, const void* b) 145 { 146 return dname_compare((const dname_type*)a, (const dname_type*)b); 147 } 148 149 int 150 tsig_init(region_type *region) 151 { 152 tsig_region = region; 153 tsig_key_table = rbtree_create(region, &tree_dname_compare); 154 tsig_algorithm_table = NULL; 155 156 #if defined(HAVE_SSL) 157 return tsig_openssl_init(region); 158 #endif /* defined(HAVE_SSL) */ 159 return 1; 160 } 161 162 void 163 tsig_add_key(tsig_key_type *key) 164 { 165 tsig_key_table_type *entry = (tsig_key_table_type *) region_alloc_zero( 166 tsig_region, sizeof(tsig_key_table_type)); 167 entry->key = key; 168 entry->node.key = entry->key->name; 169 (void)rbtree_insert(tsig_key_table, &entry->node); 170 } 171 172 void 173 tsig_del_key(tsig_key_type *key) 174 { 175 tsig_key_table_type *entry; 176 if(!key) return; 177 entry = (tsig_key_table_type*)rbtree_delete(tsig_key_table, key->name); 178 if(!entry) return; 179 region_recycle(tsig_region, entry, sizeof(tsig_key_table_type)); 180 } 181 182 tsig_key_type* 183 tsig_find_key(const dname_type* name) 184 { 185 tsig_key_table_type* entry; 186 entry = (tsig_key_table_type*)rbtree_search(tsig_key_table, name); 187 if(entry) 188 return entry->key; 189 return NULL; 190 } 191 192 void 193 tsig_add_algorithm(tsig_algorithm_type *algorithm) 194 { 195 tsig_algorithm_table_type *entry 196 = (tsig_algorithm_table_type *) region_alloc( 197 tsig_region, sizeof(tsig_algorithm_table_type)); 198 entry->algorithm = algorithm; 199 entry->next = tsig_algorithm_table; 200 tsig_algorithm_table = entry; 201 if(algorithm->maximum_digest_size > max_algo_digest_size) 202 max_algo_digest_size = algorithm->maximum_digest_size; 203 } 204 205 /** 206 * compare a tsig algorithm string lowercased 207 */ 208 int 209 tsig_strlowercmp(const char* str1, const char* str2) 210 { 211 while (str1 && str2 && *str1 != '\0' && *str2 != '\0') { 212 if(tolower((unsigned char)*str1) != tolower((unsigned char)*str2)) { 213 if(tolower((unsigned char)*str1) < tolower((unsigned char)*str2)) 214 return -1; 215 return 1; 216 } 217 str1++; 218 str2++; 219 } 220 if (str1 && str2) { 221 if (*str1 == *str2) 222 return 0; 223 else if (*str1 == '\0') 224 return -1; 225 } 226 else if (!str1 && !str2) 227 return 0; 228 else if (!str1 && str2) 229 return -1; 230 return 1; 231 } 232 233 234 /* 235 * Find an HMAC algorithm based on its short name. 236 */ 237 tsig_algorithm_type * 238 tsig_get_algorithm_by_name(const char *name) 239 { 240 tsig_algorithm_table_type *algorithm_entry; 241 242 for (algorithm_entry = tsig_algorithm_table; 243 algorithm_entry; 244 algorithm_entry = algorithm_entry->next) 245 { 246 if (tsig_strlowercmp(name, algorithm_entry->algorithm->short_name) == 0) 247 { 248 return algorithm_entry->algorithm; 249 } 250 if(strncmp("hmac-", algorithm_entry->algorithm->short_name, 5) == 0 && tsig_strlowercmp(name, algorithm_entry->algorithm->short_name+5) == 0) { 251 return algorithm_entry->algorithm; 252 } 253 } 254 255 return NULL; 256 } 257 258 259 const char * 260 tsig_error(int error_code) 261 { 262 static char message[1000]; 263 264 switch (error_code) { 265 case TSIG_ERROR_NOERROR: 266 return "No Error"; 267 break; 268 case TSIG_ERROR_BADSIG: 269 return "Bad Signature"; 270 break; 271 case TSIG_ERROR_BADKEY: 272 return "Bad Key"; 273 break; 274 case TSIG_ERROR_BADTIME: 275 return "Bad Time"; 276 break; 277 default: 278 if(error_code < 16) /* DNS rcodes */ 279 return rcode2str(error_code); 280 281 snprintf(message, sizeof(message), 282 "Unknown Error %d", error_code); 283 break; 284 } 285 return message; 286 } 287 288 static void 289 tsig_cleanup(void *data) 290 { 291 tsig_record_type *tsig = (tsig_record_type *) data; 292 region_destroy(tsig->rr_region); 293 region_destroy(tsig->context_region); 294 } 295 296 void 297 tsig_create_record(tsig_record_type *tsig, region_type *region) 298 { 299 tsig_create_record_custom(tsig, region, DEFAULT_CHUNK_SIZE, 300 DEFAULT_LARGE_OBJECT_SIZE, DEFAULT_INITIAL_CLEANUP_SIZE); 301 } 302 303 void 304 tsig_create_record_custom(tsig_record_type *tsig, region_type *region, 305 size_t chunk_size, size_t large_object_size, size_t initial_cleanup_size) 306 { 307 tsig->rr_region = region_create_custom(xalloc, free, chunk_size, 308 large_object_size, initial_cleanup_size, 0); 309 tsig->context_region = region_create_custom(xalloc, free, chunk_size, 310 large_object_size, initial_cleanup_size, 0); 311 if(region) 312 region_add_cleanup(region, tsig_cleanup, tsig); 313 tsig_init_record(tsig, NULL, NULL); 314 } 315 316 void 317 tsig_delete_record(tsig_record_type* tsig, region_type* region) 318 { 319 if(region) 320 region_remove_cleanup(region, tsig_cleanup, tsig); 321 region_destroy(tsig->rr_region); 322 region_destroy(tsig->context_region); 323 } 324 325 void 326 tsig_init_record(tsig_record_type *tsig, 327 tsig_algorithm_type *algorithm, 328 tsig_key_type *key) 329 { 330 tsig->status = TSIG_NOT_PRESENT; 331 tsig->error_code = TSIG_ERROR_NOERROR; 332 tsig->position = 0; 333 tsig->response_count = 0; 334 tsig->context = NULL; 335 tsig->algorithm = algorithm; 336 tsig->key = key; 337 tsig->prior_mac_size = 0; 338 tsig->prior_mac_data = NULL; 339 region_free_all(tsig->context_region); 340 } 341 342 int 343 tsig_from_query(tsig_record_type *tsig) 344 { 345 tsig_key_type *key = NULL; 346 tsig_algorithm_table_type *algorithm_entry; 347 tsig_algorithm_type *algorithm = NULL; 348 uint64_t current_time; 349 uint64_t signed_time; 350 351 assert(tsig->status == TSIG_OK); 352 assert(!tsig->algorithm); 353 assert(!tsig->key); 354 355 key = (tsig_key_type*)tsig_find_key(tsig->key_name); 356 357 for (algorithm_entry = tsig_algorithm_table; 358 algorithm_entry; 359 algorithm_entry = algorithm_entry->next) 360 { 361 if (dname_compare( 362 tsig->algorithm_name, 363 algorithm_entry->algorithm->wireformat_name) == 0) 364 { 365 algorithm = algorithm_entry->algorithm; 366 break; 367 } 368 } 369 370 if (!algorithm || !key) { 371 /* Algorithm or key is unknown, cannot authenticate. */ 372 tsig->error_code = TSIG_ERROR_BADKEY; 373 return 0; 374 } 375 376 if ((tsig->algorithm && algorithm != tsig->algorithm) 377 || (tsig->key && key != tsig->key)) 378 { 379 /* 380 * Algorithm or key changed during a single connection, 381 * return error. 382 */ 383 tsig->error_code = TSIG_ERROR_BADKEY; 384 return 0; 385 } 386 387 signed_time = ((((uint64_t) tsig->signed_time_high) << 32) | 388 ((uint64_t) tsig->signed_time_low)); 389 390 current_time = (uint64_t) time(NULL); 391 if ((current_time < signed_time - tsig->signed_time_fudge) 392 || (current_time > signed_time + tsig->signed_time_fudge)) 393 { 394 uint16_t current_time_high; 395 uint32_t current_time_low; 396 397 #if 0 /* debug */ 398 char current_time_text[26]; 399 char signed_time_text[26]; 400 time_t clock; 401 402 clock = (time_t) current_time; 403 ctime_r(&clock, current_time_text); 404 current_time_text[24] = '\0'; 405 406 clock = (time_t) signed_time; 407 ctime_r(&clock, signed_time_text); 408 signed_time_text[24] = '\0'; 409 410 log_msg(LOG_ERR, 411 "current server time %s is outside the range of TSIG" 412 " signed time %s with fudge %u", 413 current_time_text, 414 signed_time_text, 415 (unsigned) tsig->signed_time_fudge); 416 #endif 417 418 tsig->error_code = TSIG_ERROR_BADTIME; 419 current_time_high = (uint16_t) (current_time >> 32); 420 current_time_low = (uint32_t) current_time; 421 tsig->other_size = 6; 422 tsig->other_data = (uint8_t *) region_alloc( 423 tsig->rr_region, sizeof(uint16_t) + sizeof(uint32_t)); 424 write_uint16(tsig->other_data, current_time_high); 425 write_uint32(tsig->other_data + 2, current_time_low); 426 return 0; 427 } 428 429 tsig->algorithm = algorithm; 430 tsig->key = key; 431 tsig->response_count = 0; 432 tsig->prior_mac_size = 0; 433 434 return 1; 435 } 436 437 void 438 tsig_init_query(tsig_record_type *tsig, uint16_t original_query_id) 439 { 440 assert(tsig); 441 assert(tsig->algorithm); 442 assert(tsig->key); 443 444 tsig->response_count = 0; 445 tsig->prior_mac_size = 0; 446 tsig->algorithm_name = tsig->algorithm->wireformat_name; 447 tsig->key_name = tsig->key->name; 448 tsig->mac_size = 0; 449 tsig->mac_data = NULL; 450 tsig->original_query_id = original_query_id; 451 tsig->error_code = TSIG_ERROR_NOERROR; 452 tsig->other_size = 0; 453 tsig->other_data = NULL; 454 } 455 456 void 457 tsig_prepare(tsig_record_type *tsig) 458 { 459 if (!tsig->context) { 460 assert(tsig->algorithm); 461 tsig->context = tsig->algorithm->hmac_create_context( 462 tsig->context_region); 463 tsig->prior_mac_data = (uint8_t *) region_alloc( 464 tsig->context_region, 465 tsig->algorithm->maximum_digest_size); 466 } 467 tsig->algorithm->hmac_init_context(tsig->context, 468 tsig->algorithm, 469 tsig->key); 470 471 if (tsig->prior_mac_size > 0) { 472 uint16_t mac_size = htons(tsig->prior_mac_size); 473 tsig->algorithm->hmac_update(tsig->context, 474 &mac_size, 475 sizeof(mac_size)); 476 tsig->algorithm->hmac_update(tsig->context, 477 tsig->prior_mac_data, 478 tsig->prior_mac_size); 479 } 480 481 tsig->updates_since_last_prepare = 0; 482 } 483 484 void 485 tsig_update(tsig_record_type *tsig, buffer_type *packet, size_t length) 486 { 487 uint16_t original_query_id = htons(tsig->original_query_id); 488 489 assert(length <= buffer_limit(packet)); 490 491 tsig->algorithm->hmac_update(tsig->context, 492 &original_query_id, 493 sizeof(original_query_id)); 494 tsig->algorithm->hmac_update( 495 tsig->context, 496 buffer_at(packet, sizeof(original_query_id)), 497 length - sizeof(original_query_id)); 498 if (QR(packet)) { 499 ++tsig->response_count; 500 } 501 502 ++tsig->updates_since_last_prepare; 503 } 504 505 void 506 tsig_sign(tsig_record_type *tsig) 507 { 508 uint64_t current_time = (uint64_t) time(NULL); 509 tsig->signed_time_high = (uint16_t) (current_time >> 32); 510 tsig->signed_time_low = (uint32_t) current_time; 511 tsig->signed_time_fudge = 300; /* XXX; hardcoded value */ 512 513 tsig_digest_variables(tsig, tsig->response_count > 1); 514 515 tsig->algorithm->hmac_final(tsig->context, 516 tsig->prior_mac_data, 517 &tsig->prior_mac_size); 518 519 tsig->mac_size = tsig->prior_mac_size; 520 tsig->mac_data = tsig->prior_mac_data; 521 } 522 523 int 524 tsig_verify(tsig_record_type *tsig) 525 { 526 tsig_digest_variables(tsig, tsig->response_count > 1); 527 528 tsig->algorithm->hmac_final(tsig->context, 529 tsig->prior_mac_data, 530 &tsig->prior_mac_size); 531 532 if (tsig->mac_size != tsig->prior_mac_size 533 || CRYPTO_memcmp(tsig->mac_data, 534 tsig->prior_mac_data, 535 tsig->mac_size) != 0) 536 { 537 /* Digest is incorrect, cannot authenticate. */ 538 tsig->error_code = TSIG_ERROR_BADSIG; 539 return 0; 540 } else { 541 return 1; 542 } 543 } 544 545 int 546 tsig_find_rr(tsig_record_type *tsig, buffer_type *packet) 547 { 548 size_t saved_position = buffer_position(packet); 549 size_t rrcount = ((size_t)QDCOUNT(packet) 550 + (size_t)ANCOUNT(packet) 551 + (size_t)NSCOUNT(packet) 552 + (size_t)ARCOUNT(packet)); 553 size_t i; 554 int result; 555 556 if (ARCOUNT(packet) == 0) { 557 tsig->status = TSIG_NOT_PRESENT; 558 return 1; 559 } 560 if(rrcount > 65530) { 561 /* impossibly high number of records in 64k, reject packet */ 562 buffer_set_position(packet, saved_position); 563 return 0; 564 } 565 566 buffer_set_position(packet, QHEADERSZ); 567 568 /* TSIG must be the last record, so skip all others. */ 569 for (i = 0; i < rrcount - 1; ++i) { 570 if (!packet_skip_rr(packet, i < QDCOUNT(packet))) { 571 buffer_set_position(packet, saved_position); 572 return 0; 573 } 574 } 575 576 result = tsig_parse_rr(tsig, packet); 577 buffer_set_position(packet, saved_position); 578 return result; 579 } 580 581 int 582 tsig_parse_rr(tsig_record_type *tsig, buffer_type *packet) 583 { 584 uint16_t type; 585 uint16_t klass; 586 uint32_t ttl; 587 uint16_t rdlen; 588 589 tsig->status = TSIG_NOT_PRESENT; 590 tsig->position = buffer_position(packet); 591 tsig->key_name = NULL; 592 tsig->algorithm_name = NULL; 593 tsig->mac_data = NULL; 594 tsig->other_data = NULL; 595 region_free_all(tsig->rr_region); 596 597 tsig->key_name = dname_make_from_packet(tsig->rr_region, packet, 1, 1); 598 if (!tsig->key_name) { 599 buffer_set_position(packet, tsig->position); 600 return 0; 601 } 602 603 if (!buffer_available(packet, 10)) { 604 buffer_set_position(packet, tsig->position); 605 return 0; 606 } 607 608 type = buffer_read_u16(packet); 609 klass = buffer_read_u16(packet); 610 611 /* TSIG not present */ 612 if (type != TYPE_TSIG || klass != CLASS_ANY) { 613 buffer_set_position(packet, tsig->position); 614 return 1; 615 } 616 617 ttl = buffer_read_u32(packet); 618 rdlen = buffer_read_u16(packet); 619 620 tsig->status = TSIG_ERROR; 621 tsig->error_code = RCODE_FORMAT; 622 if (ttl != 0 || !buffer_available(packet, rdlen)) { 623 buffer_set_position(packet, tsig->position); 624 return 0; 625 } 626 627 tsig->algorithm_name = dname_make_from_packet( 628 tsig->rr_region, packet, 1, 1); 629 if (!tsig->algorithm_name || !buffer_available(packet, 10)) { 630 buffer_set_position(packet, tsig->position); 631 return 0; 632 } 633 634 tsig->signed_time_high = buffer_read_u16(packet); 635 tsig->signed_time_low = buffer_read_u32(packet); 636 tsig->signed_time_fudge = buffer_read_u16(packet); 637 tsig->mac_size = buffer_read_u16(packet); 638 if (!buffer_available(packet, tsig->mac_size)) { 639 buffer_set_position(packet, tsig->position); 640 tsig->mac_size = 0; 641 return 0; 642 } 643 if(tsig->mac_size > 16384) { 644 /* the hash should not be too big, really 512/8=64 bytes */ 645 buffer_set_position(packet, tsig->position); 646 tsig->mac_size = 0; 647 return 0; 648 } 649 tsig->mac_data = (uint8_t *) region_alloc_init( 650 tsig->rr_region, buffer_current(packet), tsig->mac_size); 651 buffer_skip(packet, tsig->mac_size); 652 if (!buffer_available(packet, 6)) { 653 buffer_set_position(packet, tsig->position); 654 return 0; 655 } 656 tsig->original_query_id = buffer_read_u16(packet); 657 tsig->error_code = buffer_read_u16(packet); 658 tsig->other_size = buffer_read_u16(packet); 659 if (!buffer_available(packet, tsig->other_size) || tsig->other_size > 16) { 660 tsig->other_size = 0; 661 buffer_set_position(packet, tsig->position); 662 return 0; 663 } 664 tsig->other_data = (uint8_t *) region_alloc_init( 665 tsig->rr_region, buffer_current(packet), tsig->other_size); 666 buffer_skip(packet, tsig->other_size); 667 tsig->status = TSIG_OK; 668 return 1; 669 } 670 671 void 672 tsig_append_rr(tsig_record_type *tsig, buffer_type *packet) 673 { 674 size_t rdlength_pos; 675 676 /* XXX: TODO key name compression? */ 677 if(tsig->key_name) 678 buffer_write(packet, dname_name(tsig->key_name), 679 tsig->key_name->name_size); 680 else buffer_write_u8(packet, 0); 681 buffer_write_u16(packet, TYPE_TSIG); 682 buffer_write_u16(packet, CLASS_ANY); 683 buffer_write_u32(packet, 0); /* TTL */ 684 rdlength_pos = buffer_position(packet); 685 buffer_skip(packet, sizeof(uint16_t)); 686 if(tsig->algorithm_name) 687 buffer_write(packet, dname_name(tsig->algorithm_name), 688 tsig->algorithm_name->name_size); 689 else buffer_write_u8(packet, 0); 690 buffer_write_u16(packet, tsig->signed_time_high); 691 buffer_write_u32(packet, tsig->signed_time_low); 692 buffer_write_u16(packet, tsig->signed_time_fudge); 693 buffer_write_u16(packet, tsig->mac_size); 694 buffer_write(packet, tsig->mac_data, tsig->mac_size); 695 buffer_write_u16(packet, tsig->original_query_id); 696 buffer_write_u16(packet, tsig->error_code); 697 buffer_write_u16(packet, tsig->other_size); 698 buffer_write(packet, tsig->other_data, tsig->other_size); 699 700 buffer_write_u16_at(packet, rdlength_pos, 701 buffer_position(packet) - rdlength_pos 702 - sizeof(uint16_t)); 703 } 704 705 size_t 706 tsig_reserved_space(tsig_record_type *tsig) 707 { 708 if (tsig->status == TSIG_NOT_PRESENT) 709 return 0; 710 711 return ( 712 (tsig->key_name?tsig->key_name->name_size:1) /* Owner */ 713 + sizeof(uint16_t) /* Type */ 714 + sizeof(uint16_t) /* Class */ 715 + sizeof(uint32_t) /* TTL */ 716 + sizeof(uint16_t) /* RDATA length */ 717 + (tsig->algorithm_name?tsig->algorithm_name->name_size:1) 718 + sizeof(uint16_t) /* Signed time (high) */ 719 + sizeof(uint32_t) /* Signed time (low) */ 720 + sizeof(uint16_t) /* Signed time fudge */ 721 + sizeof(uint16_t) /* MAC size */ 722 + max_algo_digest_size /* MAC data */ 723 + sizeof(uint16_t) /* Original query ID */ 724 + sizeof(uint16_t) /* Error code */ 725 + sizeof(uint16_t) /* Other size */ 726 + tsig->other_size); /* Other data */ 727 } 728 729 void 730 tsig_error_reply(tsig_record_type *tsig) 731 { 732 if(tsig->mac_data) 733 memset(tsig->mac_data, 0, tsig->mac_size); 734 tsig->mac_size = 0; 735 } 736 737 void 738 tsig_finalize() 739 { 740 #if defined(HAVE_SSL) 741 tsig_openssl_finalize(); 742 #endif /* defined(HAVE_SSL) */ 743 } 744