Bug 2080581

Summary: [RFE] Provide simple way to check security of digest algorithm
Product: Red Hat Enterprise Linux 9 Reporter: Petr Menšík <pemensik>
Component: opensslAssignee: Dmitry Belyavskiy <dbelyavs>
Status: NEW --- QA Contact: BaseOS QE Security Team <qe-baseos-security>
Severity: low Docs Contact:
Priority: low    
Version: 9.0CC: dbelyavs
Target Milestone: rcKeywords: FutureFeature, Triaged
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Enhancement
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Petr Menšík 2022-04-30 09:39:01 UTC
Description of problem:
I made some digging in openssl man pages. I have been able to make relative simple change of fallback to insecure algorithms on FIPS mode [1] for bind. But it would be very useful if I could do as simple checks for sha1 algorithm and test, whether it is suitable for digital signatures.

I have found nice function EVP_MD_pkey_type() in EVP_DigestInit man page. It seems this function has lost major relevance, but could indicate suitability for crypto operation on given digest method.

int EVP_MD_pkey_type(const EVP_MD *md);

I would like to change the returned NID based on crypto-policy used for this. That way, I could make simple check

if (EVP_MD_pkey_type(EVP_sha1()) != NID_undef) {
  /* means LEGACY or DEFAULT:SHA1 policy is used */
} else {
  /* DEFAULT or FIPS policy used, openssl hints this digest is not good candidate for signature creation or verification. Indicates signature operation with it are likely to fail. */
}

That function clearly references relation to pkey, has simple int return value and according to man page is just for backward compatiblity. It seems the different return value should not break a good application. It seems exactly what I would need. I expect others might use it as well.


Version-Release number of selected component (if applicable):
openssl-3.0.1-21.el9.x86_64

Additional info:

ISC upstream is preparing their own version for FIPS support [2]. They even have sha functions checks built-in, by having bundled RSA key and checking different digests for it. While this is universal solution, such check is quite long, error prone and hard to maintain. Simpler indication of digest support from the library would make it much more readable, verifiable and faster to start as well.

1. https://gitlab.isc.org/isc-projects/bind9/-/merge_requests/6238
2. https://gitlab.isc.org/isc-projects/bind9/-/blob/mnowak/fix-fips-in-tests/lib/dns/opensslrsa_link.c#L1017

Comment 1 Petr Menšík 2022-04-30 09:45:46 UTC
More direct link to check of algorithm: https://gitlab.isc.org/isc-projects/bind9/-/blob/mnowak/fix-fips-in-tests/lib/dns/opensslrsa_link.c#L1637

Comment 2 Petr Menšík 2022-05-03 14:20:01 UTC
A new propsal exists on openssl, which would allow even specification of separate verification and generation of signatures.

Comment 3 Dmitry Belyavskiy 2022-07-26 08:23:56 UTC
https://github.com/openssl/openssl/issues/18867 provides some sort of check. If we are able to fetch the EVP_MD object and EVP_PKEY_CTX_set_signature_md fails, it's the case. 

Petr, is this solution sufficient for your purposes?

Comment 4 Petr Menšík 2022-08-04 10:34:36 UTC
My projects mostly depends on signature verification, signature creation is more rare case. And neither bind or unbound calls ever EVP_PKEY_CTX_set_signature_md directly in their code. So it does not help much. What I were looking for is kind of boolean check done before creating context for signature and key operations. Mentioned call requires loaded and prepared key, which is often not yet available in code I tried to simplify.

So no, I don't think such call would work for me. I would like to check algorithm availability before I have a key for OpenSSL prepared.

Comment 5 Petr Menšík 2023-06-20 09:58:56 UTC
It seems development version of BIND9 uses EVP_PKEY_CTX only for key generation:
https://gitlab.isc.org/isc-projects/bind9/-/blob/v9.19.13/lib/dns/opensslrsa_link.c?ref_type=tags#L349

$ grep -r EVP_PKEY_CTX_set_ lib
lib/dns/opensslrsa_link.c:	if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, (int)key_size) != 1) {
lib/dns/opensslrsa_link.c:		EVP_PKEY_CTX_set_app_data(ctx, (void *)callback);
lib/dns/opensslrsa_link.c:		EVP_PKEY_CTX_set_cb(ctx, progress_cb);
lib/dns/opensslecdsa_link.c:	status = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, group_nid);
lib/dns/opensslecdsa_link.c:		DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_set_ec_paramgen_"
lib/isc/tls.c:		rv = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pkey_ctx,


I just assume you propose here to call EVP_PKEY_verify_init() variant, followed by set_signature_md. Something like:

/* omitted proper return value checks for ease of reading */
int accept_sha1_sigs() {
  int ok;
  EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
  EVP_PKEY_verify_init(ctx);
  ok = (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1());
  EVP_PKEY_CTX_free(ctx);
  return ok;
}

ISC (upstream) made check using EVP_VerifyFinal:
https://gitlab.isc.org/isc-projects/bind9/-/blob/v9.19.13/lib/dns/opensslrsa_link.c?ref_type=tags#L1169

But the disadvantage here is they have to try the actual signature verification which nobody needed in fact. Wasting CPU cycles on the startup, including key data nobody needed etc.

Should above check work already on all our RHEL9 openssl versions already?

Comment 6 Dmitry Belyavskiy 2023-06-26 09:49:14 UTC
I double-checked the code. Until you at least set the key, this check will not fail. If you set the key, it should check whether sha1 is allowed.

Comment 7 Petr Menšík 2023-07-12 16:49:11 UTC
Could it be fixed then? Every DNSSEC validating solution needs to decide whether it is required to fetch key data. When it is trying to decide whether it should do it, it has at hand only algorithm number. While BIND9 has made some workarounds, I do not think this approach should be considered the best solution avaliable.

I should not have to provide fake built-in key just to check the system policy will block its use. If it is refused not because of key size, but because algorithm used, then it is not related to the key itself. It should not require key to check it.

I do not want to add built-in checking of fake keys into unbound or dnsmasq startup, just to work around inability to query system policy allowed algorithms. There has to be more correct method.

Comment 8 Dmitry Belyavskiy 2023-07-13 11:11:04 UTC
If you have an RSA key, what's the problem with this check? If you don't, are you affected?