1 /* $NetBSD: cdnskey_60.c,v 1.1.1.4 2015/07/08 15:38:03 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2014, 2015 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 /* draft-ietf-dnsop-delegation-trust-maintainance-14 */ 20 21 #ifndef RDATA_GENERIC_CDNSKEY_60_C 22 #define RDATA_GENERIC_CDNSKEY_60_C 23 24 #include <dst/dst.h> 25 26 #define RRTYPE_CDNSKEY_ATTRIBUTES 0 27 28 static inline isc_result_t 29 fromtext_cdnskey(ARGS_FROMTEXT) { 30 isc_result_t result; 31 isc_token_t token; 32 dns_secalg_t alg; 33 dns_secproto_t proto; 34 dns_keyflags_t flags; 35 36 REQUIRE(type == 60); 37 38 UNUSED(type); 39 UNUSED(rdclass); 40 UNUSED(origin); 41 UNUSED(options); 42 UNUSED(callbacks); 43 44 /* flags */ 45 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 46 ISC_FALSE)); 47 RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion)); 48 RETERR(uint16_tobuffer(flags, target)); 49 50 /* protocol */ 51 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 52 ISC_FALSE)); 53 RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion)); 54 RETERR(mem_tobuffer(target, &proto, 1)); 55 56 /* algorithm */ 57 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 58 ISC_FALSE)); 59 RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion)); 60 RETERR(mem_tobuffer(target, &alg, 1)); 61 62 /* No Key? */ 63 if ((flags & 0xc000) == 0xc000) 64 return (ISC_R_SUCCESS); 65 66 result = isc_base64_tobuffer(lexer, target, -1); 67 if (result != ISC_R_SUCCESS) 68 return (result); 69 70 /* Ensure there's at least enough data to compute a key ID for MD5 */ 71 if (alg == DST_ALG_RSAMD5 && isc_buffer_usedlength(target) < 7) 72 return (ISC_R_UNEXPECTEDEND); 73 74 return (ISC_R_SUCCESS); 75 } 76 77 static inline isc_result_t 78 totext_cdnskey(ARGS_TOTEXT) { 79 isc_region_t sr; 80 char buf[sizeof("[key id = 64000]")]; 81 unsigned int flags; 82 unsigned char algorithm; 83 char algbuf[DNS_NAME_FORMATSIZE]; 84 const char *keyinfo; 85 isc_region_t tmpr; 86 87 REQUIRE(rdata->type == 60); 88 REQUIRE(rdata->length != 0); 89 90 dns_rdata_toregion(rdata, &sr); 91 92 /* flags */ 93 flags = uint16_fromregion(&sr); 94 isc_region_consume(&sr, 2); 95 sprintf(buf, "%u", flags); 96 RETERR(str_totext(buf, target)); 97 RETERR(str_totext(" ", target)); 98 if ((flags & DNS_KEYFLAG_KSK) != 0) { 99 if (flags & DNS_KEYFLAG_REVOKE) 100 keyinfo = "revoked KSK"; 101 else 102 keyinfo = "KSK"; 103 } else 104 keyinfo = "ZSK"; 105 106 /* protocol */ 107 sprintf(buf, "%u", sr.base[0]); 108 isc_region_consume(&sr, 1); 109 RETERR(str_totext(buf, target)); 110 RETERR(str_totext(" ", target)); 111 112 /* algorithm */ 113 algorithm = sr.base[0]; 114 sprintf(buf, "%u", algorithm); 115 isc_region_consume(&sr, 1); 116 RETERR(str_totext(buf, target)); 117 118 /* No Key? */ 119 if ((flags & 0xc000) == 0xc000) 120 return (ISC_R_SUCCESS); 121 122 if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 && 123 algorithm == DNS_KEYALG_PRIVATEDNS) { 124 dns_name_t name; 125 dns_name_init(&name, NULL); 126 dns_name_fromregion(&name, &sr); 127 dns_name_format(&name, algbuf, sizeof(algbuf)); 128 } else { 129 dns_secalg_format((dns_secalg_t) algorithm, algbuf, 130 sizeof(algbuf)); 131 } 132 133 /* key */ 134 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 135 RETERR(str_totext(" (", target)); 136 RETERR(str_totext(tctx->linebreak, target)); 137 138 if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) { 139 if (tctx->width == 0) /* No splitting */ 140 RETERR(isc_base64_totext(&sr, 0, "", target)); 141 else 142 RETERR(isc_base64_totext(&sr, tctx->width - 2, 143 tctx->linebreak, target)); 144 } else { 145 dns_rdata_toregion(rdata, &tmpr); 146 snprintf(buf, sizeof(buf), "[key id = %u]", 147 dst_region_computeid(&tmpr, algorithm)); 148 RETERR(str_totext(buf, target)); 149 } 150 151 if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) 152 RETERR(str_totext(tctx->linebreak, target)); 153 else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 154 RETERR(str_totext(" ", target)); 155 156 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 157 RETERR(str_totext(")", target)); 158 159 if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { 160 161 RETERR(str_totext(" ; ", target)); 162 RETERR(str_totext(keyinfo, target)); 163 RETERR(str_totext("; alg = ", target)); 164 RETERR(str_totext(algbuf, target)); 165 RETERR(str_totext("; key id = ", target)); 166 dns_rdata_toregion(rdata, &tmpr); 167 sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); 168 RETERR(str_totext(buf, target)); 169 } 170 return (ISC_R_SUCCESS); 171 } 172 173 static inline isc_result_t 174 fromwire_cdnskey(ARGS_FROMWIRE) { 175 unsigned char algorithm; 176 isc_region_t sr; 177 178 REQUIRE(type == 60); 179 180 UNUSED(type); 181 UNUSED(rdclass); 182 UNUSED(dctx); 183 UNUSED(options); 184 185 isc_buffer_activeregion(source, &sr); 186 if (sr.length < 4) 187 return (ISC_R_UNEXPECTEDEND); 188 189 algorithm = sr.base[3]; 190 RETERR(mem_tobuffer(target, sr.base, 4)); 191 isc_region_consume(&sr, 4); 192 isc_buffer_forward(source, 4); 193 194 if (algorithm == DNS_KEYALG_PRIVATEDNS) { 195 dns_name_t name; 196 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 197 dns_name_init(&name, NULL); 198 RETERR(dns_name_fromwire(&name, source, dctx, options, target)); 199 } 200 201 /* 202 * RSAMD5 computes key ID differently from other 203 * algorithms: we need to ensure there's enough data 204 * present for the computation 205 */ 206 if (algorithm == DST_ALG_RSAMD5 && sr.length < 3) 207 return (ISC_R_UNEXPECTEDEND); 208 209 isc_buffer_activeregion(source, &sr); 210 isc_buffer_forward(source, sr.length); 211 return (mem_tobuffer(target, sr.base, sr.length)); 212 } 213 214 static inline isc_result_t 215 towire_cdnskey(ARGS_TOWIRE) { 216 isc_region_t sr; 217 218 REQUIRE(rdata->type == 60); 219 REQUIRE(rdata->length != 0); 220 221 UNUSED(cctx); 222 223 dns_rdata_toregion(rdata, &sr); 224 return (mem_tobuffer(target, sr.base, sr.length)); 225 } 226 227 static inline int 228 compare_cdnskey(ARGS_COMPARE) { 229 isc_region_t r1; 230 isc_region_t r2; 231 232 REQUIRE(rdata1->type == rdata2->type); 233 REQUIRE(rdata1->rdclass == rdata2->rdclass); 234 REQUIRE(rdata1->type == 60); 235 REQUIRE(rdata1->length != 0); 236 REQUIRE(rdata2->length != 0); 237 238 dns_rdata_toregion(rdata1, &r1); 239 dns_rdata_toregion(rdata2, &r2); 240 return (isc_region_compare(&r1, &r2)); 241 } 242 243 static inline isc_result_t 244 fromstruct_cdnskey(ARGS_FROMSTRUCT) { 245 dns_rdata_cdnskey_t *dnskey = source; 246 247 REQUIRE(type == 60); 248 REQUIRE(source != NULL); 249 REQUIRE(dnskey->common.rdtype == type); 250 REQUIRE(dnskey->common.rdclass == rdclass); 251 252 UNUSED(type); 253 UNUSED(rdclass); 254 255 /* Flags */ 256 RETERR(uint16_tobuffer(dnskey->flags, target)); 257 258 /* Protocol */ 259 RETERR(uint8_tobuffer(dnskey->protocol, target)); 260 261 /* Algorithm */ 262 RETERR(uint8_tobuffer(dnskey->algorithm, target)); 263 264 /* Data */ 265 return (mem_tobuffer(target, dnskey->data, dnskey->datalen)); 266 } 267 268 static inline isc_result_t 269 tostruct_cdnskey(ARGS_TOSTRUCT) { 270 dns_rdata_cdnskey_t *dnskey = target; 271 isc_region_t sr; 272 273 REQUIRE(rdata->type == 60); 274 REQUIRE(target != NULL); 275 REQUIRE(rdata->length != 0); 276 277 dnskey->common.rdclass = rdata->rdclass; 278 dnskey->common.rdtype = rdata->type; 279 ISC_LINK_INIT(&dnskey->common, link); 280 281 dns_rdata_toregion(rdata, &sr); 282 283 /* Flags */ 284 if (sr.length < 2) 285 return (ISC_R_UNEXPECTEDEND); 286 dnskey->flags = uint16_fromregion(&sr); 287 isc_region_consume(&sr, 2); 288 289 /* Protocol */ 290 if (sr.length < 1) 291 return (ISC_R_UNEXPECTEDEND); 292 dnskey->protocol = uint8_fromregion(&sr); 293 isc_region_consume(&sr, 1); 294 295 /* Algorithm */ 296 if (sr.length < 1) 297 return (ISC_R_UNEXPECTEDEND); 298 dnskey->algorithm = uint8_fromregion(&sr); 299 isc_region_consume(&sr, 1); 300 301 /* Data */ 302 dnskey->datalen = sr.length; 303 dnskey->data = mem_maybedup(mctx, sr.base, dnskey->datalen); 304 if (dnskey->data == NULL) 305 return (ISC_R_NOMEMORY); 306 307 dnskey->mctx = mctx; 308 return (ISC_R_SUCCESS); 309 } 310 311 static inline void 312 freestruct_cdnskey(ARGS_FREESTRUCT) { 313 dns_rdata_cdnskey_t *dnskey = (dns_rdata_cdnskey_t *) source; 314 315 REQUIRE(source != NULL); 316 REQUIRE(dnskey->common.rdtype == 60); 317 318 if (dnskey->mctx == NULL) 319 return; 320 321 if (dnskey->data != NULL) 322 isc_mem_free(dnskey->mctx, dnskey->data); 323 dnskey->mctx = NULL; 324 } 325 326 static inline isc_result_t 327 additionaldata_cdnskey(ARGS_ADDLDATA) { 328 REQUIRE(rdata->type == 60); 329 330 UNUSED(rdata); 331 UNUSED(add); 332 UNUSED(arg); 333 334 return (ISC_R_SUCCESS); 335 } 336 337 static inline isc_result_t 338 digest_cdnskey(ARGS_DIGEST) { 339 isc_region_t r; 340 341 REQUIRE(rdata->type == 60); 342 343 dns_rdata_toregion(rdata, &r); 344 345 return ((digest)(arg, &r)); 346 } 347 348 static inline isc_boolean_t 349 checkowner_cdnskey(ARGS_CHECKOWNER) { 350 351 REQUIRE(type == 60); 352 353 UNUSED(name); 354 UNUSED(type); 355 UNUSED(rdclass); 356 UNUSED(wildcard); 357 358 return (ISC_TRUE); 359 } 360 361 static inline isc_boolean_t 362 checknames_cdnskey(ARGS_CHECKNAMES) { 363 364 REQUIRE(rdata->type == 60); 365 366 UNUSED(rdata); 367 UNUSED(owner); 368 UNUSED(bad); 369 370 return (ISC_TRUE); 371 } 372 373 static inline int 374 casecompare_cdnskey(ARGS_COMPARE) { 375 376 /* 377 * Treat ALG 253 (private DNS) subtype name case sensistively. 378 */ 379 return (compare_cdnskey(rdata1, rdata2)); 380 } 381 382 #endif /* RDATA_GENERIC_CDNSKEY_60_C */ 383