1 /* $NetBSD: dlv_32769.c,v 1.8 2014/12/10 04:37:59 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2004, 2006, 2007, 2009-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 */ 20 21 /* RFC3658 */ 22 23 #ifndef RDATA_GENERIC_DLV_32769_C 24 #define RDATA_GENERIC_DLV_32769_C 25 26 #define RRTYPE_DLV_ATTRIBUTES 0 27 28 #include <isc/sha1.h> 29 #include <isc/sha2.h> 30 31 #include <dns/ds.h> 32 33 #include "dst_gost.h" 34 35 static inline isc_result_t 36 fromtext_dlv(ARGS_FROMTEXT) { 37 isc_token_t token; 38 unsigned char c; 39 int length; 40 41 REQUIRE(type == 32769); 42 43 UNUSED(type); 44 UNUSED(rdclass); 45 UNUSED(origin); 46 UNUSED(options); 47 UNUSED(callbacks); 48 49 /* 50 * Key tag. 51 */ 52 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 53 ISC_FALSE)); 54 if (token.value.as_ulong > 0xffffU) 55 RETTOK(ISC_R_RANGE); 56 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 57 58 /* 59 * Algorithm. 60 */ 61 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 62 ISC_FALSE)); 63 if (token.value.as_ulong > 0xffU) 64 RETTOK(ISC_R_RANGE); 65 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 66 67 /* 68 * Digest type. 69 */ 70 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 71 ISC_FALSE)); 72 if (token.value.as_ulong > 0xffU) 73 RETTOK(ISC_R_RANGE); 74 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 75 c = (unsigned char) token.value.as_ulong; 76 77 /* 78 * Digest. 79 */ 80 switch (c) { 81 case DNS_DSDIGEST_SHA1: 82 length = ISC_SHA1_DIGESTLENGTH; 83 break; 84 case DNS_DSDIGEST_SHA256: 85 length = ISC_SHA256_DIGESTLENGTH; 86 break; 87 #ifdef ISC_GOST_DIGESTLENGTH 88 case DNS_DSDIGEST_GOST: 89 length = ISC_GOST_DIGESTLENGTH; 90 break; 91 #endif 92 case DNS_DSDIGEST_SHA384: 93 length = ISC_SHA384_DIGESTLENGTH; 94 break; 95 default: 96 length = -1; 97 break; 98 } 99 return (isc_hex_tobuffer(lexer, target, length)); 100 } 101 102 static inline isc_result_t 103 totext_dlv(ARGS_TOTEXT) { 104 isc_region_t sr; 105 char buf[sizeof("64000 ")]; 106 unsigned int n; 107 108 REQUIRE(rdata->type == 32769); 109 REQUIRE(rdata->length != 0); 110 111 UNUSED(tctx); 112 113 dns_rdata_toregion(rdata, &sr); 114 115 /* 116 * Key tag. 117 */ 118 n = uint16_fromregion(&sr); 119 isc_region_consume(&sr, 2); 120 sprintf(buf, "%u ", n); 121 RETERR(str_totext(buf, target)); 122 123 /* 124 * Algorithm. 125 */ 126 n = uint8_fromregion(&sr); 127 isc_region_consume(&sr, 1); 128 sprintf(buf, "%u ", n); 129 RETERR(str_totext(buf, target)); 130 131 /* 132 * Digest type. 133 */ 134 n = uint8_fromregion(&sr); 135 isc_region_consume(&sr, 1); 136 sprintf(buf, "%u", n); 137 RETERR(str_totext(buf, target)); 138 139 /* 140 * Digest. 141 */ 142 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 143 RETERR(str_totext(" (", target)); 144 RETERR(str_totext(tctx->linebreak, target)); 145 if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) { 146 if (tctx->width == 0) /* No splitting */ 147 RETERR(isc_hex_totext(&sr, 0, "", target)); 148 else 149 RETERR(isc_hex_totext(&sr, tctx->width - 2, 150 tctx->linebreak, target)); 151 } else 152 RETERR(str_totext("[omitted]", target)); 153 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 154 RETERR(str_totext(" )", target)); 155 return (ISC_R_SUCCESS); 156 } 157 158 static inline isc_result_t 159 fromwire_dlv(ARGS_FROMWIRE) { 160 isc_region_t sr; 161 162 REQUIRE(type == 32769); 163 164 UNUSED(type); 165 UNUSED(rdclass); 166 UNUSED(dctx); 167 UNUSED(options); 168 169 isc_buffer_activeregion(source, &sr); 170 171 /* 172 * Check digest lengths if we know them. 173 */ 174 if (sr.length < 4 || 175 (sr.base[3] == DNS_DSDIGEST_SHA1 && 176 sr.length < 4 + ISC_SHA1_DIGESTLENGTH) || 177 (sr.base[3] == DNS_DSDIGEST_SHA256 && 178 sr.length < 4 + ISC_SHA256_DIGESTLENGTH) || 179 #ifdef ISC_GOST_DIGESTLENGTH 180 (sr.base[3] == DNS_DSDIGEST_GOST && 181 sr.length < 4 + ISC_GOST_DIGESTLENGTH) || 182 #endif 183 (sr.base[3] == DNS_DSDIGEST_SHA384 && 184 sr.length < 4 + ISC_SHA384_DIGESTLENGTH)) 185 return (ISC_R_UNEXPECTEDEND); 186 187 /* 188 * Only copy digest lengths if we know them. 189 * If there is extra data dns_rdata_fromwire() will 190 * detect that. 191 */ 192 if (sr.base[3] == DNS_DSDIGEST_SHA1) 193 sr.length = 4 + ISC_SHA1_DIGESTLENGTH; 194 else if (sr.base[3] == DNS_DSDIGEST_SHA256) 195 sr.length = 4 + ISC_SHA256_DIGESTLENGTH; 196 #ifdef ISC_GOST_DIGESTLENGTH 197 else if (sr.base[3] == DNS_DSDIGEST_GOST) 198 sr.length = 4 + ISC_GOST_DIGESTLENGTH; 199 #endif 200 else if (sr.base[3] == DNS_DSDIGEST_SHA384) 201 sr.length = 4 + ISC_SHA384_DIGESTLENGTH; 202 203 isc_buffer_forward(source, sr.length); 204 return (mem_tobuffer(target, sr.base, sr.length)); 205 } 206 207 static inline isc_result_t 208 towire_dlv(ARGS_TOWIRE) { 209 isc_region_t sr; 210 211 REQUIRE(rdata->type == 32769); 212 REQUIRE(rdata->length != 0); 213 214 UNUSED(cctx); 215 216 dns_rdata_toregion(rdata, &sr); 217 return (mem_tobuffer(target, sr.base, sr.length)); 218 } 219 220 static inline int 221 compare_dlv(ARGS_COMPARE) { 222 isc_region_t r1; 223 isc_region_t r2; 224 225 REQUIRE(rdata1->type == rdata2->type); 226 REQUIRE(rdata1->rdclass == rdata2->rdclass); 227 REQUIRE(rdata1->type == 32769); 228 REQUIRE(rdata1->length != 0); 229 REQUIRE(rdata2->length != 0); 230 231 dns_rdata_toregion(rdata1, &r1); 232 dns_rdata_toregion(rdata2, &r2); 233 return (isc_region_compare(&r1, &r2)); 234 } 235 236 static inline isc_result_t 237 fromstruct_dlv(ARGS_FROMSTRUCT) { 238 dns_rdata_dlv_t *dlv = source; 239 240 REQUIRE(type == 32769); 241 REQUIRE(source != NULL); 242 REQUIRE(dlv->common.rdtype == type); 243 REQUIRE(dlv->common.rdclass == rdclass); 244 switch (dlv->digest_type) { 245 case DNS_DSDIGEST_SHA1: 246 REQUIRE(dlv->length == ISC_SHA1_DIGESTLENGTH); 247 break; 248 case DNS_DSDIGEST_SHA256: 249 REQUIRE(dlv->length == ISC_SHA256_DIGESTLENGTH); 250 break; 251 #ifdef ISC_GOST_DIGESTLENGTH 252 case DNS_DSDIGEST_GOST: 253 REQUIRE(dlv->length == ISC_GOST_DIGESTLENGTH); 254 break; 255 #endif 256 case DNS_DSDIGEST_SHA384: 257 REQUIRE(dlv->length == ISC_SHA384_DIGESTLENGTH); 258 break; 259 } 260 261 UNUSED(type); 262 UNUSED(rdclass); 263 264 RETERR(uint16_tobuffer(dlv->key_tag, target)); 265 RETERR(uint8_tobuffer(dlv->algorithm, target)); 266 RETERR(uint8_tobuffer(dlv->digest_type, target)); 267 268 return (mem_tobuffer(target, dlv->digest, dlv->length)); 269 } 270 271 static inline isc_result_t 272 tostruct_dlv(ARGS_TOSTRUCT) { 273 dns_rdata_dlv_t *dlv = target; 274 isc_region_t region; 275 276 REQUIRE(rdata->type == 32769); 277 REQUIRE(target != NULL); 278 REQUIRE(rdata->length != 0); 279 280 dlv->common.rdclass = rdata->rdclass; 281 dlv->common.rdtype = rdata->type; 282 ISC_LINK_INIT(&dlv->common, link); 283 284 dns_rdata_toregion(rdata, ®ion); 285 286 dlv->key_tag = uint16_fromregion(®ion); 287 isc_region_consume(®ion, 2); 288 dlv->algorithm = uint8_fromregion(®ion); 289 isc_region_consume(®ion, 1); 290 dlv->digest_type = uint8_fromregion(®ion); 291 isc_region_consume(®ion, 1); 292 dlv->length = region.length; 293 294 dlv->digest = mem_maybedup(mctx, region.base, region.length); 295 if (dlv->digest == NULL) 296 return (ISC_R_NOMEMORY); 297 298 dlv->mctx = mctx; 299 return (ISC_R_SUCCESS); 300 } 301 302 static inline void 303 freestruct_dlv(ARGS_FREESTRUCT) { 304 dns_rdata_dlv_t *dlv = source; 305 306 REQUIRE(dlv != NULL); 307 REQUIRE(dlv->common.rdtype == 32769); 308 309 if (dlv->mctx == NULL) 310 return; 311 312 if (dlv->digest != NULL) 313 isc_mem_free(dlv->mctx, dlv->digest); 314 dlv->mctx = NULL; 315 } 316 317 static inline isc_result_t 318 additionaldata_dlv(ARGS_ADDLDATA) { 319 REQUIRE(rdata->type == 32769); 320 321 UNUSED(rdata); 322 UNUSED(add); 323 UNUSED(arg); 324 325 return (ISC_R_SUCCESS); 326 } 327 328 static inline isc_result_t 329 digest_dlv(ARGS_DIGEST) { 330 isc_region_t r; 331 332 REQUIRE(rdata->type == 32769); 333 334 dns_rdata_toregion(rdata, &r); 335 336 return ((digest)(arg, &r)); 337 } 338 339 static inline isc_boolean_t 340 checkowner_dlv(ARGS_CHECKOWNER) { 341 342 REQUIRE(type == 32769); 343 344 UNUSED(name); 345 UNUSED(type); 346 UNUSED(rdclass); 347 UNUSED(wildcard); 348 349 return (ISC_TRUE); 350 } 351 352 static inline isc_boolean_t 353 checknames_dlv(ARGS_CHECKNAMES) { 354 355 REQUIRE(rdata->type == 32769); 356 357 UNUSED(rdata); 358 UNUSED(owner); 359 UNUSED(bad); 360 361 return (ISC_TRUE); 362 } 363 364 static inline int 365 casecompare_dlv(ARGS_COMPARE) { 366 return (compare_dlv(rdata1, rdata2)); 367 } 368 369 #endif /* RDATA_GENERIC_DLV_32769_C */ 370