mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
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:
parent
134db23ea8
commit
de6d807e3d
4 changed files with 150 additions and 117 deletions
|
|
@ -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,
|
||||
|
|
|
|||
121
testdata/val_positive.rpl
vendored
Normal file
121
testdata/val_positive.rpl
vendored
Normal 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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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* */
|
||||
|
|
|
|||
Loading…
Reference in a new issue