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:
Wouter Wijngaards 2012-06-22 14:31:29 +00:00
parent 42e23da129
commit 25096aa3ab
5 changed files with 107 additions and 38 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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, &params)) {
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));