1/*	$NetBSD: nsec3_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 <stddef.h>
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24
25#define UNIT_TESTING
26#include <cmocka.h>
27
28#include <isc/string.h>
29#include <isc/util.h>
30
31#include <dns/db.h>
32#include <dns/nsec3.h>
33
34#include <tests/dns.h>
35
36static void
37iteration_test(const char *file, unsigned int expected) {
38	isc_result_t result;
39	dns_db_t *db = NULL;
40	unsigned int iterations;
41
42	result = dns_test_loaddb(&db, dns_dbtype_zone, "test", file);
43	assert_int_equal(result, ISC_R_SUCCESS);
44
45	iterations = dns_nsec3_maxiterations();
46
47	assert_int_equal(iterations, expected);
48
49	dns_db_detach(&db);
50}
51
52/*%
53 * Structure containing parameters for nsec3param_salttotext_test().
54 */
55typedef struct {
56	const char *nsec3param_text; /* NSEC3PARAM RDATA in text form */
57	const char *expected_salt;   /* string expected in target buffer */
58} nsec3param_salttotext_test_params_t;
59
60/*%
61 * Check whether dns_nsec3param_salttotext() handles supplied text form
62 * NSEC3PARAM RDATA correctly: test whether the result of calling the former is
63 * as expected and whether it properly checks available buffer space.
64 *
65 * Assumes supplied text form NSEC3PARAM RDATA is valid as testing handling of
66 * invalid NSEC3PARAM RDATA is out of scope of this unit test.
67 */
68static void
69nsec3param_salttotext_test(const nsec3param_salttotext_test_params_t *params) {
70	dns_rdata_t rdata = DNS_RDATA_INIT;
71	dns_rdata_nsec3param_t nsec3param;
72	unsigned char buf[1024];
73	isc_result_t result;
74	char salt[64];
75	size_t length;
76
77	/*
78	 * Prepare a dns_rdata_nsec3param_t structure for testing.
79	 */
80	result = dns_test_rdatafromstring(
81		&rdata, dns_rdataclass_in, dns_rdatatype_nsec3param, buf,
82		sizeof(buf), params->nsec3param_text, false);
83	assert_int_equal(result, ISC_R_SUCCESS);
84	result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
85	assert_int_equal(result, ISC_R_SUCCESS);
86
87	/*
88	 * Check typical use.
89	 */
90	result = dns_nsec3param_salttotext(&nsec3param, salt, sizeof(salt));
91	assert_int_equal(result, ISC_R_SUCCESS);
92	assert_string_equal(salt, params->expected_salt);
93
94	/*
95	 * Ensure available space in the buffer is checked before the salt is
96	 * printed to it and that the amount of space checked for includes the
97	 * terminating NULL byte.
98	 */
99	length = strlen(params->expected_salt);
100	assert_true(length < sizeof(salt) - 1); /* prevent buffer overwrite */
101	assert_true(length > 0U);		/* prevent length underflow */
102
103	result = dns_nsec3param_salttotext(&nsec3param, salt, length - 1);
104	assert_int_equal(result, ISC_R_NOSPACE);
105
106	result = dns_nsec3param_salttotext(&nsec3param, salt, length);
107	assert_int_equal(result, ISC_R_NOSPACE);
108
109	result = dns_nsec3param_salttotext(&nsec3param, salt, length + 1);
110	assert_int_equal(result, ISC_R_SUCCESS);
111}
112
113/*
114 * check that appropriate max iterations is returned for different
115 * key size mixes
116 */
117ISC_RUN_TEST_IMPL(max_iterations) {
118	UNUSED(state);
119
120	iteration_test(TESTS_DIR "/testdata/nsec3/1024.db", 150);
121	iteration_test(TESTS_DIR "/testdata/nsec3/2048.db", 150);
122	iteration_test(TESTS_DIR "/testdata/nsec3/4096.db", 150);
123	iteration_test(TESTS_DIR "/testdata/nsec3/min-1024.db", 150);
124	iteration_test(TESTS_DIR "/testdata/nsec3/min-2048.db", 150);
125}
126
127/* check dns_nsec3param_salttotext() */
128ISC_RUN_TEST_IMPL(nsec3param_salttotext) {
129	size_t i;
130
131	const nsec3param_salttotext_test_params_t tests[] = {
132		/*
133		 * Tests with non-empty salts.
134		 */
135		{ "0 0 10 0123456789abcdef", "0123456789ABCDEF" },
136		{ "0 1 11 0123456789abcdef", "0123456789ABCDEF" },
137		{ "1 0 12 42", "42" },
138		{ "1 1 13 42", "42" },
139		/*
140		 * Test with empty salt.
141		 */
142		{ "0 0 0 -", "-" },
143	};
144
145	UNUSED(state);
146
147	for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
148		nsec3param_salttotext_test(&tests[i]);
149	}
150}
151
152ISC_TEST_LIST_START
153ISC_TEST_ENTRY(max_iterations)
154ISC_TEST_ENTRY(nsec3param_salttotext)
155ISC_TEST_LIST_END
156
157ISC_TEST_MAIN
158