aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/validator
diff options
context:
space:
mode:
Diffstat (limited to 'external/unbound/validator')
-rw-r--r--external/unbound/validator/autotrust.c10
-rw-r--r--external/unbound/validator/val_neg.c2
-rw-r--r--external/unbound/validator/val_neg.h2
-rw-r--r--external/unbound/validator/val_nsec.c28
-rw-r--r--external/unbound/validator/val_nsec.h6
-rw-r--r--external/unbound/validator/val_nsec3.c136
-rw-r--r--external/unbound/validator/val_nsec3.h6
-rw-r--r--external/unbound/validator/val_secalgo.c520
-rw-r--r--external/unbound/validator/val_secalgo.h15
-rw-r--r--external/unbound/validator/val_sigcrypt.c6
-rw-r--r--external/unbound/validator/val_utils.h2
-rw-r--r--external/unbound/validator/validator.c6
12 files changed, 620 insertions, 119 deletions
diff --git a/external/unbound/validator/autotrust.c b/external/unbound/validator/autotrust.c
index e63b086e6..f8c9c8c63 100644
--- a/external/unbound/validator/autotrust.c
+++ b/external/unbound/validator/autotrust.c
@@ -1195,6 +1195,14 @@ void autr_write_file(struct module_env* env, struct trust_anchor* tp)
fatal_exit("could not completely write: %s", fname);
return;
}
+ if(fflush(out) != 0)
+ log_err("could not fflush(%s): %s", fname, strerror(errno));
+#ifdef HAVE_FSYNC
+ if(fsync(fileno(out)) != 0)
+ log_err("could not fsync(%s): %s", fname, strerror(errno));
+#else
+ FlushFileBuffers((HANDLE)_fileno(out));
+#endif
if(fclose(out) != 0) {
fatal_exit("could not complete write: %s: %s",
fname, strerror(errno));
@@ -2162,7 +2170,7 @@ int autr_process_prime(struct module_env* env, struct val_env* ve,
if(!verify_dnskey(env, ve, tp, dnskey_rrset)) {
verbose(VERB_ALGO, "autotrust: dnskey did not verify.");
/* only increase failure count if this is not the first prime,
- * this means there was a previous succesful probe */
+ * this means there was a previous successful probe */
if(tp->autr->last_success) {
tp->autr->query_failed += 1;
autr_write_file(env, tp);
diff --git a/external/unbound/validator/val_neg.c b/external/unbound/validator/val_neg.c
index b1ff8d9a1..ab31f483e 100644
--- a/external/unbound/validator/val_neg.c
+++ b/external/unbound/validator/val_neg.c
@@ -38,7 +38,7 @@
*
* This file contains helper functions for the validator module.
* The functions help with aggressive negative caching.
- * This creates new denials of existance, and proofs for absence of types
+ * This creates new denials of existence, and proofs for absence of types
* from cached NSEC records.
*/
#include "config.h"
diff --git a/external/unbound/validator/val_neg.h b/external/unbound/validator/val_neg.h
index 967d1a70f..bf3a2471c 100644
--- a/external/unbound/validator/val_neg.h
+++ b/external/unbound/validator/val_neg.h
@@ -38,7 +38,7 @@
*
* This file contains helper functions for the validator module.
* The functions help with aggressive negative caching.
- * This creates new denials of existance, and proofs for absence of types
+ * This creates new denials of existence, and proofs for absence of types
* from cached NSEC records.
*/
diff --git a/external/unbound/validator/val_nsec.c b/external/unbound/validator/val_nsec.c
index bdfe3c8fa..f104a347c 100644
--- a/external/unbound/validator/val_nsec.c
+++ b/external/unbound/validator/val_nsec.c
@@ -1,5 +1,5 @@
/*
- * validator/val_nsec.c - validator NSEC denial of existance functions.
+ * validator/val_nsec.c - validator NSEC denial of existence functions.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
@@ -38,7 +38,7 @@
*
* This file contains helper functions for the validator module.
* The functions help with NSEC checking, the different NSEC proofs
- * for denial of existance, and proofs for presence of types.
+ * for denial of existence, and proofs for presence of types.
*/
#include "config.h"
#include "validator/val_nsec.h"
@@ -279,7 +279,7 @@ val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
return sec_status_insecure;
}
- /* NSEC proof did not conlusively point to DS or no DS */
+ /* NSEC proof did not conclusively point to DS or no DS */
return sec_status_unchecked;
}
@@ -340,6 +340,28 @@ int nsec_proves_nodata(struct ub_packed_rrset_key* nsec,
*wc = ce;
return 1;
}
+ } else {
+ /* See if the next owner name covers a wildcard
+ * empty non-terminal. */
+ while (dname_strict_subdomain_c(nm, nsec->rk.dname)) {
+ /* wildcard does not apply if qname below
+ * the name that exists under the '*' */
+ if (dname_subdomain_c(qinfo->qname, nm))
+ break;
+ /* but if it is a wildcard and qname is below
+ * it, then the wildcard applies. The wildcard
+ * is an empty nonterminal. nodata proven. */
+ if (dname_is_wild(nm)) {
+ size_t ce_len = ln;
+ uint8_t* ce = nm;
+ dname_remove_label(&ce, &ce_len);
+ if(dname_strict_subdomain_c(qinfo->qname, ce)) {
+ *wc = ce;
+ return 1;
+ }
+ }
+ dname_remove_label(&nm, &ln);
+ }
}
/* Otherwise, this NSEC does not prove ENT and is not a
diff --git a/external/unbound/validator/val_nsec.h b/external/unbound/validator/val_nsec.h
index f680d08c0..c031c9a3b 100644
--- a/external/unbound/validator/val_nsec.h
+++ b/external/unbound/validator/val_nsec.h
@@ -1,5 +1,5 @@
/*
- * validator/val_nsec.h - validator NSEC denial of existance functions.
+ * validator/val_nsec.h - validator NSEC denial of existence functions.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
@@ -38,7 +38,7 @@
*
* This file contains helper functions for the validator module.
* The functions help with NSEC checking, the different NSEC proofs
- * for denial of existance, and proofs for presence of types.
+ * for denial of existence, and proofs for presence of types.
*/
#ifndef VALIDATOR_VAL_NSEC_H
@@ -54,7 +54,7 @@ struct key_entry_key;
/**
* Check DS absence.
* There is a NODATA reply to a DS that needs checking.
- * NSECs can prove this is not a delegation point, or sucessfully prove
+ * NSECs can prove this is not a delegation point, or successfully prove
* that there is no DS. Or this fails.
*
* @param env: module env for rrsig verification routines.
diff --git a/external/unbound/validator/val_nsec3.c b/external/unbound/validator/val_nsec3.c
index 80ca4d0ba..22867d170 100644
--- a/external/unbound/validator/val_nsec3.c
+++ b/external/unbound/validator/val_nsec3.c
@@ -1,5 +1,5 @@
/*
- * validator/val_nsec3.c - validator NSEC3 denial of existance functions.
+ * validator/val_nsec3.c - validator NSEC3 denial of existence functions.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
@@ -38,18 +38,12 @@
*
* This file contains helper functions for the validator module.
* The functions help with NSEC3 checking, the different NSEC3 proofs
- * for denial of existance, and proofs for presence of types.
+ * for denial of existence, and proofs for presence of types.
*/
#include "config.h"
#include <ctype.h>
-#ifdef HAVE_OPENSSL_SSL_H
-#include "openssl/ssl.h"
-#endif
-#ifdef HAVE_NSS
-/* nss3 */
-#include "sechash.h"
-#endif
#include "validator/val_nsec3.h"
+#include "validator/val_secalgo.h"
#include "validator/validator.h"
#include "validator/val_kentry.h"
#include "services/cache/rrset.h"
@@ -370,8 +364,8 @@ filter_next(struct nsec3_filter* filter, size_t* rrsetnum, int* rrnum)
/**
* Start iterating over NSEC3 records.
* @param filter: the filter structure, must have been filter_init-ed.
- * @param rrsetnum: can be undefined on call, inited.
- * @param rrnum: can be undefined on call, inited.
+ * @param rrsetnum: can be undefined on call, initialised.
+ * @param rrnum: can be undefined on call, initialised.
* @return first rrset of an NSEC3, together with rrnum this points to
* the first RR to examine. Is NULL on empty list.
*/
@@ -545,46 +539,24 @@ nsec3_get_hashed(sldns_buffer* buf, uint8_t* nm, size_t nmlen, int algo,
query_dname_tolower(sldns_buffer_begin(buf));
sldns_buffer_write(buf, salt, saltlen);
sldns_buffer_flip(buf);
- switch(algo) {
-#if defined(HAVE_EVP_SHA1) || defined(HAVE_NSS)
- case NSEC3_HASH_SHA1:
-#ifdef HAVE_SSL
- hash_len = SHA_DIGEST_LENGTH;
-#else
- hash_len = SHA1_LENGTH;
-#endif
- if(hash_len > max)
- return 0;
-# ifdef HAVE_SSL
- (void)SHA1((unsigned char*)sldns_buffer_begin(buf),
- (unsigned long)sldns_buffer_limit(buf),
- (unsigned char*)res);
-# else
- (void)HASH_HashBuf(HASH_AlgSHA1, (unsigned char*)res,
- (unsigned char*)sldns_buffer_begin(buf),
- (unsigned long)sldns_buffer_limit(buf));
-# endif
- for(i=0; i<iter; i++) {
- sldns_buffer_clear(buf);
- sldns_buffer_write(buf, res, hash_len);
- sldns_buffer_write(buf, salt, saltlen);
- sldns_buffer_flip(buf);
-# ifdef HAVE_SSL
- (void)SHA1(
- (unsigned char*)sldns_buffer_begin(buf),
- (unsigned long)sldns_buffer_limit(buf),
- (unsigned char*)res);
-# else
- (void)HASH_HashBuf(HASH_AlgSHA1,
- (unsigned char*)res,
- (unsigned char*)sldns_buffer_begin(buf),
- (unsigned long)sldns_buffer_limit(buf));
-# endif
- }
- break;
-#endif /* HAVE_EVP_SHA1 or NSS */
- default:
- log_err("nsec3 hash of unknown algo %d", algo);
+ hash_len = nsec3_hash_algo_size_supported(algo);
+ if(hash_len == 0) {
+ log_err("nsec3 hash of unknown algo %d", algo);
+ return 0;
+ }
+ if(hash_len > max)
+ return 0;
+ if(!secalgo_nsec3_hash(algo, (unsigned char*)sldns_buffer_begin(buf),
+ sldns_buffer_limit(buf), (unsigned char*)res))
+ return 0;
+ for(i=0; i<iter; i++) {
+ sldns_buffer_clear(buf);
+ sldns_buffer_write(buf, res, hash_len);
+ sldns_buffer_write(buf, salt, saltlen);
+ sldns_buffer_flip(buf);
+ if(!secalgo_nsec3_hash(algo,
+ (unsigned char*)sldns_buffer_begin(buf),
+ sldns_buffer_limit(buf), (unsigned char*)res))
return 0;
}
return hash_len;
@@ -607,50 +579,24 @@ nsec3_calc_hash(struct regional* region, sldns_buffer* buf,
query_dname_tolower(sldns_buffer_begin(buf));
sldns_buffer_write(buf, salt, saltlen);
sldns_buffer_flip(buf);
- switch(algo) {
-#if defined(HAVE_EVP_SHA1) || defined(HAVE_NSS)
- case NSEC3_HASH_SHA1:
-#ifdef HAVE_SSL
- c->hash_len = SHA_DIGEST_LENGTH;
-#else
- c->hash_len = SHA1_LENGTH;
-#endif
- c->hash = (uint8_t*)regional_alloc(region,
- c->hash_len);
- if(!c->hash)
- return 0;
-# ifdef HAVE_SSL
- (void)SHA1((unsigned char*)sldns_buffer_begin(buf),
- (unsigned long)sldns_buffer_limit(buf),
- (unsigned char*)c->hash);
-# else
- (void)HASH_HashBuf(HASH_AlgSHA1,
- (unsigned char*)c->hash,
- (unsigned char*)sldns_buffer_begin(buf),
- (unsigned long)sldns_buffer_limit(buf));
-# endif
- for(i=0; i<iter; i++) {
- sldns_buffer_clear(buf);
- sldns_buffer_write(buf, c->hash, c->hash_len);
- sldns_buffer_write(buf, salt, saltlen);
- sldns_buffer_flip(buf);
-# ifdef HAVE_SSL
- (void)SHA1(
- (unsigned char*)sldns_buffer_begin(buf),
- (unsigned long)sldns_buffer_limit(buf),
- (unsigned char*)c->hash);
-# else
- (void)HASH_HashBuf(HASH_AlgSHA1,
- (unsigned char*)c->hash,
- (unsigned char*)sldns_buffer_begin(buf),
- (unsigned long)sldns_buffer_limit(buf));
-# endif
- }
- break;
-#endif /* HAVE_EVP_SHA1 or NSS */
- default:
- log_err("nsec3 hash of unknown algo %d", algo);
- return -1;
+ c->hash_len = nsec3_hash_algo_size_supported(algo);
+ if(c->hash_len == 0) {
+ log_err("nsec3 hash of unknown algo %d", algo);
+ return -1;
+ }
+ c->hash = (uint8_t*)regional_alloc(region, c->hash_len);
+ if(!c->hash)
+ return 0;
+ (void)secalgo_nsec3_hash(algo, (unsigned char*)sldns_buffer_begin(buf),
+ sldns_buffer_limit(buf), (unsigned char*)c->hash);
+ for(i=0; i<iter; i++) {
+ sldns_buffer_clear(buf);
+ sldns_buffer_write(buf, c->hash, c->hash_len);
+ sldns_buffer_write(buf, salt, saltlen);
+ sldns_buffer_flip(buf);
+ (void)secalgo_nsec3_hash(algo,
+ (unsigned char*)sldns_buffer_begin(buf),
+ sldns_buffer_limit(buf), (unsigned char*)c->hash);
}
return 1;
}
diff --git a/external/unbound/validator/val_nsec3.h b/external/unbound/validator/val_nsec3.h
index d619d672d..69ba78d83 100644
--- a/external/unbound/validator/val_nsec3.h
+++ b/external/unbound/validator/val_nsec3.h
@@ -1,5 +1,5 @@
/*
- * validator/val_nsec3.h - validator NSEC3 denial of existance functions.
+ * validator/val_nsec3.h - validator NSEC3 denial of existence functions.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
@@ -38,7 +38,7 @@
*
* This file contains helper functions for the validator module.
* The functions help with NSEC3 checking, the different NSEC3 proofs
- * for denial of existance, and proofs for presence of types.
+ * for denial of existence, and proofs for presence of types.
*
* NSEC3
* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
@@ -256,7 +256,7 @@ int nsec3_hash_cmp(const void* c1, const void* c2);
* 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 table: the cache table. Must be initialised 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.
diff --git a/external/unbound/validator/val_secalgo.c b/external/unbound/validator/val_secalgo.c
index 8ed403dfc..7c8d7b287 100644
--- a/external/unbound/validator/val_secalgo.c
+++ b/external/unbound/validator/val_secalgo.c
@@ -44,12 +44,13 @@
/* packed_rrset on top to define enum types (forced by c99 standard) */
#include "util/data/packed_rrset.h"
#include "validator/val_secalgo.h"
+#include "validator/val_nsec3.h"
#include "util/log.h"
#include "sldns/rrdef.h"
#include "sldns/keyraw.h"
#include "sldns/sbuffer.h"
-#if !defined(HAVE_SSL) && !defined(HAVE_NSS)
+#if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE)
#error "Need crypto library to do digital signature cryptography"
#endif
@@ -71,10 +72,36 @@
#include <openssl/engine.h>
#endif
+/* return size of digest if supported, or 0 otherwise */
+size_t
+nsec3_hash_algo_size_supported(int id)
+{
+ switch(id) {
+ case NSEC3_HASH_SHA1:
+ return SHA_DIGEST_LENGTH;
+ default:
+ return 0;
+ }
+}
+
+/* perform nsec3 hash. return false on failure */
+int
+secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
+ unsigned char* res)
+{
+ switch(algo) {
+ case NSEC3_HASH_SHA1:
+ (void)SHA1(buf, len, res);
+ return 1;
+ default:
+ return 0;
+ }
+}
+
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
- * @return size in bytes of digest, or 0 if not supported.
+ * @return size in bytes of digest, or 0 if not supported.
*/
size_t
ds_digest_size_supported(int algo)
@@ -565,6 +592,32 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
/* nspr4 */
#include "prerror.h"
+/* return size of digest if supported, or 0 otherwise */
+size_t
+nsec3_hash_algo_size_supported(int id)
+{
+ switch(id) {
+ case NSEC3_HASH_SHA1:
+ return SHA1_LENGTH;
+ default:
+ return 0;
+ }
+}
+
+/* perform nsec3 hash. return false on failure */
+int
+secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
+ unsigned char* res)
+{
+ switch(algo) {
+ case NSEC3_HASH_SHA1:
+ (void)HASH_HashBuf(HASH_AlgSHA1, res, buf, (unsigned long)len);
+ return 1;
+ default:
+ return 0;
+ }
+}
+
size_t
ds_digest_size_supported(int algo)
{
@@ -1069,5 +1122,466 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_bogus;
}
+#elif defined(HAVE_NETTLE)
+
+#include "sha.h"
+#include "bignum.h"
+#include "macros.h"
+#include "rsa.h"
+#include "dsa.h"
+#include "asn1.h"
+#ifdef USE_ECDSA
+#include "ecdsa.h"
+#include "ecc-curve.h"
+#endif
+
+static int
+_digest_nettle(int algo, uint8_t* buf, size_t len,
+ unsigned char* res)
+{
+ switch(algo) {
+ case SHA1_DIGEST_SIZE:
+ {
+ struct sha1_ctx ctx;
+ sha1_init(&ctx);
+ sha1_update(&ctx, len, buf);
+ sha1_digest(&ctx, SHA1_DIGEST_SIZE, res);
+ return 1;
+ }
+ case SHA256_DIGEST_SIZE:
+ {
+ struct sha256_ctx ctx;
+ sha256_init(&ctx);
+ sha256_update(&ctx, len, buf);
+ sha256_digest(&ctx, SHA256_DIGEST_SIZE, res);
+ return 1;
+ }
+ case SHA384_DIGEST_SIZE:
+ {
+ struct sha384_ctx ctx;
+ sha384_init(&ctx);
+ sha384_update(&ctx, len, buf);
+ sha384_digest(&ctx, SHA384_DIGEST_SIZE, res);
+ return 1;
+ }
+ case SHA512_DIGEST_SIZE:
+ {
+ struct sha512_ctx ctx;
+ sha512_init(&ctx);
+ sha512_update(&ctx, len, buf);
+ sha512_digest(&ctx, SHA512_DIGEST_SIZE, res);
+ return 1;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+/* return size of digest if supported, or 0 otherwise */
+size_t
+nsec3_hash_algo_size_supported(int id)
+{
+ switch(id) {
+ case NSEC3_HASH_SHA1:
+ return SHA1_DIGEST_SIZE;
+ default:
+ return 0;
+ }
+}
+
+/* perform nsec3 hash. return false on failure */
+int
+secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
+ unsigned char* res)
+{
+ switch(algo) {
+ case NSEC3_HASH_SHA1:
+ return _digest_nettle(SHA1_DIGEST_SIZE, (uint8_t*)buf, len,
+ res);
+ default:
+ return 0;
+ }
+}
+
+/**
+ * Return size of DS digest according to its hash algorithm.
+ * @param algo: DS digest algo.
+ * @return size in bytes of digest, or 0 if not supported.
+ */
+size_t
+ds_digest_size_supported(int algo)
+{
+ switch(algo) {
+ case LDNS_SHA1:
+ return SHA1_DIGEST_SIZE;
+#ifdef USE_SHA2
+ case LDNS_SHA256:
+ return SHA256_DIGEST_SIZE;
+#endif
+#ifdef USE_ECDSA
+ case LDNS_SHA384:
+ return SHA384_DIGEST_SIZE;
+#endif
+ /* GOST not supported */
+ case LDNS_HASH_GOST:
+ default:
+ break;
+ }
+ return 0;
+}
+
+int
+secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
+ unsigned char* res)
+{
+ switch(algo) {
+ case LDNS_SHA1:
+ return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res);
+#if defined(USE_SHA2)
+ case LDNS_SHA256:
+ return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res);
+#endif
+#ifdef USE_ECDSA
+ case LDNS_SHA384:
+ return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res);
+
+#endif
+ case LDNS_HASH_GOST:
+ default:
+ verbose(VERB_QUERY, "unknown DS digest algorithm %d",
+ algo);
+ break;
+ }
+ return 0;
+}
+
+int
+dnskey_algo_id_is_supported(int id)
+{
+ /* uses libnettle */
+ switch(id) {
+ case LDNS_DSA:
+ case LDNS_DSA_NSEC3:
+ case LDNS_RSASHA1:
+ case LDNS_RSASHA1_NSEC3:
+#ifdef USE_SHA2
+ case LDNS_RSASHA256:
+ case LDNS_RSASHA512:
+#endif
+#ifdef USE_ECDSA
+ case LDNS_ECDSAP256SHA256:
+ case LDNS_ECDSAP384SHA384:
+#endif
+ return 1;
+ case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */
+ case LDNS_ECC_GOST:
+ default:
+ return 0;
+ }
+}
+
+static char *
+_verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
+ unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
+{
+ uint8_t digest[SHA1_DIGEST_SIZE];
+ uint8_t key_t;
+ int res = 0;
+ size_t offset;
+ struct dsa_public_key pubkey;
+ struct dsa_signature signature;
+ unsigned int expected_len;
+
+ /* Extract DSA signature from the record */
+ nettle_dsa_signature_init(&signature);
+ /* Signature length: 41 bytes - RFC 2536 sec. 3 */
+ if(sigblock_len == 41) {
+ if(key[0] != sigblock[0])
+ return "invalid T value in DSA signature or pubkey";
+ nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1);
+ nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20);
+ } else {
+ /* DER encoded, decode the ASN1 notated R and S bignums */
+ /* SEQUENCE { r INTEGER, s INTEGER } */
+ struct asn1_der_iterator i, seq;
+ if(asn1_der_iterator_first(&i, sigblock_len,
+ (uint8_t*)sigblock) != ASN1_ITERATOR_CONSTRUCTED
+ || i.type != ASN1_SEQUENCE)
+ return "malformed DER encoded DSA signature";
+ /* decode this element of i using the seq iterator */
+ if(asn1_der_decode_constructed(&i, &seq) !=
+ ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER)
+ return "malformed DER encoded DSA signature";
+ if(!asn1_der_get_bignum(&seq, signature.r, 20*8))
+ return "malformed DER encoded DSA signature";
+ if(asn1_der_iterator_next(&seq) != ASN1_ITERATOR_PRIMITIVE
+ || seq.type != ASN1_INTEGER)
+ return "malformed DER encoded DSA signature";
+ if(!asn1_der_get_bignum(&seq, signature.s, 20*8))
+ return "malformed DER encoded DSA signature";
+ if(asn1_der_iterator_next(&i) != ASN1_ITERATOR_END)
+ return "malformed DER encoded DSA signature";
+ }
+
+ /* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */
+ key_t = key[0];
+ if (key_t > 8) {
+ return "invalid T value in DSA pubkey";
+ }
+
+ /* Pubkey minimum length: 21 bytes - RFC 2536 sec. 2 */
+ if (keylen < 21) {
+ return "DSA pubkey too short";
+ }
+
+ expected_len = 1 + /* T */
+ 20 + /* Q */
+ (64 + key_t*8) + /* P */
+ (64 + key_t*8) + /* G */
+ (64 + key_t*8); /* Y */
+ if (keylen != expected_len ) {
+ return "invalid DSA pubkey length";
+ }
+
+ /* Extract DSA pubkey from the record */
+ nettle_dsa_public_key_init(&pubkey);
+ offset = 1;
+ nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset);
+ offset += 20;
+ nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t*8), key+offset);
+ offset += (64 + key_t*8);
+ nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t*8), key+offset);
+ offset += (64 + key_t*8);
+ nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t*8), key+offset);
+
+ /* Digest content of "buf" and verify its DSA signature in "sigblock"*/
+ res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+ (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
+ res &= dsa_sha1_verify_digest(&pubkey, digest, &signature);
+
+ /* Clear and return */
+ nettle_dsa_signature_clear(&signature);
+ nettle_dsa_public_key_clear(&pubkey);
+ if (!res)
+ return "DSA signature verification failed";
+ else
+ return NULL;
+}
+
+static char *
+_verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock,
+ unsigned int sigblock_len, uint8_t* key, unsigned int keylen)
+{
+ uint16_t exp_len = 0;
+ size_t exp_offset = 0, mod_offset = 0;
+ struct rsa_public_key pubkey;
+ mpz_t signature;
+ int res = 0;
+
+ /* RSA pubkey parsing as per RFC 3110 sec. 2 */
+ if( keylen <= 1) {
+ return "null RSA key";
+ }
+ if (key[0] != 0) {
+ /* 1-byte length */
+ exp_len = key[0];
+ exp_offset = 1;
+ } else {
+ /* 1-byte NUL + 2-bytes exponent length */
+ if (keylen < 3) {
+ return "incorrect RSA key length";
+ }
+ exp_len = READ_UINT16(key+1);
+ if (exp_len == 0)
+ return "null RSA exponent length";
+ exp_offset = 3;
+ }
+ /* Check that we are not over-running input length */
+ if (keylen < exp_offset + exp_len + 1) {
+ return "RSA key content shorter than expected";
+ }
+ mod_offset = exp_offset + exp_len;
+ nettle_rsa_public_key_init(&pubkey);
+ pubkey.size = keylen - mod_offset;
+ nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]);
+ nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]);
+
+ /* Digest content of "buf" and verify its RSA signature in "sigblock"*/
+ nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock);
+ switch (digest_size) {
+ case SHA1_DIGEST_SIZE:
+ {
+ uint8_t digest[SHA1_DIGEST_SIZE];
+ res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+ (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
+ res &= rsa_sha1_verify_digest(&pubkey, digest, signature);
+ break;
+ }
+ case SHA256_DIGEST_SIZE:
+ {
+ uint8_t digest[SHA256_DIGEST_SIZE];
+ res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+ (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
+ res &= rsa_sha256_verify_digest(&pubkey, digest, signature);
+ break;
+ }
+ case SHA512_DIGEST_SIZE:
+ {
+ uint8_t digest[SHA512_DIGEST_SIZE];
+ res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+ (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
+ res &= rsa_sha512_verify_digest(&pubkey, digest, signature);
+ break;
+ }
+ default:
+ break;
+ }
+
+ /* Clear and return */
+ nettle_rsa_public_key_clear(&pubkey);
+ mpz_clear(signature);
+ if (!res) {
+ return "RSA signature verification failed";
+ } else {
+ return NULL;
+ }
+}
+
+#ifdef USE_ECDSA
+static char *
+_verify_nettle_ecdsa(sldns_buffer* buf, unsigned int digest_size, unsigned char* sigblock,
+ unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
+{
+ int res = 0;
+ struct ecc_point pubkey;
+ struct dsa_signature signature;
+
+ /* Always matched strength, as per RFC 6605 sec. 1 */
+ if (sigblock_len != 2*digest_size || keylen != 2*digest_size) {
+ return "wrong ECDSA signature length";
+ }
+
+ /* Parse ECDSA signature as per RFC 6605 sec. 4 */
+ nettle_dsa_signature_init(&signature);
+ switch (digest_size) {
+ case SHA256_DIGEST_SIZE:
+ {
+ uint8_t digest[SHA256_DIGEST_SIZE];
+ mpz_t x, y;
+ nettle_ecc_point_init(&pubkey, &nettle_secp_256r1);
+ nettle_mpz_init_set_str_256_u(x, SHA256_DIGEST_SIZE, key);
+ nettle_mpz_init_set_str_256_u(y, SHA256_DIGEST_SIZE, key+SHA256_DIGEST_SIZE);
+ nettle_mpz_set_str_256_u(signature.r, SHA256_DIGEST_SIZE, sigblock);
+ nettle_mpz_set_str_256_u(signature.s, SHA256_DIGEST_SIZE, sigblock+SHA256_DIGEST_SIZE);
+ res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+ (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
+ res &= nettle_ecc_point_set(&pubkey, x, y);
+ res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature);
+ mpz_clear(x);
+ mpz_clear(y);
+ break;
+ }
+ case SHA384_DIGEST_SIZE:
+ {
+ uint8_t digest[SHA384_DIGEST_SIZE];
+ mpz_t x, y;
+ nettle_ecc_point_init(&pubkey, &nettle_secp_384r1);
+ nettle_mpz_init_set_str_256_u(x, SHA384_DIGEST_SIZE, key);
+ nettle_mpz_init_set_str_256_u(y, SHA384_DIGEST_SIZE, key+SHA384_DIGEST_SIZE);
+ nettle_mpz_set_str_256_u(signature.r, SHA384_DIGEST_SIZE, sigblock);
+ nettle_mpz_set_str_256_u(signature.s, SHA384_DIGEST_SIZE, sigblock+SHA384_DIGEST_SIZE);
+ res = _digest_nettle(SHA384_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+ (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
+ res &= nettle_ecc_point_set(&pubkey, x, y);
+ res &= nettle_ecdsa_verify (&pubkey, SHA384_DIGEST_SIZE, digest, &signature);
+ mpz_clear(x);
+ mpz_clear(y);
+ nettle_ecc_point_clear(&pubkey);
+ break;
+ }
+ default:
+ return "unknown ECDSA algorithm";
+ }
+
+ /* Clear and return */
+ nettle_dsa_signature_clear(&signature);
+ if (!res)
+ return "ECDSA signature verification failed";
+ else
+ return NULL;
+}
+#endif
+
+/**
+ * Check a canonical sig+rrset and signature against a dnskey
+ * @param buf: buffer with data to verify, the first rrsig part and the
+ * canonicalized rrset.
+ * @param algo: DNSKEY algorithm.
+ * @param sigblock: signature rdata field from RRSIG
+ * @param sigblock_len: length of sigblock data.
+ * @param key: public key data from DNSKEY RR.
+ * @param keylen: length of keydata.
+ * @param reason: bogus reason in more detail.
+ * @return secure if verification succeeded, bogus on crypto failure,
+ * unchecked on format errors and alloc failures.
+ */
+enum sec_status
+verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
+ unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
+ char** reason)
+{
+ unsigned int digest_size = 0;
+
+ if (sigblock_len == 0 || keylen == 0) {
+ *reason = "null signature";
+ return sec_status_bogus;
+ }
+
+ switch(algo) {
+ case LDNS_DSA:
+ case LDNS_DSA_NSEC3:
+ *reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
+ if (*reason != NULL)
+ return sec_status_bogus;
+ else
+ return sec_status_secure;
+
+ case LDNS_RSASHA1:
+ case LDNS_RSASHA1_NSEC3:
+ digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE);
+#ifdef USE_SHA2
+ case LDNS_RSASHA256:
+ digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
+ case LDNS_RSASHA512:
+ digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE);
+
+#endif
+ *reason = _verify_nettle_rsa(buf, digest_size, (char*)sigblock,
+ sigblock_len, key, keylen);
+ if (*reason != NULL)
+ return sec_status_bogus;
+ else
+ return sec_status_secure;
+
+#ifdef USE_ECDSA
+ case LDNS_ECDSAP256SHA256:
+ digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
+ case LDNS_ECDSAP384SHA384:
+ digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE);
+ *reason = _verify_nettle_ecdsa(buf, digest_size, sigblock,
+ sigblock_len, key, keylen);
+ if (*reason != NULL)
+ return sec_status_bogus;
+ else
+ return sec_status_secure;
+#endif
+ case LDNS_RSAMD5:
+ case LDNS_ECC_GOST:
+ default:
+ *reason = "unable to verify signature, unknown algorithm";
+ return sec_status_bogus;
+ }
+}
-#endif /* HAVE_SSL or HAVE_NSS */
+#endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */
diff --git a/external/unbound/validator/val_secalgo.h b/external/unbound/validator/val_secalgo.h
index 085fbc5a4..589f1f11d 100644
--- a/external/unbound/validator/val_secalgo.h
+++ b/external/unbound/validator/val_secalgo.h
@@ -44,6 +44,21 @@
#define VALIDATOR_VAL_SECALGO_H
struct sldns_buffer;
+/** Return size of nsec3 hash algorithm, 0 if not supported */
+size_t nsec3_hash_algo_size_supported(int id);
+
+/**
+ * Hash a single hash call of an NSEC3 hash algorithm.
+ * Iterations and salt are done by the caller.
+ * @param algo: nsec3 hash algorithm.
+ * @param buf: the buffer to digest
+ * @param len: length of buffer to digest.
+ * @param res: result stored here (must have sufficient space).
+ * @return false on failure.
+*/
+int secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
+ unsigned char* res);
+
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
diff --git a/external/unbound/validator/val_sigcrypt.c b/external/unbound/validator/val_sigcrypt.c
index 7c643cab1..1dd07b420 100644
--- a/external/unbound/validator/val_sigcrypt.c
+++ b/external/unbound/validator/val_sigcrypt.c
@@ -57,7 +57,7 @@
#include "sldns/wire2str.h"
#include <ctype.h>
-#if !defined(HAVE_SSL) && !defined(HAVE_NSS)
+#if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE)
#error "Need crypto library to do digital signature cryptography"
#endif
@@ -795,10 +795,6 @@ canonical_compare(struct ub_packed_rrset_key* rrset, size_t i, size_t j)
if(i==j)
return 0;
- /* in case rdata-len is to be compared for canonical order
- c = memcmp(d->rr_data[i], d->rr_data[j], 2);
- if(c != 0)
- return c; */
switch(type) {
/* These RR types have only a name as RDATA.
diff --git a/external/unbound/validator/val_utils.h b/external/unbound/validator/val_utils.h
index cdb87697e..051824aba 100644
--- a/external/unbound/validator/val_utils.h
+++ b/external/unbound/validator/val_utils.h
@@ -391,7 +391,7 @@ int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset);
* Find DS denial message in cache. Saves new qstate allocation and allows
* the validator to use partial content which is not enough to construct a
* message for network (or user) consumption. Without SOA for example,
- * which is a common occurence in the unbound code since the referrals contain
+ * which is a common occurrence in the unbound code since the referrals contain
* NSEC/NSEC3 rrs without the SOA element, thus do not allow synthesis of a
* full negative reply, but do allow synthesis of sufficient proof.
* @param env: query env with caches and time.
diff --git a/external/unbound/validator/validator.c b/external/unbound/validator/validator.c
index f8b429e52..db4383bed 100644
--- a/external/unbound/validator/validator.c
+++ b/external/unbound/validator/validator.c
@@ -749,7 +749,7 @@ validate_nodata_response(struct module_env* env, struct val_env* ve,
/* Since we are here, there must be nothing in the ANSWER section to
* validate. */
/* (Note: CNAME/DNAME responses will not directly get here --
- * instead, they are chased down into indiviual CNAME validations,
+ * instead, they are chased down into individual CNAME validations,
* and at the end of the cname chain a POSITIVE, or CNAME_NOANSWER
* validation.) */
@@ -1597,7 +1597,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
target_key_name) != 0) {
/* check if there is a cache entry : pick up an NSEC if
* there is no DS, check if that NSEC has DS-bit unset, and
- * thus can disprove the secure delagation we seek.
+ * thus can disprove the secure delegation we seek.
* We can then use that NSEC even in the absence of a SOA
* record that would be required by the iterator to supply
* a completely protocol-correct response.
@@ -1829,7 +1829,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
* @return true if there is no DLV.
* false: processing is finished for the validator operate().
* This function may exit in three ways:
- * o no DLV (agressive cache), so insecure. (true)
+ * o no DLV (aggressive cache), so insecure. (true)
* o error - stop processing (false)
* o DLV lookup was started, stop processing (false)
*/