nsec3 hash function unit test.

git-svn-id: file:///svn/unbound/trunk@615 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-09-17 09:25:54 +00:00
parent 48aec18ef7
commit c7d15770c1
5 changed files with 330 additions and 45 deletions

View File

@ -1,3 +1,6 @@
17 September 2007: Wouter
- NSEC3 hash cache unit test.
14 September 2007: Wouter
- nsec3 nodata proof, nods proof, wildcard proof.
- nsec3 support for cname chain ending in noerror or nodata.

View File

@ -43,12 +43,15 @@
#include "testcode/unitmain.h"
#include "validator/val_sigcrypt.h"
#include "validator/val_nsec.h"
#include "validator/val_nsec3.h"
#include "validator/validator.h"
#include "testcode/ldns-testpkts.h"
#include "util/data/msgreply.h"
#include "util/data/msgparse.h"
#include "util/data/dname.h"
#include "util/region-allocator.h"
#include "util/alloc.h"
#include "util/rbtree.h"
#include "util/net_help.h"
#include "util/module.h"
#include "util/config_file.h"
@ -91,7 +94,6 @@ entry_to_repinfo(struct entry* e, struct alloc_cache* alloc, struct region*
struct edns_data edns;
entry_to_buf(e, pkt);
ret = reply_info_parse(pkt, alloc, qi, rep, region, &edns);
region_free_all(region);
if(ret != 0) {
printf("parse code %d: %s\n", ret,
ldns_lookup_by_id(ldns_rcodes, ret)->name);
@ -228,6 +230,7 @@ dstest_entry(struct entry* e, struct alloc_cache* alloc, struct region*
printf("result(no)= %s\n", ret?"yes":"no");
}
unit_assert(!ret);
verbose(VERB_DETAIL, "DS fail: OK; matched unit test");
} else {
fatal_exit("Bad qname in DS unit test, yes or no");
}
@ -362,6 +365,87 @@ nsectest()
unit_assert(!unitest_nsec_has_type_rdata(bitmap, len, 2230));
}
/** Test hash algo - NSEC3 hash it and compare result */
static void
nsec3_hash_test_entry(struct entry* e, rbtree_t* ct,
struct alloc_cache* alloc, struct region* region,
ldns_buffer* buf)
{
struct query_info qinfo;
struct reply_info* rep = NULL;
struct ub_packed_rrset_key* answer, *nsec3;
struct nsec3_cached_hash* hash;
int ret;
uint8_t* qname;
if(vsig) {
printf("verifying NSEC3 hash:\n");
ldns_pkt_print(stdout, e->reply_list->reply);
printf("\n");
}
entry_to_repinfo(e, alloc, region, buf, &qinfo, &rep);
nsec3 = find_rrset_type(rep, LDNS_RR_TYPE_NSEC3);
answer = find_rrset_type(rep, LDNS_RR_TYPE_AAAA);
qname = region_alloc_init(region, qinfo.qname, qinfo.qname_len);
/* check test is OK */
unit_assert(nsec3 && answer && qname);
ret = nsec3_hash_name(ct, region, buf, nsec3, 0, qname,
qinfo.qname_len, &hash);
if(ret != 1) {
printf("Bad nsec3_hash_name retcode %d\n", ret);
unit_assert(ret == 1);
}
unit_assert(hash->dname && hash->hash && hash->hash_len &&
hash->b32 && hash->b32_len);
unit_assert(hash->b32_len == (size_t)answer->rk.dname[0]);
/* does not do lowercasing. */
unit_assert(memcmp(hash->b32, answer->rk.dname+1, hash->b32_len)
== 0);
reply_info_parsedelete(rep, alloc);
query_info_clear(&qinfo);
}
/** Read file to test NSEC3 hash algo */
static void
nsec3_hash_test(const char* fname)
{
/*
* The list contains a list of ldns-testpkts entries.
* Every entry is a test.
* The qname is hashed.
* The answer section AAAA RR name is the required result.
* The auth section NSEC3 is used to get hash parameters.
* The hash cache is maintained per file.
*
* The test does not perform canonicalization during the compare.
*/
rbtree_t ct;
struct region* region = region_create(malloc, free);
struct alloc_cache alloc;
ldns_buffer* buf = ldns_buffer_new(65535);
struct entry* e;
struct entry* list = read_datafile(fname);
if(!list)
fatal_exit("could not read %s: %s", fname, strerror(errno));
rbtree_init(&ct, &nsec3_hash_cmp);
alloc_init(&alloc, NULL, 1);
unit_assert(region && buf);
/* ready to go! */
for(e = list; e; e = e->next) {
nsec3_hash_test_entry(e, &ct, &alloc, region, buf);
}
delete_entry(list);
region_destroy(region);
alloc_clear(&alloc);
ldns_buffer_free(buf);
}
void
verify_test()
{
@ -369,4 +453,5 @@ verify_test()
verifytest_file("testdata/test_signatures.1", "20070818005004");
dstest_file("testdata/test_ds_sig.1");
nsectest();
nsec3_hash_test("testdata/test_nsec3_hash.1");
}

180
testdata/test_nsec3_hash.1 vendored Normal file
View File

@ -0,0 +1,180 @@
;
; NSEC3 hash algo test file.
; The hash cache is maintained for the duration of the file.
; Every entry is a hash test.
; query name is hashed.
; answer AAAA record hash the correct hashed answer name.
; auth NSEC3 record has the hash parameters.
;
; These are from the nsec3-draft-11 example zone.
; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
ENTRY_BEGIN
SECTION QUESTION
example. IN AAAA
SECTION ANSWER
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; H(a.example) = 35mthgpgcu1qg68fab165klnsnk3dpvl
ENTRY_BEGIN
SECTION QUESTION
a.example. IN AAAA
SECTION ANSWER
35mthgpgcu1qg68fab165klnsnk3dpvl.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; H(ai.example) = gjeqe526plbf1g8mklp59enfd789njgi
ENTRY_BEGIN
SECTION QUESTION
ai.example. IN AAAA
SECTION ANSWER
gjeqe526plbf1g8mklp59enfd789njgi.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; H(ns1.example) = 2t7b4g4vsa5smi47k61mv5bv1a22bojr
ENTRY_BEGIN
SECTION QUESTION
ns1.example. IN AAAA
SECTION ANSWER
2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; H(ns2.example) = q04jkcevqvmu85r014c7dkba38o0ji5r
ENTRY_BEGIN
SECTION QUESTION
ns2.example. IN AAAA
SECTION ANSWER
q04jkcevqvmu85r014c7dkba38o0ji5r.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; H(w.example) = k8udemvp1j2f7eg6jebps17vp3n8i58h
ENTRY_BEGIN
SECTION QUESTION
w.example. IN AAAA
SECTION ANSWER
k8udemvp1j2f7eg6jebps17vp3n8i58h.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; H(*.w.example) = r53bq7cc2uvmubfu5ocmm6pers9tk9en
ENTRY_BEGIN
SECTION QUESTION
*.w.example. IN AAAA
SECTION ANSWER
r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995
ENTRY_BEGIN
SECTION QUESTION
x.w.example. IN AAAA
SECTION ANSWER
b4um86eghhds6nea196smvmlo4ors995.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; H(y.w.example) = ji6neoaepv8b5o6k4ev33abha8ht9fgc
ENTRY_BEGIN
SECTION QUESTION
y.w.example. IN AAAA
SECTION ANSWER
ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; H(x.y.w.example) = 2vptu5timamqttgl4luu9kg21e0aor3s
ENTRY_BEGIN
SECTION QUESTION
x.y.w.example. IN AAAA
SECTION ANSWER
2vptu5timamqttgl4luu9kg21e0aor3s.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; H(xx.example) = t644ebqk9bibcna874givr6joj62mlhv
; capitalization changed.
ENTRY_BEGIN
SECTION QUESTION
xX.example. IN AAAA
SECTION ANSWER
t644ebqk9bibcna874givr6joj62mlhv.example. AAAA ::1
SECTION AUTHORITY
b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd (gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
ENTRY_END
; H(2t7b4g4vsa5smi47k61mv5bv1a22bojr.example)
; = kohar7mbb8dc2ce8a9qvl8hon4k53uhi
ENTRY_BEGIN
SECTION QUESTION
2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. IN AAAA
SECTION ANSWER
kohar7mbb8dc2ce8a9qvl8hon4k53uhi.example. AAAA ::1
SECTION AUTHORITY
b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd (gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
ENTRY_END
; repeat entry to test the cache.
; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
ENTRY_BEGIN
SECTION QUESTION
example. IN AAAA
SECTION ANSWER
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; repeat entry to test the cache.
; H(a.example) = 35mthgpgcu1qg68fab165klnsnk3dpvl
ENTRY_BEGIN
SECTION QUESTION
a.example. IN AAAA
SECTION ANSWER
35mthgpgcu1qg68fab165klnsnk3dpvl.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; repeat entry to test the cache.
; H(ai.example) = gjeqe526plbf1g8mklp59enfd789njgi
ENTRY_BEGIN
SECTION QUESTION
ai.example. IN AAAA
SECTION ANSWER
gjeqe526plbf1g8mklp59enfd789njgi.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END
; repeat entry to test the cache.
; capitalization of qname.
; H(ai.example) = gjeqe526plbf1g8mklp59enfd789njgi
ENTRY_BEGIN
SECTION QUESTION
AI.example. IN AAAA
SECTION ANSWER
gjeqe526plbf1g8mklp59enfd789njgi.example. AAAA ::1
SECTION AUTHORITY
0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS SOA NSEC3PARAM RRSIG )
ENTRY_END

View File

@ -66,33 +66,6 @@ int b32_ntop_extended_hex(uint8_t const *src, size_t srclength,
int b32_pton_extended_hex(char const *src, size_t hashed_owner_str_len,
uint8_t *target, size_t targsize);
/**
* The NSEC3 hash result storage.
* Consists of an rbtree, with these nodes in it.
* The nodes detail how a set of parameters (from nsec3 rr) plus
* a dname result in a hash.
*/
struct nsec3_cached_hash {
/** rbtree node, key is this structure */
rbnode_t node;
/** where are the parameters for conversion, in this rrset data */
struct ub_packed_rrset_key* nsec3;
/** where are the parameters for conversion, this RR number in data */
int rr;
/** the name to convert */
uint8_t* dname;
/** length of the dname */
size_t dname_len;
/** the hash result (not base32 encoded) */
uint8_t* hash;
/** length of hash in bytes */
size_t hash_len;
/** the hash result in base32 encoding */
uint8_t* b32;
/** length of base32 encoding (as a label) */
size_t b32_len;
};
/**
* Closest encloser (ce) proof results
* Contains the ce and the next-closer (nc) proof.
@ -472,7 +445,7 @@ nsec3_iteration_count_high(struct val_env* ve, struct nsec3_filter* filter,
}
/** nsec3_cache_compare for rbtree */
static int
int
nsec3_hash_cmp(const void* c1, const void* c2)
{
struct nsec3_cached_hash* h1 = (struct nsec3_cached_hash*)c1;
@ -545,6 +518,7 @@ nsec3_calc_hash(struct region* region, ldns_buffer* buf,
(unsigned long)ldns_buffer_limit(buf),
(unsigned char*)c->hash);
}
break;
#endif /* SHA_DIGEST_LENGTH */
default:
log_err("nsec3 hash of unknown algo %d", algo);
@ -573,22 +547,7 @@ nsec3_calc_b32(struct region* region, ldns_buffer* buf,
return 1;
}
/**
* Obtain the hash of an owner name.
* @param table: the cache table. Must be inited at start.
* @param region: scratch region to use for allocation.
* @param buf: temporary buffer.
* @param nsec3: the rrset with parameters
* @param rr: rr number from d that has the NSEC3 parameters to hash to.
* @param dname: name to hash
* @param dname_len: the length of the name.
* @param hash: the hash node is returned on success.
* @return:
* 1 on success, either from cache or newly hashed hash is returned.
* 0 on a malloc failure.
* -1 if the NSEC3 rr was badly formatted (i.e. formerr).
*/
static int
int
nsec3_hash_name(rbtree_t* table, struct region* region, ldns_buffer* buf,
struct ub_packed_rrset_key* nsec3, int rr, uint8_t* dname,
size_t dname_len, struct nsec3_cached_hash** hash)

View File

@ -66,7 +66,9 @@
#ifndef VALIDATOR_VAL_NSEC3_H
#define VALIDATOR_VAL_NSEC3_H
#include "util/rbtree.h"
struct val_env;
struct region;
struct module_env;
struct ub_packed_rrset_key;
enum sec_status;
@ -211,4 +213,60 @@ nsec3_prove_nxornodata(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num,
struct query_info* qinfo, struct key_entry_key* kkey, int* nodata);
/**
* The NSEC3 hash result storage.
* Consists of an rbtree, with these nodes in it.
* The nodes detail how a set of parameters (from nsec3 rr) plus
* a dname result in a hash.
*/
struct nsec3_cached_hash {
/** rbtree node, key is this structure */
rbnode_t node;
/** where are the parameters for conversion, in this rrset data */
struct ub_packed_rrset_key* nsec3;
/** where are the parameters for conversion, this RR number in data */
int rr;
/** the name to convert */
uint8_t* dname;
/** length of the dname */
size_t dname_len;
/** the hash result (not base32 encoded) */
uint8_t* hash;
/** length of hash in bytes */
size_t hash_len;
/** the hash result in base32 encoding */
uint8_t* b32;
/** length of base32 encoding (as a label) */
size_t b32_len;
};
/**
* Rbtree for hash cache comparison function
*/
int nsec3_hash_cmp(const void* c1, const void* c2);
/**
* Obtain the hash of an owner name.
* Used internally by the nsec3 proof functions in this file.
* published to enable unit testing of hash algorithms and cache.
*
* @param table: the cache table. Must be inited at start.
* @param region: scratch region to use for allocation.
* This region holds the tree, if you wipe the region, reinit the tree.
* @param buf: temporary buffer.
* @param nsec3: the rrset with parameters
* @param rr: rr number from d that has the NSEC3 parameters to hash to.
* @param dname: name to hash
* This pointer is used inside the tree, assumed region-alloced.
* @param dname_len: the length of the name.
* @param hash: the hash node is returned on success.
* @return:
* 1 on success, either from cache or newly hashed hash is returned.
* 0 on a malloc failure.
* -1 if the NSEC3 rr was badly formatted (i.e. formerr).
*/
int nsec3_hash_name(rbtree_t* table, struct region* region, ldns_buffer* buf,
struct ub_packed_rrset_key* nsec3, int rr, uint8_t* dname,
size_t dname_len, struct nsec3_cached_hash** hash);
#endif /* VALIDATOR_VAL_NSEC3_H */