]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
implement DNSSEC with libNSS: NSEC3, RSA, DSA, ECDSA, and DS hashes.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 22 Jun 2012 14:31:29 +0000 (14:31 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 22 Jun 2012 14:31:29 +0000 (14:31 +0000)
make test succeeds.

git-svn-id: file:///svn/unbound/trunk@2699 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
testcode/testbound.c
testcode/unitverify.c
validator/val_nsec3.c
validator/val_secalgo.c

index 5ddd5b04427c14a846c8475a1aafc7480c6def26..e4af5412c20438ebde709dbcb71eace6ea4fd079 100644 (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.
index 05982849cc29ce596f3f3255e6e843838178ccb1..6e88edf22e625a9cd7c4d3dd32dabda02b3fafdb 100644 (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
index 2bc842c75374165f0880c10a35d29ff96695e26e..ce1bbd1f5261412f19bd2ef5535eaee0a36bf9ce 100644 (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");
index a18e3ab31d068ea7ce7518c12a652c4adca542e0..419bbc51d848829ce7f1c750fd48a7e0c65b3f1a 100644 (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;
index df5357cf62769aa236b6b073771aa333738ce951..8549c61659fd035338ea3d3a6ba607294d53cf70 100644 (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));