1/* $NetBSD: private_test.c,v 1.2 2024/02/21 22:52:50 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#include <inttypes.h> 17#include <sched.h> /* IWYU pragma: keep */ 18#include <setjmp.h> 19#include <stdarg.h> 20#include <stdbool.h> 21#include <stddef.h> 22#include <stdlib.h> 23#include <unistd.h> 24 25#define UNIT_TESTING 26#include <cmocka.h> 27 28#include <isc/buffer.h> 29#include <isc/util.h> 30 31#include <dns/nsec3.h> 32#include <dns/private.h> 33#include <dns/rdataclass.h> 34#include <dns/rdatatype.h> 35 36#include <dst/dst.h> 37 38#include <tests/dns.h> 39 40static dns_rdatatype_t privatetype = 65534; 41 42static int 43setup_test(void **state) { 44 isc_result_t result; 45 46 UNUSED(state); 47 48 result = dst_lib_init(mctx, NULL); 49 50 if (result != ISC_R_SUCCESS) { 51 return (1); 52 } 53 54 return (0); 55} 56 57static int 58teardown_test(void **state) { 59 UNUSED(state); 60 61 dst_lib_destroy(); 62 63 return (0); 64} 65 66typedef struct { 67 unsigned char alg; 68 dns_keytag_t keyid; 69 bool remove; 70 bool complete; 71} signing_testcase_t; 72 73typedef struct { 74 unsigned char hash; 75 unsigned char flags; 76 unsigned int iterations; 77 unsigned long salt; 78 bool remove; 79 bool pending; 80 bool nonsec; 81} nsec3_testcase_t; 82 83static void 84make_signing(signing_testcase_t *testcase, dns_rdata_t *private, 85 unsigned char *buf, size_t len) { 86 dns_rdata_init(private); 87 88 buf[0] = testcase->alg; 89 buf[1] = (testcase->keyid & 0xff00) >> 8; 90 buf[2] = (testcase->keyid & 0xff); 91 buf[3] = testcase->remove; 92 buf[4] = testcase->complete; 93 private->data = buf; 94 private->length = len; 95 private->type = privatetype; 96 private->rdclass = dns_rdataclass_in; 97} 98 99static void 100make_nsec3(nsec3_testcase_t *testcase, dns_rdata_t *private, 101 unsigned char *pbuf) { 102 dns_rdata_nsec3param_t params; 103 dns_rdata_t nsec3param = DNS_RDATA_INIT; 104 unsigned char bufdata[BUFSIZ]; 105 isc_buffer_t buf; 106 uint32_t salt; 107 unsigned char *sp; 108 int slen = 4; 109 110 /* for simplicity, we're using a maximum salt length of 4 */ 111 salt = htonl(testcase->salt); 112 sp = (unsigned char *)&salt; 113 while (slen > 0 && *sp == '\0') { 114 slen--; 115 sp++; 116 } 117 118 params.common.rdclass = dns_rdataclass_in; 119 params.common.rdtype = dns_rdatatype_nsec3param; 120 params.hash = testcase->hash; 121 params.iterations = testcase->iterations; 122 params.salt = sp; 123 params.salt_length = slen; 124 125 params.flags = testcase->flags; 126 if (testcase->remove) { 127 params.flags |= DNS_NSEC3FLAG_REMOVE; 128 if (testcase->nonsec) { 129 params.flags |= DNS_NSEC3FLAG_NONSEC; 130 } 131 } else { 132 params.flags |= DNS_NSEC3FLAG_CREATE; 133 if (testcase->pending) { 134 params.flags |= DNS_NSEC3FLAG_INITIAL; 135 } 136 } 137 138 isc_buffer_init(&buf, bufdata, sizeof(bufdata)); 139 dns_rdata_fromstruct(&nsec3param, dns_rdataclass_in, 140 dns_rdatatype_nsec3param, ¶ms, &buf); 141 142 dns_rdata_init(private); 143 144 dns_nsec3param_toprivate(&nsec3param, private, privatetype, pbuf, 145 DNS_NSEC3PARAM_BUFFERSIZE + 1); 146} 147 148/* convert private signing records to text */ 149ISC_RUN_TEST_IMPL(private_signing_totext) { 150 dns_rdata_t private; 151 int i; 152 153 signing_testcase_t testcases[] = { { DST_ALG_RSASHA512, 12345, 0, 0 }, 154 { DST_ALG_RSASHA256, 54321, 1, 0 }, 155 { DST_ALG_NSEC3RSASHA1, 22222, 0, 156 1 }, 157 { DST_ALG_RSASHA1, 33333, 1, 1 } }; 158 const char *results[] = { "Signing with key 12345/RSASHA512", 159 "Removing signatures for key 54321/RSASHA256", 160 "Done signing with key 22222/NSEC3RSASHA1", 161 ("Done removing signatures for key " 162 "33333/RSASHA1") }; 163 int ncases = 4; 164 165 UNUSED(state); 166 167 for (i = 0; i < ncases; i++) { 168 unsigned char data[5]; 169 char output[BUFSIZ]; 170 isc_buffer_t buf; 171 172 isc_buffer_init(&buf, output, sizeof(output)); 173 174 make_signing(&testcases[i], &private, data, sizeof(data)); 175 dns_private_totext(&private, &buf); 176 assert_string_equal(output, results[i]); 177 } 178} 179 180/* convert private chain records to text */ 181ISC_RUN_TEST_IMPL(private_nsec3_totext) { 182 dns_rdata_t private; 183 int i; 184 185 nsec3_testcase_t testcases[] = { 186 { 1, 0, 1, 0xbeef, 0, 0, 0 }, 187 { 1, 1, 10, 0xdadd, 0, 0, 0 }, 188 { 1, 0, 20, 0xbead, 0, 1, 0 }, 189 { 1, 0, 30, 0xdeaf, 1, 0, 0 }, 190 { 1, 0, 100, 0xfeedabee, 1, 0, 1 }, 191 }; 192 const char *results[] = { "Creating NSEC3 chain 1 0 1 BEEF", 193 "Creating NSEC3 chain 1 1 10 DADD", 194 "Pending NSEC3 chain 1 0 20 BEAD", 195 ("Removing NSEC3 chain 1 0 30 DEAF / " 196 "creating NSEC chain"), 197 "Removing NSEC3 chain 1 0 100 FEEDABEE" }; 198 int ncases = 5; 199 200 UNUSED(state); 201 202 for (i = 0; i < ncases; i++) { 203 unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1]; 204 char output[BUFSIZ]; 205 isc_buffer_t buf; 206 207 isc_buffer_init(&buf, output, sizeof(output)); 208 209 make_nsec3(&testcases[i], &private, data); 210 dns_private_totext(&private, &buf); 211 assert_string_equal(output, results[i]); 212 } 213} 214 215ISC_TEST_LIST_START 216ISC_TEST_ENTRY_CUSTOM(private_signing_totext, setup_test, teardown_test) 217ISC_TEST_ENTRY_CUSTOM(private_nsec3_totext, setup_test, teardown_test) 218ISC_TEST_LIST_END 219 220ISC_TEST_MAIN 221