sigcrypt keyset processing

git-svn-id: file:///svn/unbound/trunk@501 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-08-08 13:59:57 +00:00
parent bdb519c5c1
commit 8f58908f45
4 changed files with 214 additions and 8 deletions

View file

@ -1,6 +1,8 @@
8 August 2007: Wouter
- ldns _raw routines created (in ldns trunk).
- sigcrypt DS digest routines
- val_utils uses sigcrypt to perform signature cryptography.
- sigcrypt keyset processing
7 August 2007: Wouter
- security status type.

View file

@ -51,6 +51,60 @@
#error "Need SSL library to do digital signature cryptography"
#endif
/** return number of rrs in an rrset */
static size_t
rrset_get_count(struct ub_packed_rrset_key* rrset)
{
struct packed_rrset_data* d = (struct packed_rrset_data*)
rrset->entry.data;
if(!d) return 0;
return d->count;
}
/**
* Get RR signature count
*/
static size_t
rrset_get_sigcount(struct ub_packed_rrset_key* k)
{
struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
return d->rrsig_count;
}
/**
* Get signature keytag value
* @param k: rrset (with signatures)
* @param sig_idx: signature index.
* @return keytag or 0 if malformed rrsig.
*/
static uint16_t
rrset_get_sig_keytag(struct ub_packed_rrset_key* k, size_t sig_idx)
{
uint16_t t;
struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
log_assert(sig_idx < d->rrsig_count);
if(d->rr_len[d->count + sig_idx] < 2+18)
return 0;
memmove(&t, d->rr_data[d->count + sig_idx]+2+16, 2);
return t;
}
/**
* Get signature signing algorithm value
* @param k: rrset (with signatures)
* @param sig_idx: signature index.
* @return algo or 0 if malformed rrsig.
*/
static int
rrset_get_sig_algo(struct ub_packed_rrset_key* k, size_t sig_idx)
{
struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
log_assert(sig_idx < d->rrsig_count);
if(d->rr_len[d->count + sig_idx] < 2+3)
return 0;
return (int)d->rr_data[d->count + sig_idx][2+2];
}
/** get rdata pointer and size */
static void
rrset_get_rdata(struct ub_packed_rrset_key* k, size_t idx, uint8_t** rdata,
@ -286,3 +340,97 @@ int dnskey_algo_is_supported(struct ub_packed_rrset_key* dnskey_rrset,
dnskey_idx));
}
enum sec_status
dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey)
{
enum sec_status sec;
size_t i, num;
num = rrset_get_sigcount(rrset);
if(num == 0) {
verbose(VERB_ALGO, "rrset failed to verify due to a lack of "
"signatures");
return sec_status_bogus;
}
for(i=0; i<num; i++) {
sec = dnskeyset_verify_rrset_sig(env, ve, rrset, dnskey, i);
if(sec == sec_status_secure)
return sec;
}
verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus");
return sec_status_bogus;
}
enum sec_status
dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx)
{
enum sec_status sec;
size_t i, num;
num = rrset_get_sigcount(rrset);
if(num == 0) {
verbose(VERB_ALGO, "rrset failed to verify due to a lack of "
"signatures");
return sec_status_bogus;
}
for(i=0; i<num; i++) {
sec = dnskey_verify_rrset_sig(env, ve, rrset, dnskey,
dnskey_idx, i);
if(sec == sec_status_secure)
return sec;
}
verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus");
return sec_status_bogus;
}
enum sec_status
dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t sig_idx)
{
/* find matching keys and check them */
enum sec_status sec = sec_status_bogus;
uint16_t tag = rrset_get_sig_keytag(rrset, sig_idx);
int algo = rrset_get_sig_algo(rrset, sig_idx);
size_t i, num = rrset_get_count(dnskey);
size_t numchecked = 0;
for(i=0; i<num; i++) {
/* see if key matches keytag and algo */
if(algo != dnskey_get_algo(dnskey, i) ||
tag != dnskey_calc_keytag(dnskey, i))
continue;
numchecked ++;
/* see if key verifies */
sec = dnskey_verify_rrset_sig(env, ve, rrset, dnskey,
i, sig_idx);
if(sec == sec_status_secure)
return sec;
}
if(numchecked == 0) {
verbose(VERB_ALGO, "could not find appropriate key");
return sec_status_bogus;
}
return sec_status_bogus;
}
enum sec_status
dnskey_verify_rrset_sig(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, size_t sig_idx)
{
/* verify as many fields in rrsig as possible */
/* verify key dname == sig signer name */
/* verify covered type */
/* verify keytag and sig algo (possibly again) */
/* verify labels is in a valid range */
/* original ttl, always ok */
/* verify inception, expiration dates */
/* create rrset canonical format in buffer, ready for signature */
/* verify */
return sec_status_unchecked;
}

View file

@ -46,6 +46,7 @@
struct val_env;
struct module_env;
struct ub_packed_rrset_key;
enum sec_status;
/**
* Check if dnskey matches a DS digest
@ -121,12 +122,61 @@ int ds_get_key_algo(struct ub_packed_rrset_key* k, size_t idx);
*/
int dnskey_get_algo(struct ub_packed_rrset_key* k, size_t idx);
/** verify rrset against dnskey rrset. */
/**
* Verify rrset against dnskey rrset.
* @param env: module environment, scratch space is used.
* @param ve: validator environment, date settings.
* @param rrset: to be validated.
* @param dnskey: DNSKEY rrset, keyset to try.
* @return SECURE if one key in the set verifies one rrsig.
* UNCHECKED on allocation errors, unsupported algorithms, malformed data,
* and BOGUS on verification failures (no keys match any signatures).
*/
enum sec_status dnskeyset_verify_rrset(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey);
/** verify rrset against one specific dnskey (from rrset) */
/**
* verify rrset against one specific dnskey (from rrset)
* @param env: module environment, scratch space is used.
* @param ve: validator environment, date settings.
* @param rrset: to be validated.
* @param dnskey: DNSKEY rrset, keyset.
* @param dnskey_idx: which key from the rrset to try.
* @return secure if *this* key signs any of the signatures on rrset.
* unchecked on error or and bogus on bad signature.
*/
enum sec_status dnskey_verify_rrset(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t dnskey_idx);
/** verify rrset, with dnskey rrset, for a specific rrsig in rrset */
/**
* verify rrset, with dnskey rrset, for a specific rrsig in rrset
* @param env: module environment, scratch space is used.
* @param ve: validator environment, date settings.
* @param rrset: to be validated.
* @param dnskey: DNSKEY rrset, keyset to try.
* @param sig_idx: which signature to try to validate.
* @return secure if any key signs *this* signature. bogus if no key signs it,
* or unchecked on error.
*/
enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t sig_idx);
/** verify rrset, with specific dnskey(from set), for a specific rrsig */
/**
* verify rrset, with specific dnskey(from set), for a specific rrsig
* @param env: module environment, scratch space is used.
* @param ve: validator environment, date settings.
* @param rrset: to be validated.
* @param dnskey: DNSKEY rrset, keyset.
* @param dnskey_idx: which key from the rrset to try.
* @param sig_idx: which signature to try to validate.
* @return secure if this key signs this signature. unchecked on error or
* bogus if it did not validate.
*/
enum sec_status dnskey_verify_rrset_sig(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, size_t sig_idx);
#endif /* VALIDATOR_VAL_SIGCRYPT_H */

View file

@ -199,8 +199,15 @@ enum sec_status
val_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys)
{
enum sec_status sec;
log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname,
ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
sec = dnskeyset_verify_rrset(env, ve, rrset, keys);
verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
return sec_status_bogus;
/* TODO: update rrset security status */
return sec;
}
/** verify that a DS RR hashes to a key and that key signs the set */
@ -230,9 +237,8 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
/* Otherwise, we have a match! Make sure that the DNSKEY
* verifies *with this key* */
/*
sec = verify_rrset_key(env, ve, dnskey_rrset, dnskey_rrset, i);
*/
sec = dnskey_verify_rrset(env, ve, dnskey_rrset,
dnskey_rrset, i);
if(sec == sec_status_secure) {
return sec;
}