1/* 2 * Copyright (C) 2004, 2006, 2007, 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* $Id$ */ 18 19/* draft-ietf-dnsext-delegation-signer-05.txt */ 20 21#ifndef RDATA_GENERIC_DLV_32769_C 22#define RDATA_GENERIC_DLV_32769_C 23 24#define RRTYPE_DLV_ATTRIBUTES 0 25 26#include <isc/sha1.h> 27#include <isc/sha2.h> 28 29#include <dns/ds.h> 30 31 32static inline isc_result_t 33fromtext_dlv(ARGS_FROMTEXT) { 34 isc_token_t token; 35 unsigned char c; 36 int length; 37 38 REQUIRE(type == 32769); 39 40 UNUSED(type); 41 UNUSED(rdclass); 42 UNUSED(origin); 43 UNUSED(options); 44 UNUSED(callbacks); 45 46 /* 47 * Key tag. 48 */ 49 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 50 ISC_FALSE)); 51 if (token.value.as_ulong > 0xffffU) 52 RETTOK(ISC_R_RANGE); 53 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 54 55 /* 56 * Algorithm. 57 */ 58 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 59 ISC_FALSE)); 60 if (token.value.as_ulong > 0xffU) 61 RETTOK(ISC_R_RANGE); 62 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 63 64 /* 65 * Digest type. 66 */ 67 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 68 ISC_FALSE)); 69 if (token.value.as_ulong > 0xffU) 70 RETTOK(ISC_R_RANGE); 71 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 72 c = (unsigned char) token.value.as_ulong; 73 74 /* 75 * Digest. 76 */ 77 switch (c) { 78 case DNS_DSDIGEST_SHA1: 79 length = ISC_SHA1_DIGESTLENGTH; 80 break; 81 case DNS_DSDIGEST_SHA256: 82 length = ISC_SHA256_DIGESTLENGTH; 83 break; 84 case DNS_DSDIGEST_GOST: 85 length = ISC_GOST_DIGESTLENGTH; 86 break; 87 default: 88 length = -1; 89 break; 90 } 91 return (isc_hex_tobuffer(lexer, target, -1)); 92} 93 94static inline isc_result_t 95totext_dlv(ARGS_TOTEXT) { 96 isc_region_t sr; 97 char buf[sizeof("64000 ")]; 98 unsigned int n; 99 100 REQUIRE(rdata->type == 32769); 101 REQUIRE(rdata->length != 0); 102 103 UNUSED(tctx); 104 105 dns_rdata_toregion(rdata, &sr); 106 107 /* 108 * Key tag. 109 */ 110 n = uint16_fromregion(&sr); 111 isc_region_consume(&sr, 2); 112 sprintf(buf, "%u ", n); 113 RETERR(str_totext(buf, target)); 114 115 /* 116 * Algorithm. 117 */ 118 n = uint8_fromregion(&sr); 119 isc_region_consume(&sr, 1); 120 sprintf(buf, "%u ", n); 121 RETERR(str_totext(buf, target)); 122 123 /* 124 * Digest type. 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. 133 */ 134 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 135 RETERR(str_totext(" (", target)); 136 RETERR(str_totext(tctx->linebreak, target)); 137 RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak, target)); 138 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 139 RETERR(str_totext(" )", target)); 140 return (ISC_R_SUCCESS); 141} 142 143static inline isc_result_t 144fromwire_dlv(ARGS_FROMWIRE) { 145 isc_region_t sr; 146 147 REQUIRE(type == 32769); 148 149 UNUSED(type); 150 UNUSED(rdclass); 151 UNUSED(dctx); 152 UNUSED(options); 153 154 isc_buffer_activeregion(source, &sr); 155 156 /* 157 * Check digest lengths if we know them. 158 */ 159 if (sr.length < 4 || 160 (sr.base[3] == DNS_DSDIGEST_SHA1 && 161 sr.length < 4 + ISC_SHA1_DIGESTLENGTH) || 162 (sr.base[3] == DNS_DSDIGEST_SHA256 && 163 sr.length < 4 + ISC_SHA256_DIGESTLENGTH) || 164 (sr.base[3] == DNS_DSDIGEST_GOST && 165 sr.length < 4 + ISC_GOST_DIGESTLENGTH)) 166 return (ISC_R_UNEXPECTEDEND); 167 168 /* 169 * Only copy digest lengths if we know them. 170 * If there is extra data dns_rdata_fromwire() will 171 * detect that. 172 */ 173 if (sr.base[3] == DNS_DSDIGEST_SHA1) 174 sr.length = 4 + ISC_SHA1_DIGESTLENGTH; 175 else if (sr.base[3] == DNS_DSDIGEST_SHA256) 176 sr.length = 4 + ISC_SHA256_DIGESTLENGTH; 177 else if (sr.base[3] == DNS_DSDIGEST_GOST) 178 sr.length = 4 + ISC_GOST_DIGESTLENGTH; 179 180 isc_buffer_forward(source, sr.length); 181 return (mem_tobuffer(target, sr.base, sr.length)); 182} 183 184static inline isc_result_t 185towire_dlv(ARGS_TOWIRE) { 186 isc_region_t sr; 187 188 REQUIRE(rdata->type == 32769); 189 REQUIRE(rdata->length != 0); 190 191 UNUSED(cctx); 192 193 dns_rdata_toregion(rdata, &sr); 194 return (mem_tobuffer(target, sr.base, sr.length)); 195} 196 197static inline int 198compare_dlv(ARGS_COMPARE) { 199 isc_region_t r1; 200 isc_region_t r2; 201 202 REQUIRE(rdata1->type == rdata2->type); 203 REQUIRE(rdata1->rdclass == rdata2->rdclass); 204 REQUIRE(rdata1->type == 32769); 205 REQUIRE(rdata1->length != 0); 206 REQUIRE(rdata2->length != 0); 207 208 dns_rdata_toregion(rdata1, &r1); 209 dns_rdata_toregion(rdata2, &r2); 210 return (isc_region_compare(&r1, &r2)); 211} 212 213static inline isc_result_t 214fromstruct_dlv(ARGS_FROMSTRUCT) { 215 dns_rdata_dlv_t *dlv = source; 216 217 REQUIRE(type == 32769); 218 REQUIRE(source != NULL); 219 REQUIRE(dlv->common.rdtype == type); 220 REQUIRE(dlv->common.rdclass == rdclass); 221 switch (dlv->digest_type) { 222 case DNS_DSDIGEST_SHA1: 223 REQUIRE(dlv->length == ISC_SHA1_DIGESTLENGTH); 224 break; 225 case DNS_DSDIGEST_SHA256: 226 REQUIRE(dlv->length == ISC_SHA256_DIGESTLENGTH); 227 break; 228 case DNS_DSDIGEST_GOST: 229 REQUIRE(dlv->length == ISC_GOST_DIGESTLENGTH); 230 break; 231 } 232 233 UNUSED(type); 234 UNUSED(rdclass); 235 236 RETERR(uint16_tobuffer(dlv->key_tag, target)); 237 RETERR(uint8_tobuffer(dlv->algorithm, target)); 238 RETERR(uint8_tobuffer(dlv->digest_type, target)); 239 240 return (mem_tobuffer(target, dlv->digest, dlv->length)); 241} 242 243static inline isc_result_t 244tostruct_dlv(ARGS_TOSTRUCT) { 245 dns_rdata_dlv_t *dlv = target; 246 isc_region_t region; 247 248 REQUIRE(rdata->type == 32769); 249 REQUIRE(target != NULL); 250 REQUIRE(rdata->length != 0); 251 252 dlv->common.rdclass = rdata->rdclass; 253 dlv->common.rdtype = rdata->type; 254 ISC_LINK_INIT(&dlv->common, link); 255 256 dns_rdata_toregion(rdata, ®ion); 257 258 dlv->key_tag = uint16_fromregion(®ion); 259 isc_region_consume(®ion, 2); 260 dlv->algorithm = uint8_fromregion(®ion); 261 isc_region_consume(®ion, 1); 262 dlv->digest_type = uint8_fromregion(®ion); 263 isc_region_consume(®ion, 1); 264 dlv->length = region.length; 265 266 dlv->digest = mem_maybedup(mctx, region.base, region.length); 267 if (dlv->digest == NULL) 268 return (ISC_R_NOMEMORY); 269 270 dlv->mctx = mctx; 271 return (ISC_R_SUCCESS); 272} 273 274static inline void 275freestruct_dlv(ARGS_FREESTRUCT) { 276 dns_rdata_dlv_t *dlv = source; 277 278 REQUIRE(dlv != NULL); 279 REQUIRE(dlv->common.rdtype == 32769); 280 281 if (dlv->mctx == NULL) 282 return; 283 284 if (dlv->digest != NULL) 285 isc_mem_free(dlv->mctx, dlv->digest); 286 dlv->mctx = NULL; 287} 288 289static inline isc_result_t 290additionaldata_dlv(ARGS_ADDLDATA) { 291 REQUIRE(rdata->type == 32769); 292 293 UNUSED(rdata); 294 UNUSED(add); 295 UNUSED(arg); 296 297 return (ISC_R_SUCCESS); 298} 299 300static inline isc_result_t 301digest_dlv(ARGS_DIGEST) { 302 isc_region_t r; 303 304 REQUIRE(rdata->type == 32769); 305 306 dns_rdata_toregion(rdata, &r); 307 308 return ((digest)(arg, &r)); 309} 310 311static inline isc_boolean_t 312checkowner_dlv(ARGS_CHECKOWNER) { 313 314 REQUIRE(type == 32769); 315 316 UNUSED(name); 317 UNUSED(type); 318 UNUSED(rdclass); 319 UNUSED(wildcard); 320 321 return (ISC_TRUE); 322} 323 324static inline isc_boolean_t 325checknames_dlv(ARGS_CHECKNAMES) { 326 327 REQUIRE(rdata->type == 32769); 328 329 UNUSED(rdata); 330 UNUSED(owner); 331 UNUSED(bad); 332 333 return (ISC_TRUE); 334} 335 336static inline int 337casecompare_dlv(ARGS_COMPARE) { 338 return (compare_dlv(rdata1, rdata2)); 339} 340 341#endif /* RDATA_GENERIC_DLV_32769_C */ 342