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:
Petr Mensik 2022-04-08 12:15:14 +02:00
parent 730a03e9bd
commit 6cfcf21451
2 changed files with 44 additions and 39 deletions

View file

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

View file

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