1 /* $NetBSD: nsec3param_51.c,v 1.10 2025/01/26 16:25:32 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /* 17 * Copyright (C) 2004 Nominet, Ltd. 18 * 19 * Permission to use, copy, modify, and distribute this software for any 20 * purpose with or without fee is hereby granted, provided that the above 21 * copyright notice and this permission notice appear in all copies. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH 24 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 25 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 26 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 27 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 28 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 29 * PERFORMANCE OF THIS SOFTWARE. 30 */ 31 32 /* RFC 5155 */ 33 34 #ifndef RDATA_GENERIC_NSEC3PARAM_51_C 35 #define RDATA_GENERIC_NSEC3PARAM_51_C 36 37 #include <isc/base32.h> 38 #include <isc/iterated_hash.h> 39 40 #define RRTYPE_NSEC3PARAM_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) 41 42 static isc_result_t 43 fromtext_nsec3param(ARGS_FROMTEXT) { 44 isc_token_t token; 45 unsigned int flags = 0; 46 unsigned char hashalg; 47 48 REQUIRE(type == dns_rdatatype_nsec3param); 49 50 UNUSED(type); 51 UNUSED(rdclass); 52 UNUSED(callbacks); 53 UNUSED(origin); 54 UNUSED(options); 55 56 /* Hash. */ 57 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 58 false)); 59 RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion)); 60 RETERR(uint8_tobuffer(hashalg, target)); 61 62 /* Flags. */ 63 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 64 false)); 65 flags = token.value.as_ulong; 66 if (flags > 255U) { 67 RETTOK(ISC_R_RANGE); 68 } 69 RETERR(uint8_tobuffer(flags, target)); 70 71 /* Iterations. */ 72 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 73 false)); 74 if (token.value.as_ulong > 0xffffU) { 75 RETTOK(ISC_R_RANGE); 76 } 77 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 78 79 /* Salt. */ 80 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 81 false)); 82 if (token.value.as_textregion.length > (255 * 2)) { 83 RETTOK(DNS_R_TEXTTOOLONG); 84 } 85 if (strcmp(DNS_AS_STR(token), "-") == 0) { 86 RETERR(uint8_tobuffer(0, target)); 87 } else { 88 RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target)); 89 RETERR(isc_hex_decodestring(DNS_AS_STR(token), target)); 90 } 91 92 return ISC_R_SUCCESS; 93 } 94 95 static isc_result_t 96 totext_nsec3param(ARGS_TOTEXT) { 97 isc_region_t sr; 98 unsigned int i, j; 99 unsigned char hash; 100 unsigned char flags; 101 char buf[sizeof("65535 ")]; 102 uint32_t iterations; 103 104 REQUIRE(rdata->type == dns_rdatatype_nsec3param); 105 REQUIRE(rdata->length != 0); 106 107 UNUSED(tctx); 108 109 dns_rdata_toregion(rdata, &sr); 110 111 hash = uint8_fromregion(&sr); 112 isc_region_consume(&sr, 1); 113 114 flags = uint8_fromregion(&sr); 115 isc_region_consume(&sr, 1); 116 117 iterations = uint16_fromregion(&sr); 118 isc_region_consume(&sr, 2); 119 120 snprintf(buf, sizeof(buf), "%u ", hash); 121 RETERR(str_totext(buf, target)); 122 123 snprintf(buf, sizeof(buf), "%u ", flags); 124 RETERR(str_totext(buf, target)); 125 126 snprintf(buf, sizeof(buf), "%u ", iterations); 127 RETERR(str_totext(buf, target)); 128 129 j = uint8_fromregion(&sr); 130 isc_region_consume(&sr, 1); 131 INSIST(j <= sr.length); 132 133 if (j != 0) { 134 i = sr.length; 135 sr.length = j; 136 RETERR(isc_hex_totext(&sr, 1, "", target)); 137 sr.length = i - j; 138 } else { 139 RETERR(str_totext("-", target)); 140 } 141 142 return ISC_R_SUCCESS; 143 } 144 145 static isc_result_t 146 fromwire_nsec3param(ARGS_FROMWIRE) { 147 isc_region_t sr, rr; 148 unsigned int saltlen; 149 150 REQUIRE(type == dns_rdatatype_nsec3param); 151 152 UNUSED(type); 153 UNUSED(rdclass); 154 UNUSED(dctx); 155 156 isc_buffer_activeregion(source, &sr); 157 rr = sr; 158 159 /* hash(1), flags(1), iterations(2), saltlen(1) */ 160 if (sr.length < 5U) { 161 RETERR(DNS_R_FORMERR); 162 } 163 saltlen = sr.base[4]; 164 isc_region_consume(&sr, 5); 165 166 if (sr.length != saltlen) { 167 RETERR(DNS_R_FORMERR); 168 } 169 isc_region_consume(&sr, saltlen); 170 RETERR(mem_tobuffer(target, rr.base, rr.length)); 171 isc_buffer_forward(source, rr.length); 172 return ISC_R_SUCCESS; 173 } 174 175 static isc_result_t 176 towire_nsec3param(ARGS_TOWIRE) { 177 isc_region_t sr; 178 179 REQUIRE(rdata->type == dns_rdatatype_nsec3param); 180 REQUIRE(rdata->length != 0); 181 182 UNUSED(cctx); 183 184 dns_rdata_toregion(rdata, &sr); 185 return mem_tobuffer(target, sr.base, sr.length); 186 } 187 188 static int 189 compare_nsec3param(ARGS_COMPARE) { 190 isc_region_t r1; 191 isc_region_t r2; 192 193 REQUIRE(rdata1->type == rdata2->type); 194 REQUIRE(rdata1->rdclass == rdata2->rdclass); 195 REQUIRE(rdata1->type == dns_rdatatype_nsec3param); 196 REQUIRE(rdata1->length != 0); 197 REQUIRE(rdata2->length != 0); 198 199 dns_rdata_toregion(rdata1, &r1); 200 dns_rdata_toregion(rdata2, &r2); 201 return isc_region_compare(&r1, &r2); 202 } 203 204 static isc_result_t 205 fromstruct_nsec3param(ARGS_FROMSTRUCT) { 206 dns_rdata_nsec3param_t *nsec3param = source; 207 208 REQUIRE(type == dns_rdatatype_nsec3param); 209 REQUIRE(nsec3param != NULL); 210 REQUIRE(nsec3param->common.rdtype == type); 211 REQUIRE(nsec3param->common.rdclass == rdclass); 212 213 UNUSED(type); 214 UNUSED(rdclass); 215 216 RETERR(uint8_tobuffer(nsec3param->hash, target)); 217 RETERR(uint8_tobuffer(nsec3param->flags, target)); 218 RETERR(uint16_tobuffer(nsec3param->iterations, target)); 219 RETERR(uint8_tobuffer(nsec3param->salt_length, target)); 220 RETERR(mem_tobuffer(target, nsec3param->salt, nsec3param->salt_length)); 221 return ISC_R_SUCCESS; 222 } 223 224 static isc_result_t 225 tostruct_nsec3param(ARGS_TOSTRUCT) { 226 isc_region_t region; 227 dns_rdata_nsec3param_t *nsec3param = target; 228 229 REQUIRE(rdata->type == dns_rdatatype_nsec3param); 230 REQUIRE(nsec3param != NULL); 231 REQUIRE(rdata->length != 0); 232 233 nsec3param->common.rdclass = rdata->rdclass; 234 nsec3param->common.rdtype = rdata->type; 235 ISC_LINK_INIT(&nsec3param->common, link); 236 237 region.base = rdata->data; 238 region.length = rdata->length; 239 nsec3param->hash = uint8_consume_fromregion(®ion); 240 nsec3param->flags = uint8_consume_fromregion(®ion); 241 nsec3param->iterations = uint16_consume_fromregion(®ion); 242 243 nsec3param->salt_length = uint8_consume_fromregion(®ion); 244 INSIST(nsec3param->salt_length == region.length); 245 nsec3param->salt = mem_maybedup(mctx, region.base, 246 nsec3param->salt_length); 247 isc_region_consume(®ion, nsec3param->salt_length); 248 249 nsec3param->mctx = mctx; 250 return ISC_R_SUCCESS; 251 } 252 253 static void 254 freestruct_nsec3param(ARGS_FREESTRUCT) { 255 dns_rdata_nsec3param_t *nsec3param = source; 256 257 REQUIRE(nsec3param != NULL); 258 REQUIRE(nsec3param->common.rdtype == dns_rdatatype_nsec3param); 259 260 if (nsec3param->mctx == NULL) { 261 return; 262 } 263 264 if (nsec3param->salt != NULL) { 265 isc_mem_free(nsec3param->mctx, nsec3param->salt); 266 } 267 nsec3param->mctx = NULL; 268 } 269 270 static isc_result_t 271 additionaldata_nsec3param(ARGS_ADDLDATA) { 272 REQUIRE(rdata->type == dns_rdatatype_nsec3param); 273 274 UNUSED(rdata); 275 UNUSED(owner); 276 UNUSED(add); 277 UNUSED(arg); 278 279 return ISC_R_SUCCESS; 280 } 281 282 static isc_result_t 283 digest_nsec3param(ARGS_DIGEST) { 284 isc_region_t r; 285 286 REQUIRE(rdata->type == dns_rdatatype_nsec3param); 287 288 dns_rdata_toregion(rdata, &r); 289 return (digest)(arg, &r); 290 } 291 292 static bool 293 checkowner_nsec3param(ARGS_CHECKOWNER) { 294 REQUIRE(type == dns_rdatatype_nsec3param); 295 296 UNUSED(name); 297 UNUSED(type); 298 UNUSED(rdclass); 299 UNUSED(wildcard); 300 301 return true; 302 } 303 304 static bool 305 checknames_nsec3param(ARGS_CHECKNAMES) { 306 REQUIRE(rdata->type == dns_rdatatype_nsec3param); 307 308 UNUSED(rdata); 309 UNUSED(owner); 310 UNUSED(bad); 311 312 return true; 313 } 314 315 static int 316 casecompare_nsec3param(ARGS_COMPARE) { 317 return compare_nsec3param(rdata1, rdata2); 318 } 319 320 #endif /* RDATA_GENERIC_NSEC3PARAM_51_C */ 321