mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
sigcrypt keyset processing
git-svn-id: file:///svn/unbound/trunk@501 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
bdb519c5c1
commit
8f58908f45
4 changed files with 214 additions and 8 deletions
|
|
@ -1,6 +1,8 @@
|
||||||
8 August 2007: Wouter
|
8 August 2007: Wouter
|
||||||
- ldns _raw routines created (in ldns trunk).
|
- ldns _raw routines created (in ldns trunk).
|
||||||
- sigcrypt DS digest routines
|
- sigcrypt DS digest routines
|
||||||
|
- val_utils uses sigcrypt to perform signature cryptography.
|
||||||
|
- sigcrypt keyset processing
|
||||||
|
|
||||||
7 August 2007: Wouter
|
7 August 2007: Wouter
|
||||||
- security status type.
|
- security status type.
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,60 @@
|
||||||
#error "Need SSL library to do digital signature cryptography"
|
#error "Need SSL library to do digital signature cryptography"
|
||||||
#endif
|
#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 */
|
/** get rdata pointer and size */
|
||||||
static void
|
static void
|
||||||
rrset_get_rdata(struct ub_packed_rrset_key* k, size_t idx, uint8_t** rdata,
|
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));
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@
|
||||||
struct val_env;
|
struct val_env;
|
||||||
struct module_env;
|
struct module_env;
|
||||||
struct ub_packed_rrset_key;
|
struct ub_packed_rrset_key;
|
||||||
|
enum sec_status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if dnskey matches a DS digest
|
* 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);
|
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 */
|
#endif /* VALIDATOR_VAL_SIGCRYPT_H */
|
||||||
|
|
|
||||||
|
|
@ -199,8 +199,15 @@ enum sec_status
|
||||||
val_verify_rrset(struct module_env* env, struct val_env* ve,
|
val_verify_rrset(struct module_env* env, struct val_env* ve,
|
||||||
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys)
|
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 */
|
/** 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
|
/* Otherwise, we have a match! Make sure that the DNSKEY
|
||||||
* verifies *with this key* */
|
* verifies *with this key* */
|
||||||
/*
|
sec = dnskey_verify_rrset(env, ve, dnskey_rrset,
|
||||||
sec = verify_rrset_key(env, ve, dnskey_rrset, dnskey_rrset, i);
|
dnskey_rrset, i);
|
||||||
*/
|
|
||||||
if(sec == sec_status_secure) {
|
if(sec == sec_status_secure) {
|
||||||
return sec;
|
return sec;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue