xref: /netbsd-src/external/mpl/bind/dist/tests/dns/nsec3param_test.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1*bcda20f6Schristos /*	$NetBSD: nsec3param_test.c,v 1.3 2025/01/26 16:25:47 christos Exp $	*/
28aaca124Schristos 
38aaca124Schristos /*
48aaca124Schristos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
58aaca124Schristos  *
68aaca124Schristos  * SPDX-License-Identifier: MPL-2.0
78aaca124Schristos  *
88aaca124Schristos  * This Source Code Form is subject to the terms of the Mozilla Public
98aaca124Schristos  * License, v. 2.0. If a copy of the MPL was not distributed with this
108aaca124Schristos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
118aaca124Schristos  *
128aaca124Schristos  * See the COPYRIGHT file distributed with this work for additional
138aaca124Schristos  * information regarding copyright ownership.
148aaca124Schristos  */
158aaca124Schristos 
168aaca124Schristos #include <inttypes.h>
178aaca124Schristos #include <sched.h> /* IWYU pragma: keep */
188aaca124Schristos #include <setjmp.h>
198aaca124Schristos #include <stdarg.h>
208aaca124Schristos #include <stddef.h>
218aaca124Schristos #include <stdlib.h>
228aaca124Schristos #include <string.h>
238aaca124Schristos #include <unistd.h>
248aaca124Schristos 
258aaca124Schristos #define UNIT_TESTING
268aaca124Schristos #include <cmocka.h>
278aaca124Schristos 
288aaca124Schristos #include <isc/hex.h>
298aaca124Schristos #include <isc/result.h>
308aaca124Schristos #include <isc/string.h>
318aaca124Schristos #include <isc/util.h>
328aaca124Schristos 
338aaca124Schristos #include <dns/db.h>
348aaca124Schristos #include <dns/nsec3.h>
358aaca124Schristos 
368aaca124Schristos #include "zone_p.h"
378aaca124Schristos 
388aaca124Schristos #include <tests/dns.h>
398aaca124Schristos 
408aaca124Schristos #define HASH	1
418aaca124Schristos #define FLAGS	0
428aaca124Schristos #define ITER	5
438aaca124Schristos #define SALTLEN 4
448aaca124Schristos #define SALT	"FEDCBA98"
458aaca124Schristos 
468aaca124Schristos /*%
478aaca124Schristos  * Structures containing parameters for nsec3param_salttotext_test().
488aaca124Schristos  */
498aaca124Schristos typedef struct {
508aaca124Schristos 	dns_hash_t hash;
518aaca124Schristos 	unsigned char flags;
528aaca124Schristos 	dns_iterations_t iterations;
538aaca124Schristos 	unsigned char salt_length;
548aaca124Schristos 	const char *salt;
558aaca124Schristos } nsec3param_rdata_test_params_t;
568aaca124Schristos 
578aaca124Schristos typedef struct {
588aaca124Schristos 	nsec3param_rdata_test_params_t lookup;
598aaca124Schristos 	nsec3param_rdata_test_params_t expect;
608aaca124Schristos 	bool resalt;
618aaca124Schristos 	isc_result_t expected_result;
628aaca124Schristos } nsec3param_change_test_params_t;
638aaca124Schristos 
648aaca124Schristos static void
658aaca124Schristos decode_salt(const char *string, unsigned char *salt, size_t saltlen) {
668aaca124Schristos 	isc_buffer_t buf;
678aaca124Schristos 	isc_result_t result;
688aaca124Schristos 
698aaca124Schristos 	isc_buffer_init(&buf, salt, saltlen);
708aaca124Schristos 	result = isc_hex_decodestring(string, &buf);
718aaca124Schristos 	assert_int_equal(result, ISC_R_SUCCESS);
728aaca124Schristos }
738aaca124Schristos 
748aaca124Schristos static void
758aaca124Schristos copy_params(nsec3param_rdata_test_params_t from, dns_rdata_nsec3param_t *to,
768aaca124Schristos 	    unsigned char *saltbuf, size_t saltlen) {
778aaca124Schristos 	to->hash = from.hash;
788aaca124Schristos 	to->flags = from.flags;
798aaca124Schristos 	to->iterations = from.iterations;
808aaca124Schristos 	to->salt_length = from.salt_length;
818aaca124Schristos 	if (from.salt == NULL) {
828aaca124Schristos 		to->salt = NULL;
838aaca124Schristos 	} else if (strcmp(from.salt, "-") == 0) {
84*bcda20f6Schristos 		to->salt = (unsigned char *)"-";
858aaca124Schristos 	} else {
868aaca124Schristos 		decode_salt(from.salt, saltbuf, saltlen);
878aaca124Schristos 		to->salt = saltbuf;
888aaca124Schristos 	}
898aaca124Schristos }
908aaca124Schristos 
918aaca124Schristos static nsec3param_rdata_test_params_t
928aaca124Schristos rdata_fromparams(uint8_t hash, uint8_t flags, uint16_t iter, uint8_t saltlen,
938aaca124Schristos 		 const char *salt) {
948aaca124Schristos 	nsec3param_rdata_test_params_t nsec3param;
958aaca124Schristos 	nsec3param.hash = hash;
968aaca124Schristos 	nsec3param.flags = flags;
978aaca124Schristos 	nsec3param.iterations = iter;
988aaca124Schristos 	nsec3param.salt_length = saltlen;
998aaca124Schristos 	nsec3param.salt = salt;
100*bcda20f6Schristos 	return nsec3param;
1018aaca124Schristos }
1028aaca124Schristos 
1038aaca124Schristos /*%
1048aaca124Schristos  * Check whether zone_lookup_nsec3param() finds the correct NSEC3PARAM
1058aaca124Schristos  * and sets the correct parameters to use in dns_zone_setnsec3param().
1068aaca124Schristos  */
1078aaca124Schristos static void
1088aaca124Schristos nsec3param_change_test(const nsec3param_change_test_params_t *test) {
1098aaca124Schristos 	dns_zone_t *zone = NULL;
1108aaca124Schristos 	dns_rdata_nsec3param_t param, lookup, expect;
1118aaca124Schristos 	isc_result_t result;
1128aaca124Schristos 	unsigned char lookupsalt[255];
1138aaca124Schristos 	unsigned char expectsalt[255];
1148aaca124Schristos 	unsigned char saltbuf[255];
1158aaca124Schristos 
1168aaca124Schristos 	/*
1178aaca124Schristos 	 * Prepare a zone along with its signing keys.
1188aaca124Schristos 	 */
1198aaca124Schristos 	result = dns_test_makezone("nsec3", &zone, NULL, false);
1208aaca124Schristos 	assert_int_equal(result, ISC_R_SUCCESS);
1218aaca124Schristos 
1228aaca124Schristos 	result = dns_zone_setfile(
1238aaca124Schristos 		zone, TESTS_DIR "/testdata/nsec3param/nsec3.db.signed",
1248aaca124Schristos 		dns_masterformat_text, &dns_master_style_default);
1258aaca124Schristos 	assert_int_equal(result, ISC_R_SUCCESS);
1268aaca124Schristos 
1278aaca124Schristos 	result = dns_zone_load(zone, false);
1288aaca124Schristos 	assert_int_equal(result, ISC_R_SUCCESS);
1298aaca124Schristos 
1308aaca124Schristos 	/*
1318aaca124Schristos 	 * Copy parameters.
1328aaca124Schristos 	 */
1338aaca124Schristos 	copy_params(test->lookup, &lookup, lookupsalt, sizeof(lookupsalt));
1348aaca124Schristos 	copy_params(test->expect, &expect, expectsalt, sizeof(expectsalt));
1358aaca124Schristos 
1368aaca124Schristos 	/*
1378aaca124Schristos 	 * Test dns__zone_lookup_nsec3param().
1388aaca124Schristos 	 */
1398aaca124Schristos 	result = dns__zone_lookup_nsec3param(zone, &lookup, &param, saltbuf,
1408aaca124Schristos 					     test->resalt);
1418aaca124Schristos 	assert_int_equal(result, test->expected_result);
1428aaca124Schristos 	assert_int_equal(param.hash, expect.hash);
1438aaca124Schristos 	assert_int_equal(param.flags, expect.flags);
1448aaca124Schristos 	assert_int_equal(param.iterations, expect.iterations);
1458aaca124Schristos 	assert_int_equal(param.salt_length, expect.salt_length);
1468aaca124Schristos 	assert_non_null(param.salt);
1478aaca124Schristos 	if (expect.salt != NULL) {
1488aaca124Schristos 		int ret = memcmp(param.salt, expect.salt, expect.salt_length);
1498aaca124Schristos 		assert_true(ret == 0);
1508aaca124Schristos 	} else {
1518aaca124Schristos 		/*
1528aaca124Schristos 		 * We don't know what the new salt is, but we can compare it
1538aaca124Schristos 		 * to the previous salt and test that it has changed.
1548aaca124Schristos 		 */
1558aaca124Schristos 		unsigned char salt[SALTLEN];
1568aaca124Schristos 		int ret;
1578aaca124Schristos 		decode_salt(SALT, salt, SALTLEN);
1588aaca124Schristos 		ret = memcmp(param.salt, salt, SALTLEN);
1598aaca124Schristos 		assert_false(ret == 0);
1608aaca124Schristos 	}
1618aaca124Schristos 
1628aaca124Schristos 	/*
1638aaca124Schristos 	 * Detach.
1648aaca124Schristos 	 */
1658aaca124Schristos 	dns_zone_detach(&zone);
1668aaca124Schristos }
1678aaca124Schristos 
1688aaca124Schristos ISC_RUN_TEST_IMPL(nsec3param_change) {
1698aaca124Schristos 	size_t i;
1708aaca124Schristos 
1718aaca124Schristos 	/*
1728aaca124Schristos 	 * Define tests.
1738aaca124Schristos 	 */
1748aaca124Schristos 	const nsec3param_change_test_params_t tests[] = {
1758aaca124Schristos 		/*
1768aaca124Schristos 		 * 1. Change nothing (don't care about salt).
1778aaca124Schristos 		 * This should return ISC_R_SUCCESS because we are already
1788aaca124Schristos 		 * using these NSEC3 parameters.
1798aaca124Schristos 		 */
1808aaca124Schristos 		{ rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL),
1818aaca124Schristos 		  rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), false,
1828aaca124Schristos 		  ISC_R_SUCCESS },
1838aaca124Schristos 		/*
1848aaca124Schristos 		 * 2. Change nothing, but force a resalt.
1858aaca124Schristos 		 * This should change the salt. Set 'expect.salt' to NULL to
1868aaca124Schristos 		 * test a new salt has been generated.
1878aaca124Schristos 		 */
1888aaca124Schristos 		{ rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL),
1898aaca124Schristos 		  rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), true,
1908aaca124Schristos 		  DNS_R_NSEC3RESALT },
1918aaca124Schristos 		/*
1928aaca124Schristos 		 * 3. Change iterations.
1938aaca124Schristos 		 * The NSEC3 paarameters are not found, and there is no
1948aaca124Schristos 		 * need to resalt because an explicit salt has been set,
1958aaca124Schristos 		 * and resalt is not enforced.
1968aaca124Schristos 		 */
1978aaca124Schristos 		{ rdata_fromparams(HASH, FLAGS, 10, SALTLEN, SALT),
1988aaca124Schristos 		  rdata_fromparams(HASH, FLAGS, 10, SALTLEN, SALT), false,
1998aaca124Schristos 		  ISC_R_NOTFOUND },
2008aaca124Schristos 		/*
2018aaca124Schristos 		 * 4. Change iterations, don't care about the salt.
2028aaca124Schristos 		 * We don't care about the salt. Since we need to change the
2038aaca124Schristos 		 * NSEC3 parameters, we will also resalt.
2048aaca124Schristos 		 */
2058aaca124Schristos 		{ rdata_fromparams(HASH, FLAGS, 10, SALTLEN, NULL),
2068aaca124Schristos 		  rdata_fromparams(HASH, FLAGS, 10, SALTLEN, NULL), false,
2078aaca124Schristos 		  DNS_R_NSEC3RESALT },
2088aaca124Schristos 		/*
2098aaca124Schristos 		 * 5. Change salt length.
2108aaca124Schristos 		 * Changing salt length means we need to resalt.
2118aaca124Schristos 		 */
2128aaca124Schristos 		{ rdata_fromparams(HASH, FLAGS, ITER, 16, NULL),
2138aaca124Schristos 		  rdata_fromparams(HASH, FLAGS, ITER, 16, NULL), false,
2148aaca124Schristos 		  DNS_R_NSEC3RESALT },
2158aaca124Schristos 		/*
2168aaca124Schristos 		 * 6. Set explicit salt.
2178aaca124Schristos 		 * A different salt, so the NSEC3 parameters are not found.
2188aaca124Schristos 		 * No need to resalt because an explicit salt is available.
2198aaca124Schristos 		 */
2208aaca124Schristos 		{ rdata_fromparams(HASH, FLAGS, ITER, 4, "12345678"),
2218aaca124Schristos 		  rdata_fromparams(HASH, FLAGS, ITER, 4, "12345678"), false,
2228aaca124Schristos 		  ISC_R_NOTFOUND },
2238aaca124Schristos 		/*
2248aaca124Schristos 		 * 7. Same salt.
2258aaca124Schristos 		 * Nothing changed, so expect ISC_R_SUCCESS as a result.
2268aaca124Schristos 		 */
2278aaca124Schristos 		{ rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT),
2288aaca124Schristos 		  rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), false,
2298aaca124Schristos 		  ISC_R_SUCCESS },
2308aaca124Schristos 		/*
2318aaca124Schristos 		 * 8. Same salt, and force resalt.
2328aaca124Schristos 		 * Nothing changed, but a resalt is enforced.
2338aaca124Schristos 		 */
2348aaca124Schristos 		{ rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT),
2358aaca124Schristos 		  rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), true,
2368aaca124Schristos 		  DNS_R_NSEC3RESALT },
2378aaca124Schristos 		/*
2388aaca124Schristos 		 * 9. No salt.
2398aaca124Schristos 		 * Change parameters to use no salt. These parameters are
2408aaca124Schristos 		 * not found, and no new salt needs to be generated.
2418aaca124Schristos 		 */
2428aaca124Schristos 		{ rdata_fromparams(HASH, FLAGS, ITER, 0, NULL),
2438aaca124Schristos 		  rdata_fromparams(HASH, FLAGS, ITER, 0, "-"), true,
2448aaca124Schristos 		  ISC_R_NOTFOUND },
2458aaca124Schristos 		/*
2468aaca124Schristos 		 * 10. No salt, explicit.
2478aaca124Schristos 		 * Same as above, but set no salt explicitly.
2488aaca124Schristos 		 */
2498aaca124Schristos 		{ rdata_fromparams(HASH, FLAGS, ITER, 0, "-"),
2508aaca124Schristos 		  rdata_fromparams(HASH, FLAGS, ITER, 0, "-"), true,
2518aaca124Schristos 		  ISC_R_NOTFOUND },
2528aaca124Schristos 	};
2538aaca124Schristos 
2548aaca124Schristos 	UNUSED(state);
2558aaca124Schristos 
2568aaca124Schristos 	/*
2578aaca124Schristos 	 * Run tests.
2588aaca124Schristos 	 */
2598aaca124Schristos 	for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
2608aaca124Schristos 		nsec3param_change_test(&tests[i]);
2618aaca124Schristos 	}
2628aaca124Schristos }
2638aaca124Schristos 
2648aaca124Schristos ISC_TEST_LIST_START
2658aaca124Schristos ISC_TEST_ENTRY(nsec3param_change)
2668aaca124Schristos ISC_TEST_LIST_END
2678aaca124Schristos 
2688aaca124Schristos ISC_TEST_MAIN
269