Bug 2070977

Summary: bring SHA-1 verification blocking option to Fedora
Product: [Fedora] Fedora Reporter: Alexander Sosedkin <asosedki>
Component: opensslAssignee: Clemens Lang <cllang>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: high    
Version: rawhideCC: cllang, crypto-team, dbelyavs, gary.buhrmaster, mspacek, mturk, sahana, sgallagh, tm
Target Milestone: ---Keywords: Triaged
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: openssl-3.0.2-2.fc37 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2022-04-08 14:56:16 UTC 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:
Attachments:
Description Flags
Test script for TLS
none
sign_rsa.py from comment 3 none

Description Alexander Sosedkin 2022-04-01 13:43:29 UTC
In order to perform SHA-1 verification blocking in Fedora 37-38-39 multistage rollout,
most pressingly to disable it in FUTURE in f37, we'll need a config option like one in bz2031742.

Comment 1 Clemens Lang 2022-04-01 14:23:19 UTC
I'm already working on this.

Comment 2 Clemens Lang 2022-04-05 10:16:47 UTC
Acceptance Criteria:
 - when rh-allow-sha1-signatures is not set the creation and verification of SHA-1 signatures succeeds
 - when rh-allow-sha1-signatures is set to "no", creation and verification of SHA-1 signatures fails
 - In TLS, SHA-1 signature support in the signature_algorithms extension in ClientHello and CertificateRequest is advertised when rh-allow-sha1-signatures is "yes" and the current SECLEVEL is lower than 2
 - In TLS, SHA-1 signature support in the signature_algorithms extension in ClientHello and CertificateRequest is not advertised when rh-allow-sha1-signatures is unset and the current SECLEVEL is equal to 2
 - openssl1.1 does not fail when rh-allow-sha1-signatures is set (but does not actually support the option otherwise)

For some context, our plans outside of F36 and F37 for this are:

SHA1 behavior in:
------------------------------------------------------------------------------------------
|     | r-a-s-s default | LEGACY(SECLEVEL=1) | DEFAULT(SECLEVEL=2) | FUTURE (SECLEVEL=3) |
==========================================================================================
| F35 |     N/A         |     Allow Always   |   Disallow in TLS   |   Disallow in TLS   |
------------------------------------------------------------------------------------------
| F36 |  r-a-s-s=y      |     Allow Always   |   Disallow in TLS   |   Disallow in TLS   |
------------------------------------------------------------------------------------------
| F37 |  r-a-s-s=y      |     Allow Always   |   Disallow in TLS   |   Disallow Always   |
|     |                 |                    |                     |    r-a-s-s -> n     |
------------------------------------------------------------------------------------------
| F38 |            rawhide as-F39, then revert to as-F37 before release                  |
------------------------------------------------------------------------------------------
| F39 |  r-a-s-s=n      |   Disallow in TLS  |   Disallow Always   |   Disallow Always   |
|     |                 |    r-a-s-s -> y    |                     |                     |
------------------------------------------------------------------------------------------

Comment 3 Clemens Lang 2022-04-07 12:51:58 UTC
openssl1.1 seems to ignore the unknown option. I tested this with python3-m2crypto-0.38.0-2.fc35 on F36:

$ cat sign_rsa.py
#!/usr/bin/python3

import sys
from pathlib import Path
from M2Crypto import BIO, RSA, EVP

bio = BIO.MemoryBuffer(Path(sys.argv[1]).read_bytes())
rsa = RSA.load_key_bio(bio)
key = EVP.PKey()
key.assign_rsa(rsa)

payload = Path(sys.argv[2]).read_bytes()
key.digest_sign_init()
key.digest_sign_update(payload)
signature = key.digest_sign_final()

Path(sys.argv[3]).write_bytes(signature)
$ ./sign_rsa.py key.pem original-ks.cfg original-ks.cfg.sha1.sig
$ echo $?
0
$ grep -E '(alg_section|evp_properties|rh-allow-sha1-signatures)' /etc/pki/tls/openssl.cnf
alg_section = evp_properties
[evp_properties]
rh-allow-sha1-signatures = no

The config files were actually read by openssl 1.1:

$ strace -e trace=openat ./sign_rsa.py key.pem original-ks.cfg original-ks.cfg.sha1.sig |& grep -E '/etc/(pki|crypto-policies)'
openat(AT_FDCWD, "/etc/pki/tls/openssl.cnf", O_RDONLY) = 3
openat(AT_FDCWD, "/etc/crypto-policies/back-ends/opensslcnf.config", O_RDONLY) = 4
openat(AT_FDCWD, "/etc/pki/tls/openssl.cnf", O_RDONLY) = 3
openat(AT_FDCWD, "/etc/crypto-policies/back-ends/opensslcnf.config", O_RDONLY) = 4

And m2crypto does link against openssl 1.1:

$ dnf repoquery -l python3-m2crypto | grep _m2crypto
/usr/lib64/python3.10/site-packages/M2Crypto/_m2crypto.cpython-310-x86_64-linux-gnu.so
$ ldd /usr/lib64/python3.10/site-packages/M2Crypto/_m2crypto.cpython-310-x86_64-linux-gnu.so | grep -E 'lib(ssl|crypto)'
        libssl.so.1.1 => /lib64/libssl.so.1.1 (0x00007fe38a3a0000)
        libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x00007fe38a0b3000)

The generated signature is valid:

$ openssl dgst -sha1 -binary -out original-ks.cfg.sha1 original-ks.cfg
$ openssl pkeyutl -inkey key.pem -verify -sigfile original-ks.cfg.sha1.sig -in original-ks.cfg.sha1 -pkeyopt digest:sha1
Signature Verified Successfully

Comment 5 Clemens Lang 2022-04-08 13:44:49 UTC
With a mockbuild of 3.0.2-2.fc37 on rawhide:

SHA1 support:

$ grep -E '(alg_section|evp_properties|rh-allow-sha1-signatures)' /etc/pki/tls/openssl.cnf
alg_section = evp_properties
[evp_properties]
#rh-allow-sha1-signatures = yes
$ openssl dgst -sha1 -binary -out original-ks.cfg.sha1 original-ks.cfg
$ openssl pkeyutl -inkey localhost.key -sign -in original-ks.cfg.sha1 -out original-ks.cfg.sha1.sig -pkeyopt digest:sha1
$ openssl pkeyutl -inkey localhost.key -verify -sigfile original-ks.cfg.sha1.sig -in original-ks.cfg.sha1 -pkeyopt digest:sha1
Signature Verified Successfully

SHA1 disabled:

$ grep -E '(alg_section|evp_properties|rh-allow-sha1-signatures)' /etc/pki/tls/openssl.cnf
alg_section = evp_properties
[evp_properties]
rh-allow-sha1-signatures = no
$ openssl dgst -sha1 -binary -out original-ks.cfg.sha1 original-ks.cfg
$ openssl pkeyutl -inkey localhost.key -sign -in original-ks.cfg.sha1 -out original-ks.cfg.sha1.sig -pkeyopt digest:sha1
pkeyutl: Can't set parameter "digest:sha1":
C0915DFD797F0000:error:1C8000AE:Provider routines:rsa_setup_md:digest not allowed:providers/implementations/signature/rsa_sig.c:312:digest=sha1
$ openssl pkeyutl -inkey localhost.key -verify -sigfile original-ks.cfg.sha1.sig -in original-ks.cfg.sha1 -pkeyopt digest:sha1
pkeyutl: Can't set parameter "digest:sha1":
C05184CDF57F0000:error:1C8000AE:Provider routines:rsa_setup_md:digest not allowed:providers/implementations/signature/rsa_sig.c:312:digest=sha1

Comment 6 Clemens Lang 2022-04-08 13:46:28 UTC
Created attachment 1871457 [details]
Test script for TLS

Comment 7 Clemens Lang 2022-04-08 13:47:10 UTC
Created attachment 1871458 [details]
sign_rsa.py from comment 3

Comment 8 Fedora Update System 2022-04-08 14:54:47 UTC
FEDORA-2022-52b9bc6268 has been submitted as an update to Fedora 37. https://bodhi.fedoraproject.org/updates/FEDORA-2022-52b9bc6268

Comment 9 Fedora Update System 2022-04-08 14:56:16 UTC
FEDORA-2022-52b9bc6268 has been pushed to the Fedora 37 stable repository.
If problem still persists, please make note of it in this bug report.

Comment 10 Clemens Lang 2022-04-08 15:13:27 UTC
See also https://bodhi.fedoraproject.org/updates/FEDORA-2022-d906a1fd24 for f36.