From: Wouter Wijngaards Date: Tue, 17 Nov 2015 13:31:22 +0000 (+0000) Subject: - Fixup DER encoded DSA signatures for libnettle. X-Git-Tag: release-1.5.7rc1~30 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=39dc5be22226c254a85ec609d90a11d7969c34d8;p=thirdparty%2Funbound.git - Fixup DER encoded DSA signatures for libnettle. git-svn-id: file:///svn/unbound/trunk@3540 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index db8d34b00..e90ebb424 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -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. diff --git a/testcode/unitverify.c b/testcode/unitverify.c index 9e75ce1c6..9cb0eb99e 100644 --- a/testcode/unitverify.c +++ b/testcode/unitverify.c @@ -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); diff --git a/validator/val_secalgo.c b/validator/val_secalgo.c index 67ed50897..68e3eb015 100644 --- a/validator/val_secalgo.c +++ b/validator/val_secalgo.c @@ -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;