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.
#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,
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;
+}
struct val_env;
struct module_env;
struct ub_packed_rrset_key;
+enum sec_status;
/**
* Check if dnskey matches a DS digest
*/
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 */
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 */
/* 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;
}