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, &params, &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