1 /* $NetBSD: hip_55.c,v 1.5 2014/12/10 04:37:59 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2009, 2011, 2013, 2014 Internet Systems Consortium, Inc. ("ISC") 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* Id: hip_55.c,v 1.8 2011/01/13 04:59:26 tbox Exp */ 20 21 /* reviewed: TBC */ 22 23 /* RFC 5205 */ 24 25 #ifndef RDATA_GENERIC_HIP_5_C 26 #define RDATA_GENERIC_HIP_5_C 27 28 #define RRTYPE_HIP_ATTRIBUTES (0) 29 30 static inline isc_result_t 31 fromtext_hip(ARGS_FROMTEXT) { 32 isc_token_t token; 33 dns_name_t name; 34 isc_buffer_t buffer; 35 isc_buffer_t hit_len; 36 isc_buffer_t key_len; 37 unsigned char *start; 38 size_t len; 39 40 REQUIRE(type == 55); 41 42 UNUSED(type); 43 UNUSED(rdclass); 44 UNUSED(callbacks); 45 46 /* 47 * Dummy HIT len. 48 */ 49 hit_len = *target; 50 RETERR(uint8_tobuffer(0, target)); 51 52 /* 53 * Algorithm. 54 */ 55 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 56 ISC_FALSE)); 57 if (token.value.as_ulong > 0xffU) 58 RETTOK(ISC_R_RANGE); 59 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 60 61 /* 62 * Dummy KEY len. 63 */ 64 key_len = *target; 65 RETERR(uint16_tobuffer(0, target)); 66 67 /* 68 * HIT (base16). 69 */ 70 start = isc_buffer_used(target); 71 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 72 ISC_FALSE)); 73 RETTOK(isc_hex_decodestring(DNS_AS_STR(token), target)); 74 75 /* 76 * Fill in HIT len. 77 */ 78 len = (unsigned char *)isc_buffer_used(target) - start; 79 if (len > 0xffU) 80 RETTOK(ISC_R_RANGE); 81 RETERR(uint8_tobuffer((isc_uint32_t)len, &hit_len)); 82 83 /* 84 * Public key (base64). 85 */ 86 start = isc_buffer_used(target); 87 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 88 ISC_FALSE)); 89 RETTOK(isc_base64_decodestring(DNS_AS_STR(token), target)); 90 91 /* 92 * Fill in KEY len. 93 */ 94 len = (unsigned char *)isc_buffer_used(target) - start; 95 if (len > 0xffffU) 96 RETTOK(ISC_R_RANGE); 97 RETERR(uint16_tobuffer((isc_uint32_t)len, &key_len)); 98 99 /* 100 * Rendezvous Servers. 101 */ 102 dns_name_init(&name, NULL); 103 do { 104 RETERR(isc_lex_getmastertoken(lexer, &token, 105 isc_tokentype_string, 106 ISC_TRUE)); 107 if (token.type != isc_tokentype_string) 108 break; 109 buffer_fromregion(&buffer, &token.value.as_region); 110 origin = (origin != NULL) ? origin : dns_rootname; 111 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, 112 target)); 113 } while (1); 114 115 /* 116 * Let upper layer handle eol/eof. 117 */ 118 isc_lex_ungettoken(lexer, &token); 119 120 return (ISC_R_SUCCESS); 121 } 122 123 static inline isc_result_t 124 totext_hip(ARGS_TOTEXT) { 125 isc_region_t region; 126 dns_name_t name; 127 unsigned int length, key_len, hit_len; 128 unsigned char algorithm; 129 char buf[sizeof("225 ")]; 130 131 REQUIRE(rdata->type == 55); 132 REQUIRE(rdata->length != 0); 133 134 dns_rdata_toregion(rdata, ®ion); 135 136 hit_len = uint8_fromregion(®ion); 137 isc_region_consume(®ion, 1); 138 139 algorithm = uint8_fromregion(®ion); 140 isc_region_consume(®ion, 1); 141 142 key_len = uint16_fromregion(®ion); 143 isc_region_consume(®ion, 2); 144 145 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 146 RETERR(str_totext("( ", target)); 147 148 /* 149 * Algorithm 150 */ 151 sprintf(buf, "%u ", algorithm); 152 RETERR(str_totext(buf, target)); 153 154 /* 155 * HIT. 156 */ 157 INSIST(hit_len < region.length); 158 length = region.length; 159 region.length = hit_len; 160 RETERR(isc_hex_totext(®ion, 1, "", target)); 161 region.length = length - hit_len; 162 RETERR(str_totext(tctx->linebreak, target)); 163 164 /* 165 * Public KEY. 166 */ 167 INSIST(key_len <= region.length); 168 length = region.length; 169 region.length = key_len; 170 RETERR(isc_base64_totext(®ion, 1, "", target)); 171 region.length = length - key_len; 172 RETERR(str_totext(tctx->linebreak, target)); 173 174 /* 175 * Rendezvous Servers. 176 */ 177 dns_name_init(&name, NULL); 178 while (region.length > 0) { 179 dns_name_fromregion(&name, ®ion); 180 181 RETERR(dns_name_totext(&name, ISC_FALSE, target)); 182 isc_region_consume(®ion, name.length); 183 if (region.length > 0) 184 RETERR(str_totext(tctx->linebreak, target)); 185 } 186 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 187 RETERR(str_totext(" )", target)); 188 return (ISC_R_SUCCESS); 189 } 190 191 static inline isc_result_t 192 fromwire_hip(ARGS_FROMWIRE) { 193 isc_region_t region, rr; 194 dns_name_t name; 195 isc_uint8_t hit_len; 196 isc_uint16_t key_len; 197 198 REQUIRE(type == 55); 199 200 UNUSED(type); 201 UNUSED(rdclass); 202 203 isc_buffer_activeregion(source, ®ion); 204 if (region.length < 4U) 205 RETERR(DNS_R_FORMERR); 206 207 rr = region; 208 hit_len = uint8_fromregion(®ion); 209 if (hit_len == 0) 210 RETERR(DNS_R_FORMERR); 211 isc_region_consume(®ion, 2); /* hit length + algorithm */ 212 key_len = uint16_fromregion(®ion); 213 if (key_len == 0) 214 RETERR(DNS_R_FORMERR); 215 isc_region_consume(®ion, 2); 216 if (region.length < (unsigned) (hit_len + key_len)) 217 RETERR(DNS_R_FORMERR); 218 219 RETERR(mem_tobuffer(target, rr.base, 4 + hit_len + key_len)); 220 isc_buffer_forward(source, 4 + hit_len + key_len); 221 222 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 223 while (isc_buffer_activelength(source) > 0) { 224 dns_name_init(&name, NULL); 225 RETERR(dns_name_fromwire(&name, source, dctx, options, target)); 226 } 227 return (ISC_R_SUCCESS); 228 } 229 230 static inline isc_result_t 231 towire_hip(ARGS_TOWIRE) { 232 isc_region_t region; 233 234 REQUIRE(rdata->type == 55); 235 REQUIRE(rdata->length != 0); 236 237 UNUSED(cctx); 238 239 dns_rdata_toregion(rdata, ®ion); 240 return (mem_tobuffer(target, region.base, region.length)); 241 } 242 243 static inline int 244 compare_hip(ARGS_COMPARE) { 245 isc_region_t region1; 246 isc_region_t region2; 247 248 REQUIRE(rdata1->type == rdata2->type); 249 REQUIRE(rdata1->rdclass == rdata2->rdclass); 250 REQUIRE(rdata1->type == 55); 251 REQUIRE(rdata1->length != 0); 252 REQUIRE(rdata2->length != 0); 253 254 dns_rdata_toregion(rdata1, ®ion1); 255 dns_rdata_toregion(rdata2, ®ion2); 256 return (isc_region_compare(®ion1, ®ion2)); 257 } 258 259 static inline isc_result_t 260 fromstruct_hip(ARGS_FROMSTRUCT) { 261 dns_rdata_hip_t *hip = source; 262 dns_rdata_hip_t myhip; 263 isc_result_t result; 264 265 REQUIRE(type == 55); 266 REQUIRE(source != NULL); 267 REQUIRE(hip->common.rdtype == type); 268 REQUIRE(hip->common.rdclass == rdclass); 269 REQUIRE(hip->hit_len > 0 && hip->hit != NULL); 270 REQUIRE(hip->key_len > 0 && hip->key != NULL); 271 REQUIRE((hip->servers == NULL && hip->servers_len == 0) || 272 (hip->servers != NULL && hip->servers_len != 0)); 273 274 UNUSED(type); 275 UNUSED(rdclass); 276 277 RETERR(uint8_tobuffer(hip->hit_len, target)); 278 RETERR(uint8_tobuffer(hip->algorithm, target)); 279 RETERR(uint16_tobuffer(hip->key_len, target)); 280 RETERR(mem_tobuffer(target, hip->hit, hip->hit_len)); 281 RETERR(mem_tobuffer(target, hip->key, hip->key_len)); 282 283 myhip = *hip; 284 for (result = dns_rdata_hip_first(&myhip); 285 result == ISC_R_SUCCESS; 286 result = dns_rdata_hip_next(&myhip)) 287 /* empty */; 288 289 return(mem_tobuffer(target, hip->servers, hip->servers_len)); 290 } 291 292 static inline isc_result_t 293 tostruct_hip(ARGS_TOSTRUCT) { 294 isc_region_t region; 295 dns_rdata_hip_t *hip = target; 296 297 REQUIRE(rdata->type == 55); 298 REQUIRE(target != NULL); 299 REQUIRE(rdata->length != 0); 300 301 hip->common.rdclass = rdata->rdclass; 302 hip->common.rdtype = rdata->type; 303 ISC_LINK_INIT(&hip->common, link); 304 305 dns_rdata_toregion(rdata, ®ion); 306 307 hip->hit_len = uint8_fromregion(®ion); 308 isc_region_consume(®ion, 1); 309 310 hip->algorithm = uint8_fromregion(®ion); 311 isc_region_consume(®ion, 1); 312 313 hip->key_len = uint16_fromregion(®ion); 314 isc_region_consume(®ion, 2); 315 316 hip->hit = hip->key = hip->servers = NULL; 317 318 hip->hit = mem_maybedup(mctx, region.base, hip->hit_len); 319 if (hip->hit == NULL) 320 goto cleanup; 321 isc_region_consume(®ion, hip->hit_len); 322 323 INSIST(hip->key_len <= region.length); 324 325 hip->key = mem_maybedup(mctx, region.base, hip->key_len); 326 if (hip->key == NULL) 327 goto cleanup; 328 isc_region_consume(®ion, hip->key_len); 329 330 hip->servers_len = region.length; 331 if (hip->servers_len != 0) { 332 hip->servers = mem_maybedup(mctx, region.base, region.length); 333 if (hip->servers == NULL) 334 goto cleanup; 335 } 336 337 hip->offset = hip->servers_len; 338 hip->mctx = mctx; 339 return (ISC_R_SUCCESS); 340 341 cleanup: 342 if (hip->hit != NULL) 343 isc_mem_free(mctx, hip->hit); 344 if (hip->key != NULL) 345 isc_mem_free(mctx, hip->key); 346 if (hip->servers != NULL) 347 isc_mem_free(mctx, hip->servers); 348 return (ISC_R_NOMEMORY); 349 350 } 351 352 static inline void 353 freestruct_hip(ARGS_FREESTRUCT) { 354 dns_rdata_hip_t *hip = source; 355 356 REQUIRE(source != NULL); 357 358 if (hip->mctx == NULL) 359 return; 360 361 isc_mem_free(hip->mctx, hip->hit); 362 isc_mem_free(hip->mctx, hip->key); 363 if (hip->servers != NULL) 364 isc_mem_free(hip->mctx, hip->servers); 365 hip->mctx = NULL; 366 } 367 368 static inline isc_result_t 369 additionaldata_hip(ARGS_ADDLDATA) { 370 UNUSED(rdata); 371 UNUSED(add); 372 UNUSED(arg); 373 374 REQUIRE(rdata->type == 55); 375 376 return (ISC_R_SUCCESS); 377 } 378 379 static inline isc_result_t 380 digest_hip(ARGS_DIGEST) { 381 isc_region_t r; 382 383 REQUIRE(rdata->type == 55); 384 385 dns_rdata_toregion(rdata, &r); 386 return ((digest)(arg, &r)); 387 } 388 389 static inline isc_boolean_t 390 checkowner_hip(ARGS_CHECKOWNER) { 391 392 REQUIRE(type == 55); 393 394 UNUSED(name); 395 UNUSED(type); 396 UNUSED(rdclass); 397 UNUSED(wildcard); 398 399 return (ISC_TRUE); 400 } 401 402 static inline isc_boolean_t 403 checknames_hip(ARGS_CHECKNAMES) { 404 405 REQUIRE(rdata->type == 55); 406 407 UNUSED(rdata); 408 UNUSED(owner); 409 UNUSED(bad); 410 411 return (ISC_TRUE); 412 } 413 414 isc_result_t 415 dns_rdata_hip_first(dns_rdata_hip_t *hip) { 416 if (hip->servers_len == 0) 417 return (ISC_R_NOMORE); 418 hip->offset = 0; 419 return (ISC_R_SUCCESS); 420 } 421 422 isc_result_t 423 dns_rdata_hip_next(dns_rdata_hip_t *hip) { 424 isc_region_t region; 425 dns_name_t name; 426 427 if (hip->offset >= hip->servers_len) 428 return (ISC_R_NOMORE); 429 430 region.base = hip->servers + hip->offset; 431 region.length = hip->servers_len - hip->offset; 432 dns_name_init(&name, NULL); 433 dns_name_fromregion(&name, ®ion); 434 hip->offset += name.length; 435 INSIST(hip->offset <= hip->servers_len); 436 return (ISC_R_SUCCESS); 437 } 438 439 void 440 dns_rdata_hip_current(dns_rdata_hip_t *hip, dns_name_t *name) { 441 isc_region_t region; 442 443 REQUIRE(hip->offset < hip->servers_len); 444 445 region.base = hip->servers + hip->offset; 446 region.length = hip->servers_len - hip->offset; 447 dns_name_fromregion(name, ®ion); 448 449 INSIST(name->length + hip->offset <= hip->servers_len); 450 } 451 452 static inline int 453 casecompare_hip(ARGS_COMPARE) { 454 isc_region_t r1; 455 isc_region_t r2; 456 dns_name_t name1; 457 dns_name_t name2; 458 int order; 459 isc_uint8_t hit_len; 460 isc_uint16_t key_len; 461 462 REQUIRE(rdata1->type == rdata2->type); 463 REQUIRE(rdata1->rdclass == rdata2->rdclass); 464 REQUIRE(rdata1->type == 55); 465 REQUIRE(rdata1->length != 0); 466 REQUIRE(rdata2->length != 0); 467 468 dns_rdata_toregion(rdata1, &r1); 469 dns_rdata_toregion(rdata2, &r2); 470 471 INSIST(r1.length > 4); 472 INSIST(r2.length > 4); 473 order = memcmp(r1.base, r2.base, 4); 474 if (order != 0) 475 return (order); 476 477 hit_len = uint8_fromregion(&r1); 478 isc_region_consume(&r1, 2); /* hit length + algorithm */ 479 key_len = uint16_fromregion(&r1); 480 isc_region_consume(&r1, 2); /* key length */ 481 isc_region_consume(&r2, 4); 482 483 INSIST(r1.length >= (unsigned) (hit_len + key_len)); 484 INSIST(r2.length >= (unsigned) (hit_len + key_len)); 485 order = memcmp(r1.base, r2.base, hit_len + key_len); 486 if (order != 0) 487 return (order); 488 isc_region_consume(&r1, hit_len + key_len); 489 isc_region_consume(&r2, hit_len + key_len); 490 491 dns_name_init(&name1, NULL); 492 dns_name_init(&name2, NULL); 493 while (r1.length != 0 && r2.length != 0) { 494 dns_name_fromregion(&name1, &r1); 495 dns_name_fromregion(&name2, &r2); 496 order = dns_name_rdatacompare(&name1, &name2); 497 if (order != 0) 498 return (order); 499 500 isc_region_consume(&r1, name_length(&name1)); 501 isc_region_consume(&r2, name_length(&name2)); 502 } 503 return (isc_region_compare(&r1, &r2)); 504 } 505 506 #endif /* RDATA_GENERIC_HIP_5_C */ 507