update unbound, fix unbound openssl issue on OS X

This commit is contained in:
Riccardo Spagni 2015-12-30 12:57:50 +02:00
parent 32a26332f8
commit 2d43ae8063
No known key found for this signature in database
GPG key ID: 55432DF31CCD4FCD
101 changed files with 4685 additions and 3057 deletions

View file

@ -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);

View file

@ -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"

View file

@ -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.
*/

View file

@ -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

View file

@ -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.

View file

@ -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;
}

View file

@ -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.

View file

@ -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)
#endif /* HAVE_SSL or HAVE_NSS */
#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 or HAVE_NETTLE */

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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)
*/