mirror of
https://github.com/NLnetLabs/unbound.git
synced 2024-09-21 06:37:08 +00:00
implement DNSSEC with libNSS: NSEC3, RSA, DSA, ECDSA, and DS hashes.
make test succeeds. git-svn-id: file:///svn/unbound/trunk@2699 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
42e23da129
commit
25096aa3ab
@ -1,3 +1,6 @@
|
||||
22 June 2012: Wouter
|
||||
- implement DS records, NSEC3 and ECDSA for compile with libnss.
|
||||
|
||||
21 June 2012: Wouter
|
||||
- fix error handling of alloc failure during rrsig verification.
|
||||
- nss check for verification failure.
|
||||
|
@ -281,7 +281,7 @@ main(int argc, char* argv[])
|
||||
printf("selftest successful\n");
|
||||
exit(0);
|
||||
case '2':
|
||||
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
|
||||
#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS)) && defined(USE_SHA2)
|
||||
printf("SHA256 supported\n");
|
||||
exit(0);
|
||||
#else
|
||||
|
@ -505,12 +505,12 @@ verify_test(void)
|
||||
verifytest_file("testdata/test_signatures.6", "20080416005004");
|
||||
verifytest_file("testdata/test_signatures.7", "20070829144150");
|
||||
verifytest_file("testdata/test_signatures.8", "20070829144150");
|
||||
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
|
||||
#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS)) && defined(USE_SHA2)
|
||||
verifytest_file("testdata/test_sigs.rsasha256", "20070829144150");
|
||||
verifytest_file("testdata/test_sigs.sha1_and_256", "20070829144150");
|
||||
verifytest_file("testdata/test_sigs.rsasha256_draft", "20090101000000");
|
||||
#endif
|
||||
#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
|
||||
#if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS)) && defined(USE_SHA2)
|
||||
verifytest_file("testdata/test_sigs.rsasha512_draft", "20070829144150");
|
||||
#endif
|
||||
verifytest_file("testdata/test_sigs.hinfo", "20090107100022");
|
||||
|
@ -45,6 +45,9 @@
|
||||
#ifdef HAVE_OPENSSL_SSL_H
|
||||
#include "openssl/ssl.h"
|
||||
#endif
|
||||
#ifdef HAVE_NSS
|
||||
#include <nss3/sechash.h>
|
||||
#endif
|
||||
#include "validator/val_nsec3.h"
|
||||
#include "validator/validator.h"
|
||||
#include "validator/val_kentry.h"
|
||||
@ -541,26 +544,43 @@ nsec3_get_hashed(ldns_buffer* buf, uint8_t* nm, size_t nmlen, int algo,
|
||||
ldns_buffer_write(buf, salt, saltlen);
|
||||
ldns_buffer_flip(buf);
|
||||
switch(algo) {
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
#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*)ldns_buffer_begin(buf),
|
||||
(unsigned long)ldns_buffer_limit(buf),
|
||||
(unsigned char*)res);
|
||||
# else
|
||||
(void)HASH_HashBuf(HASH_AlgSHA1, (unsigned char*)res,
|
||||
(unsigned char*)ldns_buffer_begin(buf),
|
||||
(unsigned long)ldns_buffer_limit(buf));
|
||||
# endif
|
||||
for(i=0; i<iter; i++) {
|
||||
ldns_buffer_clear(buf);
|
||||
ldns_buffer_write(buf, res, hash_len);
|
||||
ldns_buffer_write(buf, salt, saltlen);
|
||||
ldns_buffer_flip(buf);
|
||||
# ifdef HAVE_SSL
|
||||
(void)SHA1(
|
||||
(unsigned char*)ldns_buffer_begin(buf),
|
||||
(unsigned long)ldns_buffer_limit(buf),
|
||||
(unsigned char*)res);
|
||||
# else
|
||||
(void)HASH_HashBuf(HASH_AlgSHA1,
|
||||
(unsigned char*)res,
|
||||
(unsigned char*)ldns_buffer_begin(buf),
|
||||
(unsigned long)ldns_buffer_limit(buf));
|
||||
# endif
|
||||
}
|
||||
break;
|
||||
#endif /* HAVE_EVP_SHA1 */
|
||||
#endif /* HAVE_EVP_SHA1 or NSS */
|
||||
default:
|
||||
log_err("nsec3 hash of unknown algo %d", algo);
|
||||
return 0;
|
||||
@ -586,28 +606,46 @@ nsec3_calc_hash(struct regional* region, ldns_buffer* buf,
|
||||
ldns_buffer_write(buf, salt, saltlen);
|
||||
ldns_buffer_flip(buf);
|
||||
switch(algo) {
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
#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*)ldns_buffer_begin(buf),
|
||||
(unsigned long)ldns_buffer_limit(buf),
|
||||
(unsigned char*)c->hash);
|
||||
# else
|
||||
(void)HASH_HashBuf(HASH_AlgSHA1,
|
||||
(unsigned char*)c->hash,
|
||||
(unsigned char*)ldns_buffer_begin(buf),
|
||||
(unsigned long)ldns_buffer_limit(buf));
|
||||
# endif
|
||||
for(i=0; i<iter; i++) {
|
||||
ldns_buffer_clear(buf);
|
||||
ldns_buffer_write(buf, c->hash, c->hash_len);
|
||||
ldns_buffer_write(buf, salt, saltlen);
|
||||
ldns_buffer_flip(buf);
|
||||
# ifdef HAVE_SSL
|
||||
(void)SHA1(
|
||||
(unsigned char*)ldns_buffer_begin(buf),
|
||||
(unsigned long)ldns_buffer_limit(buf),
|
||||
(unsigned char*)c->hash);
|
||||
# else
|
||||
(void)HASH_HashBuf(HASH_AlgSHA1,
|
||||
(unsigned char*)c->hash,
|
||||
(unsigned char*)ldns_buffer_begin(buf),
|
||||
(unsigned long)ldns_buffer_limit(buf));
|
||||
# endif
|
||||
}
|
||||
break;
|
||||
#endif /* HAVE_EVP_SHA1 */
|
||||
#endif /* HAVE_EVP_SHA1 or NSS */
|
||||
default:
|
||||
log_err("nsec3 hash of unknown algo %d", algo);
|
||||
return -1;
|
||||
|
@ -562,11 +562,9 @@ ds_digest_size_supported(int algo)
|
||||
{
|
||||
/* uses libNSS */
|
||||
switch(algo) {
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
case LDNS_SHA1:
|
||||
return SHA1_LENGTH;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA256
|
||||
#ifdef USE_SHA2
|
||||
case LDNS_SHA256:
|
||||
return SHA256_LENGTH;
|
||||
#endif
|
||||
@ -587,12 +585,10 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
|
||||
{
|
||||
/* uses libNSS */
|
||||
switch(algo) {
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
case LDNS_SHA1:
|
||||
return HASH_HashBuf(HASH_AlgSHA1, res, buf, len)
|
||||
== SECSuccess;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA256
|
||||
#if defined(USE_SHA2)
|
||||
case LDNS_SHA256:
|
||||
return HASH_HashBuf(HASH_AlgSHA256, res, buf, len)
|
||||
== SECSuccess;
|
||||
@ -621,10 +617,10 @@ dnskey_algo_id_is_supported(int id)
|
||||
case LDNS_RSASHA1:
|
||||
case LDNS_RSASHA1_NSEC3:
|
||||
case LDNS_RSAMD5:
|
||||
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
|
||||
#ifdef USE_SHA2
|
||||
case LDNS_RSASHA256:
|
||||
#endif
|
||||
#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
|
||||
#ifdef USE_SHA2
|
||||
case LDNS_RSASHA512:
|
||||
#endif
|
||||
#ifdef USE_ECDSA
|
||||
@ -662,25 +658,56 @@ static SECKEYPublicKey* nss_key_create(KeyType ktype)
|
||||
|
||||
static SECKEYPublicKey* nss_buf2ecdsa(unsigned char* key, size_t len, int algo)
|
||||
{
|
||||
return NULL;
|
||||
#if 0
|
||||
/* TODO */
|
||||
SECKEYPublicKey* pk;
|
||||
SECItem pub = {siBuffer, NULL, 0};
|
||||
SECItem params = {siBuffer, NULL, 0};
|
||||
unsigned char param256[] = {
|
||||
/* OBJECTIDENTIFIER 1.2.840.10045.3.1.7 (P-256)
|
||||
* {iso(1) member-body(2) us(840) ansi-x962(10045) curves(3) prime(1) prime256v1(7)} */
|
||||
0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
|
||||
};
|
||||
unsigned char param384[] = {
|
||||
/* OBJECTIDENTIFIER 1.3.132.0.34 (P-384)
|
||||
* {iso(1) identified-organization(3) certicom(132) curve(0) ansip384r1(34)} */
|
||||
0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22
|
||||
};
|
||||
unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
|
||||
const unsigned char* pp = buf;
|
||||
ECGroup* ecg;
|
||||
|
||||
|
||||
/* check length, which uncompressed must be 2 bignums */
|
||||
if(algo == LDNS_ECDSAP256SHA256) {
|
||||
if(keylen != 2*256/8) return NULL;
|
||||
ecg = ECGroup_fromName(ECCurve_X9_62_PRIME_256V1);
|
||||
if(len != 2*256/8) return NULL;
|
||||
/* ECCurve_X9_62_PRIME_256V1 */
|
||||
} else if(algo == LDNS_ECDSAP384SHA384) {
|
||||
if(keylen != 2*384/8) return NULL;
|
||||
ecg = ECGroup_fromName(ECCurve_X9_62_PRIME_384R1);
|
||||
} else ecg= NULL;
|
||||
if(!ecg) return NULL;
|
||||
#endif
|
||||
if(len != 2*384/8) return NULL;
|
||||
/* ECCurve_X9_62_PRIME_384R1 */
|
||||
} else return NULL;
|
||||
|
||||
buf[0] = 0x04; /* POINT_FORM_UNCOMPRESSED */
|
||||
memmove(buf+1, key, len);
|
||||
pub.data = buf;
|
||||
pub.len = len+1;
|
||||
if(algo == LDNS_ECDSAP256SHA256) {
|
||||
params.data = param256;
|
||||
params.len = sizeof(param256);
|
||||
} else {
|
||||
params.data = param384;
|
||||
params.len = sizeof(param384);
|
||||
}
|
||||
|
||||
pk = nss_key_create(ecKey);
|
||||
if(!pk)
|
||||
return NULL;
|
||||
pk->u.ec.size = (len/2)*8;
|
||||
if(SECITEM_CopyItem(pk->arena, &pk->u.ec.publicValue, &pub)) {
|
||||
SECKEY_DestroyPublicKey(pk);
|
||||
return NULL;
|
||||
}
|
||||
if(SECITEM_CopyItem(pk->arena, &pk->u.ec.DEREncodedParams, ¶ms)) {
|
||||
SECKEY_DestroyPublicKey(pk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pk;
|
||||
}
|
||||
|
||||
static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len)
|
||||
@ -837,10 +864,10 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
|
||||
break;
|
||||
case LDNS_RSASHA1:
|
||||
case LDNS_RSASHA1_NSEC3:
|
||||
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
|
||||
#ifdef USE_SHA2
|
||||
case LDNS_RSASHA256:
|
||||
#endif
|
||||
#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
|
||||
#ifdef USE_SHA2
|
||||
case LDNS_RSASHA512:
|
||||
#endif
|
||||
*pubkey = nss_buf2rsa(key, keylen);
|
||||
@ -849,14 +876,14 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
|
||||
return 0;
|
||||
}
|
||||
/* select SHA version */
|
||||
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
|
||||
#ifdef USE_SHA2
|
||||
if(algo == LDNS_RSASHA256) {
|
||||
*htype = HASH_AlgSHA256;
|
||||
*prefix = p_sha256;
|
||||
*prefixlen = sizeof(p_sha256);
|
||||
} else
|
||||
#endif
|
||||
#if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
|
||||
#ifdef USE_SHA2
|
||||
if(algo == LDNS_RSASHA512) {
|
||||
*htype = HASH_AlgSHA512;
|
||||
*prefix = p_sha512;
|
||||
@ -890,8 +917,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
|
||||
return 0;
|
||||
}
|
||||
*htype = HASH_AlgSHA256;
|
||||
*prefix = p_sha256;
|
||||
*prefixlen = sizeof(p_sha256);
|
||||
/* no prefix for DSA verification */
|
||||
break;
|
||||
case LDNS_ECDSAP384SHA384:
|
||||
*pubkey = nss_buf2ecdsa(key, keylen,
|
||||
@ -901,8 +927,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
|
||||
return 0;
|
||||
}
|
||||
*htype = HASH_AlgSHA384;
|
||||
*prefix = p_sha384;
|
||||
*prefixlen = sizeof(p_sha384);
|
||||
/* no prefix for DSA verification */
|
||||
break;
|
||||
#endif /* USE_ECDSA */
|
||||
case LDNS_ECC_GOST:
|
||||
@ -1006,10 +1031,13 @@ verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock,
|
||||
}
|
||||
err = PORT_GetError();
|
||||
if(err != SEC_ERROR_BAD_SIGNATURE) {
|
||||
/* failed to verify */
|
||||
/* failed to verify, but other errors are commonly returned
|
||||
* for a bad signature from NSS. Thus we return bogus,
|
||||
* not unchecked*/
|
||||
verbose(VERB_QUERY, "verify: PK11_Verify failed: %s",
|
||||
PORT_ErrorToString(err));
|
||||
return sec_status_unchecked;
|
||||
*reason = "signature crypto failed";
|
||||
return sec_status_bogus;
|
||||
}
|
||||
verbose(VERB_QUERY, "verify: signature mismatch: %s",
|
||||
PORT_ErrorToString(err));
|
||||
|
Loading…
Reference in New Issue
Block a user