no convert to der for DSA signatures

signature test.


git-svn-id: file:///svn/unbound/trunk@564 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-08-29 14:27:04 +00:00
parent 134db23ea8
commit de6d807e3d
4 changed files with 150 additions and 117 deletions

View file

@ -3,6 +3,9 @@
- added RSA and DSA test keys, public and private pairs, 512 bits. - added RSA and DSA test keys, public and private pairs, 512 bits.
- default configuration is with validation enabled. - default configuration is with validation enabled.
Only a trust-anchor needs to be configured for DNSSEC to work. 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 28 August 2007: Wouter
- removed double use for udp buffers, that could fail, - removed double use for udp buffers, that could fail,

121
testdata/val_positive.rpl vendored Normal file
View file

@ -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

View file

@ -312,7 +312,10 @@ ds_create_dnskey_digest(struct module_env* env,
ldns_buffer_limit(b), (unsigned char*)digest); ldns_buffer_limit(b), (unsigned char*)digest);
return 1; return 1;
#endif #endif
default: break; default:
verbose(VERB_DETAIL, "unknown DS digest algorithm %d",
(int) ds_get_digest_algo(ds_rrset, ds_idx));
break;
} }
return 0; return 0;
} }
@ -326,21 +329,33 @@ int ds_digest_match_dnskey(struct module_env* env,
uint8_t* digest; /* generated digest */ uint8_t* digest; /* generated digest */
size_t digestlen = ds_digest_size_algo(ds_rrset, ds_idx); 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 */ return 0; /* not supported, or DS RR format error */
}
/* check digest length in DS with length from hash function */ /* check digest length in DS with length from hash function */
ds_get_sigdata(ds_rrset, ds_idx, &ds, &dslen); 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 */ return 0; /* DS algorithm and digest do not match */
}
digest = region_alloc(env->scratch, digestlen); digest = region_alloc(env->scratch, digestlen);
if(!digest) if(!digest) {
verbose(VERB_DETAIL, "DS fail: out of memory");
return 0; /* mem error */ return 0; /* mem error */
}
if(!ds_create_dnskey_digest(env, dnskey_rrset, dnskey_idx, ds_rrset, 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 */ 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 0; /* digest different */
}
return 1; return 1;
} }
@ -1164,91 +1179,6 @@ log_crypto_error(const char* str, unsigned long e)
log_err("%s crypto %s", str, buf); 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. * 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 digest_type: digest type to use
* @param key: key to setup for. * @param key: key to setup for.
* @param keylen: length of key. * @param keylen: length of key.
* @param sig: sig to update if necessary.
* @param siglen: length of sig.
* @return false on failure. * @return false on failure.
*/ */
static int static int
setup_key_digest(int algo, EVP_PKEY* evp_key, const EVP_MD** digest_type, setup_key_digest(int algo, EVP_PKEY* evp_key, const EVP_MD** digest_type,
unsigned char* key, size_t keylen, unsigned char* key, size_t keylen)
unsigned char** sig, unsigned int* siglen)
{ {
switch(algo) { switch(algo) {
case LDNS_DSA: 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, EVP_PKEY_assign_DSA(evp_key,
ldns_key_buf2dsa_raw(key, keylen)); ldns_key_buf2dsa_raw(key, keylen));
*digest_type = EVP_dss1(); *digest_type = EVP_dss1();
if(!dsa_convert_to_der(sig, siglen))
return 0;
break; break;
case LDNS_RSASHA1: case LDNS_RSASHA1:
@ -1297,23 +1222,6 @@ setup_key_digest(int algo, EVP_PKEY* evp_key, const EVP_MD** digest_type,
return 1; 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 * Check a canonical sig+rrset and signature against a dnskey
* @param buf: buffer with data to verify, the first rrsig part and the * @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; return sec_status_unchecked;
} }
if(!setup_key_digest(algo, evp_key, &digest_type, key, keylen, if(!setup_key_digest(algo, evp_key, &digest_type, key, keylen)) {
&sigblock, &sigblock_len)) { verbose(VERB_DETAIL, "verify: failed to setup key");
EVP_PKEY_free(evp_key); EVP_PKEY_free(evp_key);
return sec_status_bogus; 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); res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key);
EVP_MD_CTX_cleanup(&ctx); EVP_MD_CTX_cleanup(&ctx);
EVP_PKEY_free(evp_key); EVP_PKEY_free(evp_key);
desetup_key_digest(algo, sigblock);
if(res == 1) { if(res == 1) {
return sec_status_secure; return sec_status_secure;

View file

@ -365,8 +365,10 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
* same DS hash algorithm. */ * same DS hash algorithm. */
if(!ds_digest_match_dnskey(env, dnskey_rrset, i, ds_rrset, if(!ds_digest_match_dnskey(env, dnskey_rrset, i, ds_rrset,
ds_idx)) { ds_idx)) {
verbose(VERB_ALGO, "DS match attempt failed");
continue; continue;
} }
verbose(VERB_ALGO, "DS match digest ok, trying signature");
/* Otherwise, we have a match! Make sure that the DNSKEY /* Otherwise, we have a match! Make sure that the DNSKEY
* verifies *with this key* */ * verifies *with this key* */