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, ¶m, 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