ds_43.c revision 1.7
1/* $NetBSD: ds_43.c,v 1.7 2020/05/24 19:46:24 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 */ 13 14/* RFC3658 */ 15 16#ifndef RDATA_GENERIC_DS_43_C 17#define RDATA_GENERIC_DS_43_C 18 19#define RRTYPE_DS_ATTRIBUTES \ 20 (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH | \ 21 DNS_RDATATYPEATTR_ATPARENT) 22 23#include <isc/md.h> 24 25#include <dns/ds.h> 26 27static inline isc_result_t 28generic_fromtext_ds(ARGS_FROMTEXT) { 29 isc_token_t token; 30 unsigned char c; 31 int length; 32 33 UNUSED(type); 34 UNUSED(rdclass); 35 UNUSED(origin); 36 UNUSED(options); 37 UNUSED(callbacks); 38 39 /* 40 * Key tag. 41 */ 42 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 43 false)); 44 if (token.value.as_ulong > 0xffffU) { 45 RETTOK(ISC_R_RANGE); 46 } 47 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 48 49 /* 50 * Algorithm. 51 */ 52 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 53 false)); 54 RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion)); 55 RETERR(mem_tobuffer(target, &c, 1)); 56 57 /* 58 * Digest type. 59 */ 60 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 61 false)); 62 RETTOK(dns_dsdigest_fromtext(&c, &token.value.as_textregion)); 63 RETERR(mem_tobuffer(target, &c, 1)); 64 65 /* 66 * Digest. 67 */ 68 switch (c) { 69 case DNS_DSDIGEST_SHA1: 70 length = ISC_SHA1_DIGESTLENGTH; 71 break; 72 case DNS_DSDIGEST_SHA256: 73 length = ISC_SHA256_DIGESTLENGTH; 74 break; 75 case DNS_DSDIGEST_SHA384: 76 length = ISC_SHA384_DIGESTLENGTH; 77 break; 78 default: 79 length = -2; 80 break; 81 } 82 return (isc_hex_tobuffer(lexer, target, length)); 83} 84 85static inline isc_result_t 86fromtext_ds(ARGS_FROMTEXT) { 87 REQUIRE(type == dns_rdatatype_ds); 88 89 return (generic_fromtext_ds(rdclass, type, lexer, origin, options, 90 target, callbacks)); 91} 92 93static inline isc_result_t 94generic_totext_ds(ARGS_TOTEXT) { 95 isc_region_t sr; 96 char buf[sizeof("64000 ")]; 97 unsigned int n; 98 99 REQUIRE(rdata->length != 0); 100 101 UNUSED(tctx); 102 103 dns_rdata_toregion(rdata, &sr); 104 105 /* 106 * Key tag. 107 */ 108 n = uint16_fromregion(&sr); 109 isc_region_consume(&sr, 2); 110 snprintf(buf, sizeof(buf), "%u ", n); 111 RETERR(str_totext(buf, target)); 112 113 /* 114 * Algorithm. 115 */ 116 n = uint8_fromregion(&sr); 117 isc_region_consume(&sr, 1); 118 snprintf(buf, sizeof(buf), "%u ", n); 119 RETERR(str_totext(buf, target)); 120 121 /* 122 * Digest type. 123 */ 124 n = uint8_fromregion(&sr); 125 isc_region_consume(&sr, 1); 126 snprintf(buf, sizeof(buf), "%u", n); 127 RETERR(str_totext(buf, target)); 128 129 /* 130 * Digest. 131 */ 132 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 133 RETERR(str_totext(" (", target)); 134 } 135 RETERR(str_totext(tctx->linebreak, target)); 136 if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) { 137 if (tctx->width == 0) { /* No splitting */ 138 RETERR(isc_hex_totext(&sr, 0, "", target)); 139 } else { 140 RETERR(isc_hex_totext(&sr, tctx->width - 2, 141 tctx->linebreak, target)); 142 } 143 } else { 144 RETERR(str_totext("[omitted]", target)); 145 } 146 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 147 RETERR(str_totext(" )", target)); 148 } 149 return (ISC_R_SUCCESS); 150} 151 152static inline isc_result_t 153totext_ds(ARGS_TOTEXT) { 154 REQUIRE(rdata->type == dns_rdatatype_ds); 155 156 return (generic_totext_ds(rdata, tctx, target)); 157} 158 159static inline isc_result_t 160generic_fromwire_ds(ARGS_FROMWIRE) { 161 isc_region_t sr; 162 163 UNUSED(type); 164 UNUSED(rdclass); 165 UNUSED(dctx); 166 UNUSED(options); 167 168 isc_buffer_activeregion(source, &sr); 169 170 /* 171 * Check digest lengths if we know them. 172 */ 173 if (sr.length < 5 || 174 (sr.base[3] == DNS_DSDIGEST_SHA1 && 175 sr.length < 4 + ISC_SHA1_DIGESTLENGTH) || 176 (sr.base[3] == DNS_DSDIGEST_SHA256 && 177 sr.length < 4 + ISC_SHA256_DIGESTLENGTH) || 178 (sr.base[3] == DNS_DSDIGEST_SHA384 && 179 sr.length < 4 + ISC_SHA384_DIGESTLENGTH)) 180 { 181 return (ISC_R_UNEXPECTEDEND); 182 } 183 184 /* 185 * Only copy digest lengths if we know them. 186 * If there is extra data dns_rdata_fromwire() will 187 * detect that. 188 */ 189 if (sr.base[3] == DNS_DSDIGEST_SHA1) { 190 sr.length = 4 + ISC_SHA1_DIGESTLENGTH; 191 } else if (sr.base[3] == DNS_DSDIGEST_SHA256) { 192 sr.length = 4 + ISC_SHA256_DIGESTLENGTH; 193 } else if (sr.base[3] == DNS_DSDIGEST_SHA384) { 194 sr.length = 4 + ISC_SHA384_DIGESTLENGTH; 195 } 196 197 isc_buffer_forward(source, sr.length); 198 return (mem_tobuffer(target, sr.base, sr.length)); 199} 200 201static inline isc_result_t 202fromwire_ds(ARGS_FROMWIRE) { 203 REQUIRE(type == dns_rdatatype_ds); 204 205 return (generic_fromwire_ds(rdclass, type, source, dctx, options, 206 target)); 207} 208 209static inline isc_result_t 210towire_ds(ARGS_TOWIRE) { 211 isc_region_t sr; 212 213 REQUIRE(rdata->type == dns_rdatatype_ds); 214 REQUIRE(rdata->length != 0); 215 216 UNUSED(cctx); 217 218 dns_rdata_toregion(rdata, &sr); 219 return (mem_tobuffer(target, sr.base, sr.length)); 220} 221 222static inline int 223compare_ds(ARGS_COMPARE) { 224 isc_region_t r1; 225 isc_region_t r2; 226 227 REQUIRE(rdata1->type == rdata2->type); 228 REQUIRE(rdata1->rdclass == rdata2->rdclass); 229 REQUIRE(rdata1->type == dns_rdatatype_ds); 230 REQUIRE(rdata1->length != 0); 231 REQUIRE(rdata2->length != 0); 232 233 dns_rdata_toregion(rdata1, &r1); 234 dns_rdata_toregion(rdata2, &r2); 235 return (isc_region_compare(&r1, &r2)); 236} 237 238static inline isc_result_t 239generic_fromstruct_ds(ARGS_FROMSTRUCT) { 240 dns_rdata_ds_t *ds = source; 241 242 REQUIRE(ds != NULL); 243 REQUIRE(ds->common.rdtype == type); 244 REQUIRE(ds->common.rdclass == rdclass); 245 246 UNUSED(type); 247 UNUSED(rdclass); 248 249 switch (ds->digest_type) { 250 case DNS_DSDIGEST_SHA1: 251 REQUIRE(ds->length == ISC_SHA1_DIGESTLENGTH); 252 break; 253 case DNS_DSDIGEST_SHA256: 254 REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH); 255 break; 256 case DNS_DSDIGEST_SHA384: 257 REQUIRE(ds->length == ISC_SHA384_DIGESTLENGTH); 258 break; 259 } 260 261 RETERR(uint16_tobuffer(ds->key_tag, target)); 262 RETERR(uint8_tobuffer(ds->algorithm, target)); 263 RETERR(uint8_tobuffer(ds->digest_type, target)); 264 265 return (mem_tobuffer(target, ds->digest, ds->length)); 266} 267 268static inline isc_result_t 269fromstruct_ds(ARGS_FROMSTRUCT) { 270 REQUIRE(type == dns_rdatatype_ds); 271 272 return (generic_fromstruct_ds(rdclass, type, source, target)); 273} 274 275static inline isc_result_t 276generic_tostruct_ds(ARGS_TOSTRUCT) { 277 dns_rdata_ds_t *ds = target; 278 isc_region_t region; 279 280 REQUIRE(ds != NULL); 281 REQUIRE(rdata->length != 0); 282 REQUIRE(ds->common.rdtype == rdata->type); 283 REQUIRE(ds->common.rdclass == rdata->rdclass); 284 REQUIRE(!ISC_LINK_LINKED(&ds->common, link)); 285 286 dns_rdata_toregion(rdata, ®ion); 287 288 ds->key_tag = uint16_fromregion(®ion); 289 isc_region_consume(®ion, 2); 290 ds->algorithm = uint8_fromregion(®ion); 291 isc_region_consume(®ion, 1); 292 ds->digest_type = uint8_fromregion(®ion); 293 isc_region_consume(®ion, 1); 294 ds->length = region.length; 295 296 ds->digest = mem_maybedup(mctx, region.base, region.length); 297 if (ds->digest == NULL) { 298 return (ISC_R_NOMEMORY); 299 } 300 301 ds->mctx = mctx; 302 return (ISC_R_SUCCESS); 303} 304 305static inline isc_result_t 306tostruct_ds(ARGS_TOSTRUCT) { 307 dns_rdata_ds_t *ds = target; 308 309 REQUIRE(rdata->type == dns_rdatatype_ds); 310 REQUIRE(ds != NULL); 311 312 ds->common.rdclass = rdata->rdclass; 313 ds->common.rdtype = rdata->type; 314 ISC_LINK_INIT(&ds->common, link); 315 316 return (generic_tostruct_ds(rdata, target, mctx)); 317} 318 319static inline void 320freestruct_ds(ARGS_FREESTRUCT) { 321 dns_rdata_ds_t *ds = source; 322 323 REQUIRE(ds != NULL); 324 REQUIRE(ds->common.rdtype == dns_rdatatype_ds); 325 326 if (ds->mctx == NULL) { 327 return; 328 } 329 330 if (ds->digest != NULL) { 331 isc_mem_free(ds->mctx, ds->digest); 332 } 333 ds->mctx = NULL; 334} 335 336static inline isc_result_t 337additionaldata_ds(ARGS_ADDLDATA) { 338 REQUIRE(rdata->type == dns_rdatatype_ds); 339 340 UNUSED(rdata); 341 UNUSED(add); 342 UNUSED(arg); 343 344 return (ISC_R_SUCCESS); 345} 346 347static inline isc_result_t 348digest_ds(ARGS_DIGEST) { 349 isc_region_t r; 350 351 REQUIRE(rdata->type == dns_rdatatype_ds); 352 353 dns_rdata_toregion(rdata, &r); 354 355 return ((digest)(arg, &r)); 356} 357 358static inline bool 359checkowner_ds(ARGS_CHECKOWNER) { 360 REQUIRE(type == dns_rdatatype_ds); 361 362 UNUSED(name); 363 UNUSED(type); 364 UNUSED(rdclass); 365 UNUSED(wildcard); 366 367 return (true); 368} 369 370static inline bool 371checknames_ds(ARGS_CHECKNAMES) { 372 REQUIRE(rdata->type == dns_rdatatype_ds); 373 374 UNUSED(rdata); 375 UNUSED(owner); 376 UNUSED(bad); 377 378 return (true); 379} 380 381static inline int 382casecompare_ds(ARGS_COMPARE) { 383 return (compare_ds(rdata1, rdata2)); 384} 385 386#endif /* RDATA_GENERIC_DS_43_C */ 387