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