diff --git a/doc/Changelog b/doc/Changelog index 41ea0f352..538ea702a 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,7 @@ - tpkg tests for udp wait list. - documented 0x20 status. - fixup chroot and checkconf, it is much smarter now. + - fixup DSA EVP signature decoding. Solution that Jelte found copied. 11 April 2008: Wouter - random port selection out of the configged ports. diff --git a/testcode/unitverify.c b/testcode/unitverify.c index 4c7eb7160..cd7a809ff 100644 --- a/testcode/unitverify.c +++ b/testcode/unitverify.c @@ -461,6 +461,7 @@ verify_test() { printf("verify test\n"); verifytest_file("testdata/test_signatures.1", "20070818005004"); + verifytest_file("testdata/test_signatures.2", "20080414005004"); dstest_file("testdata/test_ds_sig.1"); nsectest(); nsec3_hash_test("testdata/test_nsec3_hash.1"); diff --git a/testdata/test_signatures.2 b/testdata/test_signatures.2 new file mode 100644 index 000000000..03378538e --- /dev/null +++ b/testdata/test_signatures.2 @@ -0,0 +1,23 @@ +; Signature test file + +; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification. +; later entries are verified with it. + + +; DNSKEY used for testing, from april 2008 +ENTRY_BEGIN +SECTION QUESTION +cesar.sec3.br. IN DNSKEY +SECTION ANSWER +cesar.sec3.br. 43200 IN DNSKEY 257 3 3 AMAdw+X4IcinbsSOXamwV4BrJVbRjSJ63DYRV0NLR4W5cDMEQGmB3Lci ybjLvaEogs9RDmjhxQrQJRfaIVMG11LtOwlTPBr4yzyeK9zzeZPAQz2F 9yCCPqgUdts51v4XeK5evtn+b4AB7t/j+v7Vb+26k8No6hmJiRJAy59N Fpzrt5FoY5qFZ8QbPl59nzEcXTbOiXBNSu9mQbe/jFH5p9NP4KB0iNL/ oAthNIVVsDG8hQFh1hE5YlDNLxYY3U+TODjWx//DZvkn5Tyyvp7I6b33 oJiq +ENTRY_END + +; entry to test +ENTRY_BEGIN +SECTION QUESTION +cesar.sec3.br. IN SOA +SECTION ANSWER +cesar.sec3.br. 43200 IN SOA home.kuroiwa.eng.br. hostmaster.cesar.sec3.br. 2008040903 86400 86400 8640000 600 +cesar.sec3.br. 43200 IN RRSIG SOA 3 3 43200 20081010000000 20080410122550 14996 cesar.sec3.br. AJOGbuGOMggPspEBhIc58I8BXUHqR+DKiZqGZRwu9jMTgAX6JCPunSI= ;{id = 14996} +ENTRY_END + diff --git a/validator/val_sigcrypt.c b/validator/val_sigcrypt.c index f0c9fc4d2..6b2a1d21c 100644 --- a/validator/val_sigcrypt.c +++ b/validator/val_sigcrypt.c @@ -1182,6 +1182,48 @@ log_crypto_error(const char* str, unsigned long e) log_err("%s crypto %s", str, buf); } +/** + * Setup DSA key digest in DER encoding ... + * @param sig: input is signature output alloced ptr (unless failure). + * caller must free alloced ptr if this routine returns true. + * @param len: intput is initial siglen, output is output len. + * @return false on failure. + */ +static int +setup_dsa_sig(unsigned char** sig, unsigned int* len) +{ + unsigned char* orig = *sig; + unsigned int origlen = *len; + + uint8_t t; + BIGNUM *R, *S; + DSA_SIG *dsasig; + + /* extract the R and S field from the sig buffer */ + if(origlen < 1 + 2*SHA_DIGEST_LENGTH) + return 0; + t = orig[0]; + R = BN_new(); + if(!R) return 0; + (void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R); + S = BN_new(); + if(!S) return 0; + (void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S); + dsasig = DSA_SIG_new(); + if(!dsasig) return 0; + + dsasig->r = R; + dsasig->s = S; + *sig = NULL; + *len = i2d_DSA_SIG(dsasig, sig); + if(*len == 0) { + free(sig); + return 0; + } + DSA_SIG_free(dsasig); + return 1; +} + /** * Setup key and digest for verification. Adjust sig if necessary. * @@ -1255,6 +1297,13 @@ verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, EVP_PKEY_free(evp_key); return sec_status_bogus; } + if(algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) { + if(!setup_dsa_sig(&sigblock, &sigblock_len)) { + verbose(VERB_QUERY, "verify: failed to setup DSA sig"); + EVP_PKEY_free(evp_key); + return sec_status_bogus; + } + } /* do the signature cryptography work */ EVP_MD_CTX_init(&ctx); @@ -1265,6 +1314,10 @@ verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, EVP_MD_CTX_cleanup(&ctx); EVP_PKEY_free(evp_key); + if(algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) { + free(sigblock); + } + if(res == 1) { return sec_status_secure; } else if(res == 0) {