mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-01-22 22:52:55 -05:00
Make SHA-1 signed domains insecure if openssl refuses the digest
RHEL9/CentOS 9 would fail in default crypto policy. If call to openssl returns invalid digest then report the name insecure. If all tested signatures return the same issue, then make the reply insecure.
This commit is contained in:
parent
730a03e9bd
commit
6cfcf21451
2 changed files with 44 additions and 39 deletions
|
|
@ -652,6 +652,33 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
digest_ctx_free(EVP_MD_CTX* ctx, EVP_PKEY *evp_key,
|
||||
unsigned char* sigblock, int dofree, int docrypto_free)
|
||||
{
|
||||
#ifdef HAVE_EVP_MD_CTX_NEW
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
#else
|
||||
EVP_MD_CTX_cleanup(ctx);
|
||||
free(ctx);
|
||||
#endif
|
||||
EVP_PKEY_free(evp_key);
|
||||
if(dofree) free(sigblock);
|
||||
else if(docrypto_free) OPENSSL_free(sigblock);
|
||||
}
|
||||
|
||||
static enum sec_status
|
||||
digest_error_status(void)
|
||||
{
|
||||
#ifdef EVP_R_INVALID_DIGEST
|
||||
unsigned long e = ERR_get_error();
|
||||
if (ERR_GET_LIB(e) == ERR_LIB_EVP &&
|
||||
ERR_GET_REASON(e) == EVP_R_INVALID_DIGEST)
|
||||
return sec_status_indeterminate;
|
||||
#endif
|
||||
return sec_status_unchecked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a canonical sig+rrset and signature against a dnskey
|
||||
* @param buf: buffer with data to verify, the first rrsig part and the
|
||||
|
|
@ -735,62 +762,35 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
|
|||
}
|
||||
#ifndef HAVE_EVP_DIGESTVERIFY
|
||||
if(EVP_DigestInit(ctx, digest_type) == 0) {
|
||||
enum sec_status sec = digest_error_status();
|
||||
verbose(VERB_QUERY, "verify: EVP_DigestInit failed");
|
||||
#ifdef HAVE_EVP_MD_CTX_NEW
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
#else
|
||||
EVP_MD_CTX_cleanup(ctx);
|
||||
free(ctx);
|
||||
#endif
|
||||
EVP_PKEY_free(evp_key);
|
||||
if(dofree) free(sigblock);
|
||||
else if(docrypto_free) OPENSSL_free(sigblock);
|
||||
return sec_status_unchecked;
|
||||
digest_ctx_free(ctx, evp_key, sigblock,
|
||||
dofree, docrypto_free);
|
||||
return sec;
|
||||
}
|
||||
if(EVP_DigestUpdate(ctx, (unsigned char*)sldns_buffer_begin(buf),
|
||||
(unsigned int)sldns_buffer_limit(buf)) == 0) {
|
||||
verbose(VERB_QUERY, "verify: EVP_DigestUpdate failed");
|
||||
#ifdef HAVE_EVP_MD_CTX_NEW
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
#else
|
||||
EVP_MD_CTX_cleanup(ctx);
|
||||
free(ctx);
|
||||
#endif
|
||||
EVP_PKEY_free(evp_key);
|
||||
if(dofree) free(sigblock);
|
||||
else if(docrypto_free) OPENSSL_free(sigblock);
|
||||
digest_ctx_free(ctx, evp_key, sigblock,
|
||||
dofree, docrypto_free);
|
||||
return sec_status_unchecked;
|
||||
}
|
||||
|
||||
res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key);
|
||||
#else /* HAVE_EVP_DIGESTVERIFY */
|
||||
if(EVP_DigestVerifyInit(ctx, NULL, digest_type, NULL, evp_key) == 0) {
|
||||
enum sec_status sec = digest_error_status();
|
||||
verbose(VERB_QUERY, "verify: EVP_DigestVerifyInit failed");
|
||||
#ifdef HAVE_EVP_MD_CTX_NEW
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
#else
|
||||
EVP_MD_CTX_cleanup(ctx);
|
||||
free(ctx);
|
||||
#endif
|
||||
EVP_PKEY_free(evp_key);
|
||||
if(dofree) free(sigblock);
|
||||
else if(docrypto_free) OPENSSL_free(sigblock);
|
||||
return sec_status_unchecked;
|
||||
digest_ctx_free(ctx, evp_key, sigblock,
|
||||
dofree, docrypto_free);
|
||||
return sec;
|
||||
}
|
||||
res = EVP_DigestVerify(ctx, sigblock, sigblock_len,
|
||||
(unsigned char*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_limit(buf));
|
||||
#endif
|
||||
#ifdef HAVE_EVP_MD_CTX_NEW
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
#else
|
||||
EVP_MD_CTX_cleanup(ctx);
|
||||
free(ctx);
|
||||
#endif
|
||||
EVP_PKEY_free(evp_key);
|
||||
|
||||
if(dofree) free(sigblock);
|
||||
else if(docrypto_free) OPENSSL_free(sigblock);
|
||||
digest_ctx_free(ctx, evp_key, sigblock,
|
||||
dofree, docrypto_free);
|
||||
|
||||
if(res == 1) {
|
||||
return sec_status_secure;
|
||||
|
|
|
|||
|
|
@ -646,6 +646,7 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
|
|||
int algo = rrset_get_sig_algo(rrset, sig_idx);
|
||||
size_t i, num = rrset_get_count(dnskey);
|
||||
size_t numchecked = 0;
|
||||
size_t numindeterminate = 0;
|
||||
int buf_canon = 0;
|
||||
verbose(VERB_ALGO, "verify sig %d %d", (int)tag, algo);
|
||||
if(!dnskey_algo_id_is_supported(algo)) {
|
||||
|
|
@ -666,12 +667,16 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
|
|||
sig_idx, sortree, &buf_canon, reason, section, qstate);
|
||||
if(sec == sec_status_secure)
|
||||
return sec;
|
||||
else if(sec == sec_status_indeterminate)
|
||||
numindeterminate ++;
|
||||
}
|
||||
if(numchecked == 0) {
|
||||
*reason = "signatures from unknown keys";
|
||||
verbose(VERB_QUERY, "verify: could not find appropriate key");
|
||||
return sec_status_bogus;
|
||||
}
|
||||
if (numindeterminate == numchecked)
|
||||
return sec_status_indeterminate;
|
||||
return sec_status_bogus;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue