1 /* $NetBSD: zonemd_63.c,v 1.2 2020/05/24 19:46:24 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 */ 13 14 /* draft-wessels-zone-digest-05 */ 15 16 #ifndef RDATA_GENERIC_ZONEMD_63_C 17 #define RDATA_GENERIC_ZONEMD_63_C 18 19 #define RRTYPE_ZONEMD_ATTRIBUTES 0 20 21 static inline isc_result_t 22 fromtext_zonemd(ARGS_FROMTEXT) { 23 isc_token_t token; 24 int digest_type, length; 25 26 UNUSED(type); 27 UNUSED(rdclass); 28 UNUSED(origin); 29 UNUSED(options); 30 UNUSED(callbacks); 31 32 /* 33 * Serial. 34 */ 35 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 36 false)); 37 RETERR(uint32_tobuffer(token.value.as_ulong, target)); 38 39 /* 40 * Digest type. 41 */ 42 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 43 false)); 44 digest_type = token.value.as_ulong; 45 RETERR(uint8_tobuffer(digest_type, target)); 46 47 /* 48 * Reserved. 49 */ 50 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 51 false)); 52 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 53 54 /* 55 * Digest. 56 */ 57 switch (digest_type) { 58 case DNS_ZONEMD_DIGEST_SHA384: 59 length = ISC_SHA384_DIGESTLENGTH; 60 break; 61 default: 62 length = -2; 63 break; 64 } 65 66 return (isc_hex_tobuffer(lexer, target, length)); 67 } 68 69 static inline isc_result_t 70 totext_zonemd(ARGS_TOTEXT) { 71 isc_region_t sr; 72 char buf[sizeof("0123456789")]; 73 unsigned long num; 74 75 REQUIRE(rdata->length > 6); 76 77 UNUSED(tctx); 78 79 dns_rdata_toregion(rdata, &sr); 80 81 /* 82 * Serial. 83 */ 84 num = uint32_fromregion(&sr); 85 isc_region_consume(&sr, 4); 86 snprintf(buf, sizeof(buf), "%lu", num); 87 RETERR(str_totext(buf, target)); 88 89 RETERR(str_totext(" ", target)); 90 91 /* 92 * Digest type. 93 */ 94 num = uint8_fromregion(&sr); 95 isc_region_consume(&sr, 1); 96 snprintf(buf, sizeof(buf), "%lu", num); 97 RETERR(str_totext(buf, target)); 98 99 RETERR(str_totext(" ", target)); 100 /* 101 * Reserved. 102 */ 103 num = uint8_fromregion(&sr); 104 isc_region_consume(&sr, 1); 105 snprintf(buf, sizeof(buf), "%lu", num); 106 RETERR(str_totext(buf, target)); 107 108 /* 109 * Digest. 110 */ 111 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 112 RETERR(str_totext(" (", target)); 113 } 114 RETERR(str_totext(tctx->linebreak, target)); 115 if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) { 116 if (tctx->width == 0) { /* No splitting */ 117 RETERR(isc_hex_totext(&sr, 0, "", target)); 118 } else { 119 RETERR(isc_hex_totext(&sr, tctx->width - 2, 120 tctx->linebreak, target)); 121 } 122 } else { 123 RETERR(str_totext("[omitted]", target)); 124 } 125 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 126 RETERR(str_totext(" )", target)); 127 } 128 return (ISC_R_SUCCESS); 129 } 130 131 static inline isc_result_t 132 fromwire_zonemd(ARGS_FROMWIRE) { 133 isc_region_t sr; 134 135 UNUSED(type); 136 UNUSED(rdclass); 137 UNUSED(dctx); 138 UNUSED(options); 139 140 isc_buffer_activeregion(source, &sr); 141 142 /* 143 * If we do not recognize the digest type, only ensure that the digest 144 * is present at all. 145 * 146 * If we do recognize the digest type, ensure that the digest is of the 147 * correct length. 148 */ 149 if (sr.length < 7 || (sr.base[4] == DNS_ZONEMD_DIGEST_SHA384 && 150 sr.length < 6 + ISC_SHA384_DIGESTLENGTH)) 151 { 152 return (ISC_R_UNEXPECTEDEND); 153 } 154 155 /* 156 * Only specify the number of octets to consume if we recognize the 157 * digest type. 158 * 159 * If there is extra data, dns_rdata_fromwire() will detect that. 160 */ 161 if (sr.base[4] == DNS_ZONEMD_DIGEST_SHA384) { 162 sr.length = 6 + ISC_SHA384_DIGESTLENGTH; 163 } 164 165 isc_buffer_forward(source, sr.length); 166 return (mem_tobuffer(target, sr.base, sr.length)); 167 } 168 169 static inline isc_result_t 170 towire_zonemd(ARGS_TOWIRE) { 171 isc_region_t sr; 172 173 REQUIRE(rdata->type == dns_rdatatype_zonemd); 174 REQUIRE(rdata->length != 0); 175 176 UNUSED(cctx); 177 178 dns_rdata_toregion(rdata, &sr); 179 return (mem_tobuffer(target, sr.base, sr.length)); 180 } 181 182 static inline int 183 compare_zonemd(ARGS_COMPARE) { 184 isc_region_t r1; 185 isc_region_t r2; 186 187 REQUIRE(rdata1->type == rdata2->type); 188 REQUIRE(rdata1->rdclass == rdata2->rdclass); 189 REQUIRE(rdata1->type == dns_rdatatype_zonemd); 190 REQUIRE(rdata1->length != 0); 191 REQUIRE(rdata2->length != 0); 192 193 dns_rdata_toregion(rdata1, &r1); 194 dns_rdata_toregion(rdata2, &r2); 195 return (isc_region_compare(&r1, &r2)); 196 } 197 198 static inline isc_result_t 199 fromstruct_zonemd(ARGS_FROMSTRUCT) { 200 dns_rdata_zonemd_t *zonemd = source; 201 202 REQUIRE(zonemd != NULL); 203 REQUIRE(zonemd->common.rdtype == type); 204 REQUIRE(zonemd->common.rdclass == rdclass); 205 206 UNUSED(type); 207 UNUSED(rdclass); 208 209 switch (zonemd->digest_type) { 210 case DNS_ZONEMD_DIGEST_SHA384: 211 REQUIRE(zonemd->length == ISC_SHA384_DIGESTLENGTH); 212 break; 213 } 214 215 RETERR(uint32_tobuffer(zonemd->serial, target)); 216 RETERR(uint8_tobuffer(zonemd->digest_type, target)); 217 RETERR(uint8_tobuffer(zonemd->reserved, target)); 218 219 return (mem_tobuffer(target, zonemd->digest, zonemd->length)); 220 } 221 222 static inline isc_result_t 223 tostruct_zonemd(ARGS_TOSTRUCT) { 224 dns_rdata_zonemd_t *zonemd = target; 225 isc_region_t region; 226 227 REQUIRE(rdata->type == dns_rdatatype_zonemd); 228 REQUIRE(zonemd != NULL); 229 REQUIRE(rdata->length != 0); 230 231 zonemd->common.rdclass = rdata->rdclass; 232 zonemd->common.rdtype = rdata->type; 233 ISC_LINK_INIT(&zonemd->common, link); 234 235 dns_rdata_toregion(rdata, ®ion); 236 237 zonemd->serial = uint32_fromregion(®ion); 238 isc_region_consume(®ion, 4); 239 zonemd->digest_type = uint8_fromregion(®ion); 240 isc_region_consume(®ion, 1); 241 zonemd->reserved = uint8_fromregion(®ion); 242 isc_region_consume(®ion, 1); 243 zonemd->length = region.length; 244 245 zonemd->digest = mem_maybedup(mctx, region.base, region.length); 246 if (zonemd->digest == NULL) { 247 return (ISC_R_NOMEMORY); 248 } 249 250 zonemd->mctx = mctx; 251 return (ISC_R_SUCCESS); 252 } 253 254 static inline void 255 freestruct_zonemd(ARGS_FREESTRUCT) { 256 dns_rdata_zonemd_t *zonemd = source; 257 258 REQUIRE(zonemd != NULL); 259 REQUIRE(zonemd->common.rdtype == dns_rdatatype_zonemd); 260 261 if (zonemd->mctx == NULL) { 262 return; 263 } 264 265 if (zonemd->digest != NULL) { 266 isc_mem_free(zonemd->mctx, zonemd->digest); 267 } 268 zonemd->mctx = NULL; 269 } 270 271 static inline isc_result_t 272 additionaldata_zonemd(ARGS_ADDLDATA) { 273 REQUIRE(rdata->type == dns_rdatatype_zonemd); 274 275 UNUSED(rdata); 276 UNUSED(add); 277 UNUSED(arg); 278 279 return (ISC_R_SUCCESS); 280 } 281 282 static inline isc_result_t 283 digest_zonemd(ARGS_DIGEST) { 284 isc_region_t r; 285 286 REQUIRE(rdata->type == dns_rdatatype_zonemd); 287 288 dns_rdata_toregion(rdata, &r); 289 290 return ((digest)(arg, &r)); 291 } 292 293 static inline bool 294 checkowner_zonemd(ARGS_CHECKOWNER) { 295 REQUIRE(type == dns_rdatatype_zonemd); 296 297 UNUSED(name); 298 UNUSED(type); 299 UNUSED(rdclass); 300 UNUSED(wildcard); 301 302 return (true); 303 } 304 305 static inline bool 306 checknames_zonemd(ARGS_CHECKNAMES) { 307 REQUIRE(rdata->type == dns_rdatatype_zonemd); 308 309 UNUSED(rdata); 310 UNUSED(owner); 311 UNUSED(bad); 312 313 return (true); 314 } 315 316 static inline int 317 casecompare_zonemd(ARGS_COMPARE) { 318 return (compare_zonemd(rdata1, rdata2)); 319 } 320 321 #endif /* RDATA_GENERIC_ZONEMD_63_C */ 322