1 /* $NetBSD: key_25.c,v 1.6 2014/12/10 04:37:59 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2004, 2005, 2007, 2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 1999-2003 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* Id */ 21 22 /* 23 * Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley. 24 */ 25 26 /* RFC2535 */ 27 28 #ifndef RDATA_GENERIC_KEY_25_C 29 #define RDATA_GENERIC_KEY_25_C 30 31 #include <dst/dst.h> 32 33 #define RRTYPE_KEY_ATTRIBUTES (0) 34 35 static inline isc_result_t 36 fromtext_key(ARGS_FROMTEXT) { 37 isc_result_t result; 38 isc_token_t token; 39 dns_secalg_t alg; 40 dns_secproto_t proto; 41 dns_keyflags_t flags; 42 43 REQUIRE(type == 25); 44 45 UNUSED(type); 46 UNUSED(rdclass); 47 UNUSED(origin); 48 UNUSED(options); 49 UNUSED(callbacks); 50 51 /* flags */ 52 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 53 ISC_FALSE)); 54 RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion)); 55 RETERR(uint16_tobuffer(flags, target)); 56 57 /* protocol */ 58 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 59 ISC_FALSE)); 60 RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion)); 61 RETERR(mem_tobuffer(target, &proto, 1)); 62 63 /* algorithm */ 64 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 65 ISC_FALSE)); 66 RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion)); 67 RETERR(mem_tobuffer(target, &alg, 1)); 68 69 /* No Key? */ 70 if ((flags & 0xc000) == 0xc000) 71 return (ISC_R_SUCCESS); 72 73 result = isc_base64_tobuffer(lexer, target, -1); 74 if (result != ISC_R_SUCCESS) 75 return (result); 76 77 /* Ensure there's at least enough data to compute a key ID for MD5 */ 78 if (alg == DST_ALG_RSAMD5 && isc_buffer_usedlength(target) < 7) 79 return (ISC_R_UNEXPECTEDEND); 80 81 return (ISC_R_SUCCESS); 82 } 83 84 static inline isc_result_t 85 totext_key(ARGS_TOTEXT) { 86 isc_region_t sr; 87 char buf[sizeof("64000")]; 88 unsigned int flags; 89 unsigned char algorithm; 90 char namebuf[DNS_NAME_FORMATSIZE]; 91 92 REQUIRE(rdata->type == 25); 93 REQUIRE(rdata->length != 0); 94 95 dns_rdata_toregion(rdata, &sr); 96 97 /* flags */ 98 flags = uint16_fromregion(&sr); 99 isc_region_consume(&sr, 2); 100 sprintf(buf, "%u", flags); 101 RETERR(str_totext(buf, target)); 102 RETERR(str_totext(" ", target)); 103 104 /* protocol */ 105 sprintf(buf, "%u", sr.base[0]); 106 isc_region_consume(&sr, 1); 107 RETERR(str_totext(buf, target)); 108 RETERR(str_totext(" ", target)); 109 110 /* algorithm */ 111 algorithm = sr.base[0]; 112 sprintf(buf, "%u", algorithm); 113 isc_region_consume(&sr, 1); 114 RETERR(str_totext(buf, target)); 115 116 /* No Key? */ 117 if ((flags & 0xc000) == 0xc000) 118 return (ISC_R_SUCCESS); 119 120 if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 && 121 algorithm == DNS_KEYALG_PRIVATEDNS) { 122 dns_name_t name; 123 dns_name_init(&name, NULL); 124 dns_name_fromregion(&name, &sr); 125 dns_name_format(&name, namebuf, sizeof(namebuf)); 126 } else 127 namebuf[0] = 0; 128 129 /* key */ 130 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 131 RETERR(str_totext(" (", target)); 132 RETERR(str_totext(tctx->linebreak, target)); 133 if (tctx->width == 0) /* No splitting */ 134 RETERR(isc_base64_totext(&sr, 60, "", target)); 135 else 136 RETERR(isc_base64_totext(&sr, tctx->width - 2, 137 tctx->linebreak, target)); 138 139 if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) 140 RETERR(str_totext(tctx->linebreak, target)); 141 else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 142 RETERR(str_totext(" ", target)); 143 144 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 145 RETERR(str_totext(")", target)); 146 147 if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { 148 isc_region_t tmpr; 149 150 RETERR(str_totext(" ; key id = ", target)); 151 dns_rdata_toregion(rdata, &tmpr); 152 sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); 153 RETERR(str_totext(buf, target)); 154 if (algorithm == DNS_KEYALG_PRIVATEDNS) { 155 RETERR(str_totext(tctx->linebreak, target)); 156 RETERR(str_totext("; alg = ", target)); 157 RETERR(str_totext(namebuf, target)); 158 } 159 } 160 return (ISC_R_SUCCESS); 161 } 162 163 static inline isc_result_t 164 fromwire_key(ARGS_FROMWIRE) { 165 unsigned char algorithm; 166 isc_region_t sr; 167 168 REQUIRE(type == 25); 169 170 UNUSED(type); 171 UNUSED(rdclass); 172 UNUSED(dctx); 173 UNUSED(options); 174 175 isc_buffer_activeregion(source, &sr); 176 if (sr.length < 4) 177 return (ISC_R_UNEXPECTEDEND); 178 179 algorithm = sr.base[3]; 180 RETERR(mem_tobuffer(target, sr.base, 4)); 181 isc_region_consume(&sr, 4); 182 isc_buffer_forward(source, 4); 183 184 if (algorithm == DNS_KEYALG_PRIVATEDNS) { 185 dns_name_t name; 186 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 187 dns_name_init(&name, NULL); 188 RETERR(dns_name_fromwire(&name, source, dctx, options, target)); 189 } 190 191 /* 192 * RSAMD5 computes key ID differently from other 193 * algorithms: we need to ensure there's enough data 194 * present for the computation 195 */ 196 if (algorithm == DST_ALG_RSAMD5 && sr.length < 3) 197 return (ISC_R_UNEXPECTEDEND); 198 199 isc_buffer_activeregion(source, &sr); 200 isc_buffer_forward(source, sr.length); 201 return (mem_tobuffer(target, sr.base, sr.length)); 202 } 203 204 static inline isc_result_t 205 towire_key(ARGS_TOWIRE) { 206 isc_region_t sr; 207 208 REQUIRE(rdata->type == 25); 209 REQUIRE(rdata->length != 0); 210 211 UNUSED(cctx); 212 213 dns_rdata_toregion(rdata, &sr); 214 return (mem_tobuffer(target, sr.base, sr.length)); 215 } 216 217 static inline int 218 compare_key(ARGS_COMPARE) { 219 isc_region_t r1; 220 isc_region_t r2; 221 222 REQUIRE(rdata1->type == rdata2->type); 223 REQUIRE(rdata1->rdclass == rdata2->rdclass); 224 REQUIRE(rdata1->type == 25); 225 REQUIRE(rdata1->length != 0); 226 REQUIRE(rdata2->length != 0); 227 228 dns_rdata_toregion(rdata1, &r1); 229 dns_rdata_toregion(rdata2, &r2); 230 return (isc_region_compare(&r1, &r2)); 231 } 232 233 static inline isc_result_t 234 fromstruct_key(ARGS_FROMSTRUCT) { 235 dns_rdata_key_t *key = source; 236 237 REQUIRE(type == 25); 238 REQUIRE(source != NULL); 239 REQUIRE(key->common.rdtype == type); 240 REQUIRE(key->common.rdclass == rdclass); 241 242 UNUSED(type); 243 UNUSED(rdclass); 244 245 /* Flags */ 246 RETERR(uint16_tobuffer(key->flags, target)); 247 248 /* Protocol */ 249 RETERR(uint8_tobuffer(key->protocol, target)); 250 251 /* Algorithm */ 252 RETERR(uint8_tobuffer(key->algorithm, target)); 253 254 /* Data */ 255 return (mem_tobuffer(target, key->data, key->datalen)); 256 } 257 258 static inline isc_result_t 259 tostruct_key(ARGS_TOSTRUCT) { 260 dns_rdata_key_t *key = target; 261 isc_region_t sr; 262 263 REQUIRE(rdata->type == 25); 264 REQUIRE(target != NULL); 265 REQUIRE(rdata->length != 0); 266 267 key->common.rdclass = rdata->rdclass; 268 key->common.rdtype = rdata->type; 269 ISC_LINK_INIT(&key->common, link); 270 271 dns_rdata_toregion(rdata, &sr); 272 273 /* Flags */ 274 if (sr.length < 2) 275 return (ISC_R_UNEXPECTEDEND); 276 key->flags = uint16_fromregion(&sr); 277 isc_region_consume(&sr, 2); 278 279 /* Protocol */ 280 if (sr.length < 1) 281 return (ISC_R_UNEXPECTEDEND); 282 key->protocol = uint8_fromregion(&sr); 283 isc_region_consume(&sr, 1); 284 285 /* Algorithm */ 286 if (sr.length < 1) 287 return (ISC_R_UNEXPECTEDEND); 288 key->algorithm = uint8_fromregion(&sr); 289 isc_region_consume(&sr, 1); 290 291 /* Data */ 292 key->datalen = sr.length; 293 key->data = mem_maybedup(mctx, sr.base, key->datalen); 294 if (key->data == NULL) 295 return (ISC_R_NOMEMORY); 296 297 key->mctx = mctx; 298 return (ISC_R_SUCCESS); 299 } 300 301 static inline void 302 freestruct_key(ARGS_FREESTRUCT) { 303 dns_rdata_key_t *key = (dns_rdata_key_t *) source; 304 305 REQUIRE(source != NULL); 306 REQUIRE(key->common.rdtype == 25); 307 308 if (key->mctx == NULL) 309 return; 310 311 if (key->data != NULL) 312 isc_mem_free(key->mctx, key->data); 313 key->mctx = NULL; 314 } 315 316 static inline isc_result_t 317 additionaldata_key(ARGS_ADDLDATA) { 318 REQUIRE(rdata->type == 25); 319 320 UNUSED(rdata); 321 UNUSED(add); 322 UNUSED(arg); 323 324 return (ISC_R_SUCCESS); 325 } 326 327 static inline isc_result_t 328 digest_key(ARGS_DIGEST) { 329 isc_region_t r; 330 331 REQUIRE(rdata->type == 25); 332 333 dns_rdata_toregion(rdata, &r); 334 335 return ((digest)(arg, &r)); 336 } 337 338 static inline isc_boolean_t 339 checkowner_key(ARGS_CHECKOWNER) { 340 341 REQUIRE(type == 25); 342 343 UNUSED(name); 344 UNUSED(type); 345 UNUSED(rdclass); 346 UNUSED(wildcard); 347 348 return (ISC_TRUE); 349 } 350 351 static inline isc_boolean_t 352 checknames_key(ARGS_CHECKNAMES) { 353 354 REQUIRE(rdata->type == 25); 355 356 UNUSED(rdata); 357 UNUSED(owner); 358 UNUSED(bad); 359 360 return (ISC_TRUE); 361 } 362 363 static inline int 364 casecompare_key(ARGS_COMPARE) { 365 return (compare_key(rdata1, rdata2)); 366 } 367 368 #endif /* RDATA_GENERIC_KEY_25_C */ 369