1 /* 2 * tsig.c 3 * 4 * contains the functions needed for TSIG [RFC2845] 5 * 6 * (c) 2005-2006 NLnet Labs 7 * See the file LICENSE for the license 8 */ 9 10 #include <ldns/config.h> 11 12 #include <ldns/ldns.h> 13 14 #include <strings.h> 15 16 #ifdef HAVE_SSL 17 #include <openssl/hmac.h> 18 #include <openssl/md5.h> 19 #endif /* HAVE_SSL */ 20 21 const char * 22 ldns_tsig_algorithm(const ldns_tsig_credentials *tc) 23 { 24 return tc->algorithm; 25 } 26 27 const char * 28 ldns_tsig_keyname(const ldns_tsig_credentials *tc) 29 { 30 return tc->keyname; 31 } 32 33 const char * 34 ldns_tsig_keydata(const ldns_tsig_credentials *tc) 35 { 36 return tc->keydata; 37 } 38 39 char * 40 ldns_tsig_keyname_clone(const ldns_tsig_credentials *tc) 41 { 42 return strdup(tc->keyname); 43 } 44 45 char * 46 ldns_tsig_keydata_clone(const ldns_tsig_credentials *tc) 47 { 48 return strdup(tc->keydata); 49 } 50 51 /* 52 * Makes an exact copy of the wire, but with the tsig rr removed 53 */ 54 static uint8_t * 55 ldns_tsig_prepare_pkt_wire(const uint8_t *wire, size_t wire_len, size_t *result_len) 56 { 57 uint8_t *wire2 = NULL; 58 uint16_t qd_count; 59 uint16_t an_count; 60 uint16_t ns_count; 61 uint16_t ar_count; 62 ldns_rr *rr; 63 64 size_t pos; 65 uint16_t i; 66 67 ldns_status status; 68 69 if(wire_len < LDNS_HEADER_SIZE) { 70 return NULL; 71 } 72 /* fake parse the wire */ 73 qd_count = LDNS_QDCOUNT(wire); 74 an_count = LDNS_ANCOUNT(wire); 75 ns_count = LDNS_NSCOUNT(wire); 76 ar_count = LDNS_ARCOUNT(wire); 77 78 if (ar_count > 0) { 79 ar_count--; 80 } else { 81 return NULL; 82 } 83 84 pos = LDNS_HEADER_SIZE; 85 86 for (i = 0; i < qd_count; i++) { 87 status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_QUESTION); 88 if (status != LDNS_STATUS_OK) { 89 return NULL; 90 } 91 ldns_rr_free(rr); 92 } 93 94 for (i = 0; i < an_count; i++) { 95 status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_ANSWER); 96 if (status != LDNS_STATUS_OK) { 97 return NULL; 98 } 99 ldns_rr_free(rr); 100 } 101 102 for (i = 0; i < ns_count; i++) { 103 status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_AUTHORITY); 104 if (status != LDNS_STATUS_OK) { 105 return NULL; 106 } 107 ldns_rr_free(rr); 108 } 109 110 for (i = 0; i < ar_count; i++) { 111 status = ldns_wire2rr(&rr, wire, wire_len, &pos, 112 LDNS_SECTION_ADDITIONAL); 113 if (status != LDNS_STATUS_OK) { 114 return NULL; 115 } 116 ldns_rr_free(rr); 117 } 118 119 *result_len = pos; 120 wire2 = LDNS_XMALLOC(uint8_t, *result_len); 121 if(!wire2) { 122 return NULL; 123 } 124 memcpy(wire2, wire, *result_len); 125 126 ldns_write_uint16(wire2 + LDNS_ARCOUNT_OFF, ar_count); 127 128 return wire2; 129 } 130 131 #ifdef HAVE_SSL 132 static const EVP_MD * 133 ldns_digest_function(char *name) 134 { 135 /* these are the mandatory algorithms from RFC4635 */ 136 /* The optional algorithms are not yet implemented */ 137 if (strcasecmp(name, "hmac-sha512.") == 0) { 138 #ifdef HAVE_EVP_SHA512 139 return EVP_sha512(); 140 #else 141 return NULL; 142 #endif 143 } else if (strcasecmp(name, "hmac-shac384.") == 0) { 144 #ifdef HAVE_EVP_SHA384 145 return EVP_sha384(); 146 #else 147 return NULL; 148 #endif 149 } else if (strcasecmp(name, "hmac-sha256.") == 0) { 150 #ifdef HAVE_EVP_SHA256 151 return EVP_sha256(); 152 #else 153 return NULL; 154 #endif 155 } else if (strcasecmp(name, "hmac-sha1.") == 0) { 156 return EVP_sha1(); 157 } else if (strcasecmp(name, "hmac-md5.sig-alg.reg.int.") == 0) { 158 return EVP_md5(); 159 } else { 160 return NULL; 161 } 162 } 163 #endif 164 165 #ifdef HAVE_SSL 166 static ldns_status 167 ldns_tsig_mac_new(ldns_rdf **tsig_mac, const uint8_t *pkt_wire, size_t pkt_wire_size, 168 const char *key_data, const ldns_rdf *key_name_rdf, const ldns_rdf *fudge_rdf, 169 const ldns_rdf *algorithm_rdf, const ldns_rdf *time_signed_rdf, const ldns_rdf *error_rdf, 170 const ldns_rdf *other_data_rdf, const ldns_rdf *orig_mac_rdf, int tsig_timers_only) 171 { 172 ldns_status status; 173 char *wireformat; 174 int wiresize; 175 unsigned char *mac_bytes = NULL; 176 unsigned char *key_bytes = NULL; 177 int key_size; 178 const EVP_MD *digester; 179 char *algorithm_name = NULL; 180 unsigned int md_len = EVP_MAX_MD_SIZE; 181 ldns_rdf *result = NULL; 182 ldns_buffer *data_buffer = NULL; 183 ldns_rdf *canonical_key_name_rdf = NULL; 184 ldns_rdf *canonical_algorithm_rdf = NULL; 185 186 if (key_name_rdf == NULL || algorithm_rdf == NULL) { 187 return LDNS_STATUS_NULL; 188 } 189 canonical_key_name_rdf = ldns_rdf_clone(key_name_rdf); 190 if (canonical_key_name_rdf == NULL) { 191 return LDNS_STATUS_MEM_ERR; 192 } 193 canonical_algorithm_rdf = ldns_rdf_clone(algorithm_rdf); 194 if (canonical_algorithm_rdf == NULL) { 195 ldns_rdf_deep_free(canonical_key_name_rdf); 196 return LDNS_STATUS_MEM_ERR; 197 } 198 /* 199 * prepare the digestible information 200 */ 201 data_buffer = ldns_buffer_new(LDNS_MAX_PACKETLEN); 202 if (!data_buffer) { 203 status = LDNS_STATUS_MEM_ERR; 204 goto clean; 205 } 206 /* if orig_mac is not NULL, add it too */ 207 if (orig_mac_rdf) { 208 (void) ldns_rdf2buffer_wire(data_buffer, orig_mac_rdf); 209 } 210 ldns_buffer_write(data_buffer, pkt_wire, pkt_wire_size); 211 if (!tsig_timers_only) { 212 ldns_dname2canonical(canonical_key_name_rdf); 213 (void)ldns_rdf2buffer_wire(data_buffer, 214 canonical_key_name_rdf); 215 ldns_buffer_write_u16(data_buffer, LDNS_RR_CLASS_ANY); 216 ldns_buffer_write_u32(data_buffer, 0); 217 ldns_dname2canonical(canonical_algorithm_rdf); 218 (void)ldns_rdf2buffer_wire(data_buffer, 219 canonical_algorithm_rdf); 220 } 221 (void)ldns_rdf2buffer_wire(data_buffer, time_signed_rdf); 222 (void)ldns_rdf2buffer_wire(data_buffer, fudge_rdf); 223 if (!tsig_timers_only) { 224 (void)ldns_rdf2buffer_wire(data_buffer, error_rdf); 225 (void)ldns_rdf2buffer_wire(data_buffer, other_data_rdf); 226 } 227 228 wireformat = (char *) data_buffer->_data; 229 wiresize = (int) ldns_buffer_position(data_buffer); 230 231 algorithm_name = ldns_rdf2str(algorithm_rdf); 232 if(!algorithm_name) { 233 status = LDNS_STATUS_MEM_ERR; 234 goto clean; 235 } 236 237 /* prepare the key */ 238 key_bytes = LDNS_XMALLOC(unsigned char, 239 ldns_b64_pton_calculate_size(strlen(key_data))); 240 if(!key_bytes) { 241 status = LDNS_STATUS_MEM_ERR; 242 goto clean; 243 } 244 key_size = ldns_b64_pton(key_data, key_bytes, 245 ldns_b64_pton_calculate_size(strlen(key_data))); 246 if (key_size < 0) { 247 status = LDNS_STATUS_INVALID_B64; 248 goto clean; 249 } 250 /* hmac it */ 251 /* 2 spare bytes for the length */ 252 mac_bytes = LDNS_XMALLOC(unsigned char, md_len+2); 253 if(!mac_bytes) { 254 status = LDNS_STATUS_MEM_ERR; 255 goto clean; 256 } 257 memset(mac_bytes, 0, md_len+2); 258 259 digester = ldns_digest_function(algorithm_name); 260 261 if (digester) { 262 (void) HMAC(digester, key_bytes, key_size, (void *)wireformat, 263 (size_t) wiresize, mac_bytes + 2, &md_len); 264 265 ldns_write_uint16(mac_bytes, md_len); 266 result = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT16_DATA, md_len + 2, 267 mac_bytes); 268 } else { 269 status = LDNS_STATUS_CRYPTO_UNKNOWN_ALGO; 270 goto clean; 271 } 272 *tsig_mac = result; 273 status = LDNS_STATUS_OK; 274 clean: 275 LDNS_FREE(mac_bytes); 276 LDNS_FREE(key_bytes); 277 LDNS_FREE(algorithm_name); 278 ldns_buffer_free(data_buffer); 279 ldns_rdf_deep_free(canonical_algorithm_rdf); 280 ldns_rdf_deep_free(canonical_key_name_rdf); 281 return status; 282 } 283 #endif /* HAVE_SSL */ 284 285 286 #ifdef HAVE_SSL 287 bool 288 ldns_pkt_tsig_verify(ldns_pkt *pkt, const uint8_t *wire, size_t wirelen, const char *key_name, 289 const char *key_data, const ldns_rdf *orig_mac_rdf) 290 { 291 return ldns_pkt_tsig_verify_next(pkt, wire, wirelen, key_name, key_data, orig_mac_rdf, 0); 292 } 293 294 bool 295 ldns_pkt_tsig_verify_next(ldns_pkt *pkt, const uint8_t *wire, size_t wirelen, const char* key_name, 296 const char *key_data, const ldns_rdf *orig_mac_rdf, int tsig_timers_only) 297 { 298 ldns_rdf *fudge_rdf; 299 ldns_rdf *algorithm_rdf; 300 ldns_rdf *time_signed_rdf; 301 ldns_rdf *orig_id_rdf; 302 ldns_rdf *error_rdf; 303 ldns_rdf *other_data_rdf; 304 ldns_rdf *pkt_mac_rdf; 305 ldns_rdf *my_mac_rdf; 306 ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name); 307 uint16_t pkt_id, orig_pkt_id; 308 ldns_status status; 309 310 uint8_t *prepared_wire = NULL; 311 size_t prepared_wire_size = 0; 312 313 ldns_rr *orig_tsig = ldns_pkt_tsig(pkt); 314 315 if (!orig_tsig || ldns_rr_rd_count(orig_tsig) <= 6) { 316 ldns_rdf_deep_free(key_name_rdf); 317 return false; 318 } 319 algorithm_rdf = ldns_rr_rdf(orig_tsig, 0); 320 time_signed_rdf = ldns_rr_rdf(orig_tsig, 1); 321 fudge_rdf = ldns_rr_rdf(orig_tsig, 2); 322 pkt_mac_rdf = ldns_rr_rdf(orig_tsig, 3); 323 orig_id_rdf = ldns_rr_rdf(orig_tsig, 4); 324 error_rdf = ldns_rr_rdf(orig_tsig, 5); 325 other_data_rdf = ldns_rr_rdf(orig_tsig, 6); 326 327 /* remove temporarily */ 328 ldns_pkt_set_tsig(pkt, NULL); 329 /* temporarily change the id to the original id */ 330 pkt_id = ldns_pkt_id(pkt); 331 orig_pkt_id = ldns_rdf2native_int16(orig_id_rdf); 332 ldns_pkt_set_id(pkt, orig_pkt_id); 333 334 prepared_wire = ldns_tsig_prepare_pkt_wire(wire, wirelen, &prepared_wire_size); 335 336 status = ldns_tsig_mac_new(&my_mac_rdf, prepared_wire, prepared_wire_size, 337 key_data, key_name_rdf, fudge_rdf, algorithm_rdf, 338 time_signed_rdf, error_rdf, other_data_rdf, orig_mac_rdf, tsig_timers_only); 339 340 LDNS_FREE(prepared_wire); 341 342 if (status != LDNS_STATUS_OK) { 343 ldns_rdf_deep_free(key_name_rdf); 344 return false; 345 } 346 /* Put back the values */ 347 ldns_pkt_set_tsig(pkt, orig_tsig); 348 ldns_pkt_set_id(pkt, pkt_id); 349 350 ldns_rdf_deep_free(key_name_rdf); 351 352 if( ldns_rdf_size(pkt_mac_rdf) != ldns_rdf_size(my_mac_rdf)) { 353 ldns_rdf_deep_free(my_mac_rdf); 354 return false; 355 } 356 /* use time insensitive memory compare */ 357 if( 358 #ifdef HAVE_CRYPTO_MEMCMP 359 CRYPTO_memcmp 360 #else 361 memcmp 362 #endif 363 (ldns_rdf_data(pkt_mac_rdf), ldns_rdf_data(my_mac_rdf), 364 ldns_rdf_size(my_mac_rdf)) == 0) { 365 ldns_rdf_deep_free(my_mac_rdf); 366 return true; 367 } else { 368 ldns_rdf_deep_free(my_mac_rdf); 369 return false; 370 } 371 } 372 #endif /* HAVE_SSL */ 373 374 #ifdef HAVE_SSL 375 ldns_status 376 ldns_pkt_tsig_sign(ldns_pkt *pkt, const char *key_name, const char *key_data, 377 uint16_t fudge, const char *algorithm_name, const ldns_rdf *query_mac) 378 { 379 return ldns_pkt_tsig_sign_next(pkt, key_name, key_data, fudge, algorithm_name, query_mac, 0); 380 } 381 382 ldns_status 383 ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data, 384 uint16_t fudge, const char *algorithm_name, const ldns_rdf *query_mac, int tsig_timers_only) 385 { 386 ldns_rr *tsig_rr; 387 ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name); 388 ldns_rdf *fudge_rdf = NULL; 389 ldns_rdf *orig_id_rdf = NULL; 390 ldns_rdf *algorithm_rdf; 391 ldns_rdf *error_rdf = NULL; 392 ldns_rdf *mac_rdf = NULL; 393 ldns_rdf *other_data_rdf = NULL; 394 395 ldns_status status = LDNS_STATUS_OK; 396 397 uint8_t *pkt_wire = NULL; 398 size_t pkt_wire_len; 399 400 struct timeval tv_time_signed; 401 uint8_t *time_signed = NULL; 402 ldns_rdf *time_signed_rdf = NULL; 403 404 algorithm_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, algorithm_name); 405 if(!key_name_rdf || !algorithm_rdf) { 406 status = LDNS_STATUS_MEM_ERR; 407 goto clean; 408 } 409 410 /* eww don't have create tsigtime rdf yet :( */ 411 /* bleh :p */ 412 if (gettimeofday(&tv_time_signed, NULL) == 0) { 413 time_signed = LDNS_XMALLOC(uint8_t, 6); 414 if(!time_signed) { 415 status = LDNS_STATUS_MEM_ERR; 416 goto clean; 417 } 418 ldns_write_uint64_as_uint48(time_signed, 419 (uint64_t)tv_time_signed.tv_sec); 420 } else { 421 status = LDNS_STATUS_INTERNAL_ERR; 422 goto clean; 423 } 424 425 time_signed_rdf = ldns_rdf_new(LDNS_RDF_TYPE_TSIGTIME, 6, time_signed); 426 if(!time_signed_rdf) { 427 LDNS_FREE(time_signed); 428 status = LDNS_STATUS_MEM_ERR; 429 goto clean; 430 } 431 432 fudge_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, fudge); 433 434 orig_id_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_pkt_id(pkt)); 435 436 error_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 0); 437 438 other_data_rdf = ldns_native2rdf_int16_data(0, NULL); 439 440 if(!fudge_rdf || !orig_id_rdf || !error_rdf || !other_data_rdf) { 441 status = LDNS_STATUS_MEM_ERR; 442 goto clean; 443 } 444 445 if (ldns_pkt2wire(&pkt_wire, pkt, &pkt_wire_len) != LDNS_STATUS_OK) { 446 status = LDNS_STATUS_ERR; 447 goto clean; 448 } 449 450 status = ldns_tsig_mac_new(&mac_rdf, pkt_wire, pkt_wire_len, 451 key_data, key_name_rdf, fudge_rdf, algorithm_rdf, 452 time_signed_rdf, error_rdf, other_data_rdf, query_mac, tsig_timers_only); 453 454 if (!mac_rdf) { 455 goto clean; 456 } 457 458 LDNS_FREE(pkt_wire); 459 460 /* Create the TSIG RR */ 461 tsig_rr = ldns_rr_new(); 462 if(!tsig_rr) { 463 status = LDNS_STATUS_MEM_ERR; 464 goto clean; 465 } 466 ldns_rr_set_owner(tsig_rr, key_name_rdf); 467 ldns_rr_set_class(tsig_rr, LDNS_RR_CLASS_ANY); 468 ldns_rr_set_type(tsig_rr, LDNS_RR_TYPE_TSIG); 469 ldns_rr_set_ttl(tsig_rr, 0); 470 471 ldns_rr_push_rdf(tsig_rr, algorithm_rdf); 472 ldns_rr_push_rdf(tsig_rr, time_signed_rdf); 473 ldns_rr_push_rdf(tsig_rr, fudge_rdf); 474 ldns_rr_push_rdf(tsig_rr, mac_rdf); 475 ldns_rr_push_rdf(tsig_rr, orig_id_rdf); 476 ldns_rr_push_rdf(tsig_rr, error_rdf); 477 ldns_rr_push_rdf(tsig_rr, other_data_rdf); 478 479 ldns_pkt_set_tsig(pkt, tsig_rr); 480 481 return status; 482 483 clean: 484 LDNS_FREE(pkt_wire); 485 ldns_rdf_free(key_name_rdf); 486 ldns_rdf_free(algorithm_rdf); 487 ldns_rdf_free(time_signed_rdf); 488 ldns_rdf_free(fudge_rdf); 489 ldns_rdf_free(orig_id_rdf); 490 ldns_rdf_free(error_rdf); 491 ldns_rdf_free(other_data_rdf); 492 return status; 493 } 494 #endif /* HAVE_SSL */ 495