From: Wouter Wijngaards Date: Wed, 29 Aug 2007 14:27:04 +0000 (+0000) Subject: no convert to der for DSA signatures X-Git-Tag: release-0.5~77 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de6d807e3d380ce4e522bd4cff2abe097f81ead5;p=thirdparty%2Funbound.git no convert to der for DSA signatures signature test. git-svn-id: file:///svn/unbound/trunk@564 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 8042649d5..60f3886aa 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,9 @@ - added RSA and DSA test keys, public and private pairs, 512 bits. - default configuration is with validation enabled. Only a trust-anchor needs to be configured for DNSSEC to work. + - do not convert to DER for DSA signature verification. + - validator replay test file, for a DS to DNSKEY DSA key prime and + positive response. 28 August 2007: Wouter - removed double use for udp buffers, that could fail, diff --git a/testdata/val_positive.rpl b/testdata/val_positive.rpl new file mode 100644 index 000000000..cad6b1063 --- /dev/null +++ b/testdata/val_positive.rpl @@ -0,0 +1,121 @@ +; config options +; The island of trust is at example.com +server: + trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b" + val-override-date: "20070916134226" + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test validator with positive response + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.4 + +; response to DNSKEY priming query +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN DNSKEY +SECTION ANSWER +example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b} +example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854} +ENTRY_END + +; response to query of interest +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 10 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AD NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +SECTION AUTHORITY +example.com. IN NS ns.example.com. +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.4 +ENTRY_END + +SCENARIO_END diff --git a/validator/val_sigcrypt.c b/validator/val_sigcrypt.c index ef848b99b..cfa57a77f 100644 --- a/validator/val_sigcrypt.c +++ b/validator/val_sigcrypt.c @@ -312,7 +312,10 @@ ds_create_dnskey_digest(struct module_env* env, ldns_buffer_limit(b), (unsigned char*)digest); return 1; #endif - default: break; + default: + verbose(VERB_DETAIL, "unknown DS digest algorithm %d", + (int) ds_get_digest_algo(ds_rrset, ds_idx)); + break; } return 0; } @@ -326,21 +329,33 @@ int ds_digest_match_dnskey(struct module_env* env, uint8_t* digest; /* generated digest */ size_t digestlen = ds_digest_size_algo(ds_rrset, ds_idx); - if(digestlen == 0) + if(digestlen == 0) { + verbose(VERB_DETAIL, "DS fail: not supported, or DS RR " + "format error"); return 0; /* not supported, or DS RR format error */ + } /* check digest length in DS with length from hash function */ ds_get_sigdata(ds_rrset, ds_idx, &ds, &dslen); - if(!ds || dslen != digestlen) + if(!ds || dslen != digestlen) { + verbose(VERB_DETAIL, "DS fail: DS RR algo and digest do not " + "match each other"); return 0; /* DS algorithm and digest do not match */ + } digest = region_alloc(env->scratch, digestlen); - if(!digest) + if(!digest) { + verbose(VERB_DETAIL, "DS fail: out of memory"); return 0; /* mem error */ + } if(!ds_create_dnskey_digest(env, dnskey_rrset, dnskey_idx, ds_rrset, - ds_idx, digest)) + ds_idx, digest)) { + verbose(VERB_DETAIL, "DS fail: could not calc key digest"); return 0; /* digest algo failed */ - if(memcmp(digest, ds, dslen) != 0) + } + if(memcmp(digest, ds, dslen) != 0) { + verbose(VERB_DETAIL, "DS fail: digest is different"); return 0; /* digest different */ + } return 1; } @@ -1164,91 +1179,6 @@ log_crypto_error(const char* str, unsigned long e) log_err("%s crypto %s", str, buf); } -/** - * Convert DSA RRsig sigblock to a DSA_SIG structure. - * @param sig: sigblock field of RRSIG - * @param siglen: length of sig. - * @return DSA_SIG or NULL - */ -static DSA_SIG* -dsa_rrsig_to_dsa_sig(unsigned char* sig, unsigned int siglen) -{ - uint8_t t; - BIGNUM *R, *S; - DSA_SIG *dsasig; - - /* extract the R and S field from the sig buffer */ - if(siglen < 1 + SHA_DIGEST_LENGTH*2) { - verbose(VERB_DETAIL, "verify: short DSA RRSIG"); - return NULL; - } - t = sig[0]; - R = BN_new(); - if(!R) { - log_err("verify: alloc failure"); - return NULL; - } - S = BN_new(); - if(!S) { - BN_free(R); - log_err("verify: alloc failure"); - return NULL; - } - if(!BN_bin2bn(sig + 1, SHA_DIGEST_LENGTH, R)) { - log_err("verify: bignum failure"); - BN_free(R); - BN_free(S); - return NULL; - } - if(!BN_bin2bn(sig + 21, SHA_DIGEST_LENGTH, S)) { - log_err("verify: bignum failure"); - BN_free(R); - BN_free(S); - return NULL; - } - - dsasig = DSA_SIG_new(); - if(!dsasig) { - log_err("verify: alloc failure"); - BN_free(R); - BN_free(S); - return NULL; - } - dsasig->r = R; - dsasig->s = S; - return dsasig; -} - -/** - * Convert DSA signature to a DER signature. - * @param sig: signature, used to read, then replaced with malloced - * DER signature on success. - * @param siglen: read to get input len, then updated to new length. - * @return false on (alloc) error. - */ -static int -dsa_convert_to_der(unsigned char** sig, unsigned int* siglen) -{ - DSA_SIG* dsasig; - int res; - - dsasig = dsa_rrsig_to_dsa_sig(*sig, *siglen); - if(!dsasig) { - return 0; - } - *sig = NULL; /* needs libcrypto >= 0.9.7 */ - res = i2d_DSA_SIG(dsasig, sig); - if(res < 0) { - log_crypto_error("verify: bad dsa sig ", - ERR_get_error()); - DSA_SIG_free(dsasig); - return 0; - } - DSA_SIG_free(dsasig); - *siglen = (unsigned int)res; - return 1; -} - /** * Setup key and digest for verification. Adjust sig if necessary. * @@ -1257,14 +1187,11 @@ dsa_convert_to_der(unsigned char** sig, unsigned int* siglen) * @param digest_type: digest type to use * @param key: key to setup for. * @param keylen: length of key. - * @param sig: sig to update if necessary. - * @param siglen: length of sig. * @return false on failure. */ static int setup_key_digest(int algo, EVP_PKEY* evp_key, const EVP_MD** digest_type, - unsigned char* key, size_t keylen, - unsigned char** sig, unsigned int* siglen) + unsigned char* key, size_t keylen) { switch(algo) { case LDNS_DSA: @@ -1272,8 +1199,6 @@ setup_key_digest(int algo, EVP_PKEY* evp_key, const EVP_MD** digest_type, EVP_PKEY_assign_DSA(evp_key, ldns_key_buf2dsa_raw(key, keylen)); *digest_type = EVP_dss1(); - if(!dsa_convert_to_der(sig, siglen)) - return 0; break; case LDNS_RSASHA1: @@ -1297,23 +1222,6 @@ setup_key_digest(int algo, EVP_PKEY* evp_key, const EVP_MD** digest_type, return 1; } -/** - * Desetup what setup_key_digest setup. - * @param algo: key algorithm - * @param sig: signature. - */ -static void -desetup_key_digest(int algo, unsigned char* sig) -{ - switch(algo) { - case LDNS_DSA: - case LDNS_DSA_NSEC3: - /* free converted signature */ - free(sig); - break; - } -} - /** * Check a canonical sig+rrset and signature against a dnskey * @param buf: buffer with data to verify, the first rrsig part and the @@ -1339,8 +1247,8 @@ verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, return sec_status_unchecked; } - if(!setup_key_digest(algo, evp_key, &digest_type, key, keylen, - &sigblock, &sigblock_len)) { + if(!setup_key_digest(algo, evp_key, &digest_type, key, keylen)) { + verbose(VERB_DETAIL, "verify: failed to setup key"); EVP_PKEY_free(evp_key); return sec_status_bogus; } @@ -1353,7 +1261,6 @@ verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key); EVP_MD_CTX_cleanup(&ctx); EVP_PKEY_free(evp_key); - desetup_key_digest(algo, sigblock); if(res == 1) { return sec_status_secure; diff --git a/validator/val_utils.c b/validator/val_utils.c index 0590d0b70..0b39adcbf 100644 --- a/validator/val_utils.c +++ b/validator/val_utils.c @@ -365,8 +365,10 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve, * same DS hash algorithm. */ if(!ds_digest_match_dnskey(env, dnskey_rrset, i, ds_rrset, ds_idx)) { + verbose(VERB_ALGO, "DS match attempt failed"); continue; } + verbose(VERB_ALGO, "DS match digest ok, trying signature"); /* Otherwise, we have a match! Make sure that the DNSKEY * verifies *with this key* */