]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fixup DER encoded DSA signatures for libnettle.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 17 Nov 2015 13:31:22 +0000 (13:31 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 17 Nov 2015 13:31:22 +0000 (13:31 +0000)
git-svn-id: file:///svn/unbound/trunk@3540 be551aaa-1e26-0410-a405-d3ace91eadb9

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

index db8d34b001796e6e97d7f41a0ac4d7273d3c7c59..e90ebb42440eef2d73090bd489b85e2e885bd858 100644 (file)
@@ -4,6 +4,7 @@
          --with-libunbound-only.
        - refactor nsec3 hash implementation to be more library-portable.
        - iana portlist update.
+       - Fixup DER encoded DSA signatures for libnettle.
 
 16 November 2015: Wouter
        - Fix for lenient accept of reverse order DNAME and CNAME.
index 9e75ce1c62883fb8883a566ce040cbc9a93e0d5f..9cb0eb99e7ccfacf61755e409764ba6ce12e6be3 100644 (file)
@@ -191,8 +191,7 @@ verifytest_rrset(struct module_env* env, struct val_env* ve,
                printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
                        reason?reason:"");
        }
-       if(should_be_bogus(rrset, qinfo) ||
-               (reason && strncmp(reason, "(custom)", 8) == 0)) {
+       if(should_be_bogus(rrset, qinfo)) {
                unit_assert(sec == sec_status_bogus);
        } else {
                unit_assert(sec == sec_status_secure);
index 67ed5089767228d20ec0b88bf95f271d9b219062..68e3eb0156b47148bb345e8dde0cb10cbd50299f 100644 (file)
@@ -1129,6 +1129,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
 #include "macros.h"
 #include "rsa.h"
 #include "dsa.h"
+#include "asn1.h"
 #ifdef USE_ECDSA
 #include "ecdsa.h"
 #include "ecc-curve.h"
@@ -1292,15 +1293,40 @@ _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
        struct dsa_signature signature;
        unsigned int expected_len;
 
-       /* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */
-       key_t = key[0];
-       if (key_t != sigblock[0] || key_t > 8 ) {
-               return "invalid T value in DSA signature or pubkey";
+       /* 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 */
+               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";
        }
 
-       /* Signature length: 41 bytes - RFC 2536 sec. 3 */
-       if (sigblock_len != 41) {
-               return "invalid DSA signature length";
+       /* 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 */
@@ -1328,11 +1354,6 @@ _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
        offset += (64 + key_t*8);
        nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t*8), key+offset);
 
-       /* Extract DSA signature from the record */
-       nettle_dsa_signature_init(&signature);
-       nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1);
-       nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20);
-
        /* 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), digest);
@@ -1519,11 +1540,6 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
        switch(algo) {
        case LDNS_DSA:
        case LDNS_DSA_NSEC3:
-               /* Some of these signatures are non-standard */
-               if (key[0] > 8 || sigblock_len != 41) {
-                       *reason = "(custom) unknown DSA signature";
-                       return sec_status_unchecked;
-               }
                *reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
                if (*reason != NULL)
                        return sec_status_bogus;