static void test_dnssec_nsec3_hash(void) { static const uint8_t salt[] = { 0xB0, 0x1D, 0xFA, 0xCE }; static const uint8_t next_hashed_name[] = { 0x84, 0x10, 0x26, 0x53, 0xc9, 0xfa, 0x4d, 0x85, 0x6c, 0x97, 0x82, 0xe2, 0x8f, 0xdf, 0x2d, 0x5e, 0x87, 0x69, 0xc4, 0x52 }; _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; uint8_t h[DNSSEC_HASH_SIZE_MAX]; _cleanup_free_ char *b = NULL; int k; /* The NSEC3 RR for eurid.eu on 2015-12-14. */ rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC3, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM.eurid.eu."); assert_se(rr); rr->nsec3.algorithm = DNSSEC_DIGEST_SHA1; rr->nsec3.flags = 1; rr->nsec3.iterations = 1; rr->nsec3.salt = memdup(salt, sizeof(salt)); assert_se(rr->nsec3.salt); rr->nsec3.salt_size = sizeof(salt); rr->nsec3.next_hashed_name = memdup(next_hashed_name, sizeof(next_hashed_name)); assert_se(rr->nsec3.next_hashed_name); rr->nsec3.next_hashed_name_size = sizeof(next_hashed_name); log_info("NSEC3: %s", strna(dns_resource_record_to_string(rr))); k = dnssec_nsec3_hash(rr, "eurid.eu", &h); assert_se(k >= 0); b = base32hexmem(h, k, false); assert_se(b); assert_se(strcasecmp(b, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM") == 0); }
/*! * \brief Create NSEC3 owner name from regular owner name. * * \param owner Node owner name. * \param zone_apex Zone apex name. * \param params Params for NSEC3 hashing function. * * \return NSEC3 owner name, NULL in case of error. */ knot_dname_t *knot_create_nsec3_owner(const knot_dname_t *owner, const knot_dname_t *zone_apex, const knot_nsec3_params_t *params) { if (owner == NULL || zone_apex == NULL || params == NULL) { return NULL; } int owner_size = knot_dname_size(owner); if (owner_size < 0) { return NULL; } dnssec_binary_t data = { 0 }; data.data = (uint8_t *)owner; data.size = owner_size; dnssec_binary_t hash = { 0 }; dnssec_nsec3_params_t xparams = { .algorithm = params->algorithm, .flags = params->flags, .iterations = params->iterations, .salt = { .data = params->salt, .size = params->salt_length } }; int r = dnssec_nsec3_hash(&data, &xparams, &hash); if (r != DNSSEC_EOK) { return NULL; } knot_dname_t *result = knot_nsec3_hash_to_dname(hash.data, hash.size, zone_apex); dnssec_binary_free(&hash); return result; }
/*! * \brief Entry point of 'knsec3hash'. */ int main(int argc, char *argv[]) { struct option options[] = { { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { NULL } }; int opt = 0; int li = 0; while ((opt = getopt_long(argc, argv, "hV", options, &li)) != -1) { switch(opt) { case 'V': printf("%s, version %s\n", PROGRAM_NAME, PACKAGE_VERSION); return 0; case 'h': usage(stdout); return 0; default: usage(stderr); return 1; } } // knsec3hash <salt> <algorithm> <iterations> <domain> if (argc != 5) { usage(stderr); return 1; } int exit_code = 1; dnssec_nsec3_params_t nsec3_params = { 0 }; dnssec_binary_t dname = { 0 }; dnssec_binary_t digest = { 0 }; dnssec_binary_t digest_print = { 0 }; if (!parse_nsec3_params(&nsec3_params, argv[1], argv[2], argv[3])) { goto fail; } dname.data = dname_from_ascii(argv[4]); dname.size = dname_length(dname.data); if (dname.data == NULL) { error("Cannot parse domain name."); goto fail; } dname_normalize(dname.data); int r = dnssec_nsec3_hash(&dname, &nsec3_params, &digest); if (r != DNSSEC_EOK) { error("Cannot compute NSEC3 hash, %s.", dnssec_strerror(r)); goto fail; } r = base32hex_encode(&digest, &digest_print); if (r != DNSSEC_EOK) { error("Cannot encode computed hash, %s.", dnssec_strerror(r)); goto fail; } exit_code = 0; printf("%.*s (salt=%s, hash=%d, iterations=%d)\n", (int)digest_print.size, digest_print.data, argv[1], nsec3_params.algorithm, nsec3_params.iterations); fail: dnssec_nsec3_params_free(&nsec3_params); dnssec_binary_free(&dname); dnssec_binary_free(&digest); dnssec_binary_free(&digest_print); return exit_code; }