.`httpd` now starts correctly if using an ECDSA private key without matching public key stored in a PKCS #11 device
Unlike RSA keys, ECDSA private keys do not necessarily contain public-key information. In this case, you cannot obtain the public key from an ECDSA private key. For this reason, a PKCS #11 device stores public-key information in a separate object whether it is a public-key object or a certificate object. OpenSSL expected the `EVP_PKEY` structure provided by an engine for a private key to contain the public-key information. When filling the `EVP_PKEY` structure to be provided to OpenSSL, the engine in the `openssl-pkcs11` package tried to fetch the public-key information only from matching public-key objects and ignored the present certificate objects.
When OpenSSL requested an ECDSA private key from the engine, the provided `EVP_PKEY` structure did not contain the public-key information if the public key was not present in the PKCS #11 device, even when a matching certificate that contained the public key was available. As a consequence, since the Apache `httpd` web server called the `X509_check_private_key()` function, which requires the public key, in its start-up process, `httpd` failed to start in this scenario. This problem has been solved by loading the EC public key from the certificate if the public-key object is not available. As a result, `httpd` now starts correctly when ECDSA keys are stored in a PKCS #11 device.
DescriptionStanislav Zidek
2019-01-09 17:22:53 UTC
Description of problem:
httpd does not work with ECDSA keys stored on PKCS#11 token. I am not sure however if the problems is in httpd or perhaps "lower" (in openssl-pkcs11?).
Version-Release number of selected component (if applicable):
httpd-2.4.37-7.module+el8+2443+605475b7.x86_64
openssl-pkcs11-0.4.8-2.el8.x86_64
openssl-1.1.1-8.el8.x86_64
softhsm-2.4.0-1.el8.x86_64
How reproducible:
always
Steps to Reproduce:
1. cd into directory with /CoreOS/p11-kit/Integration/httpd-pkcs11-uri
2. change KEYTYPES array to test rsa-pss - "KEYTYPES=(ecdsa)"
3. 1minutetip --buildroot rhel8
Actual results:
/var/log/httpd/error_log:
Found slot: SoftHSM slot ID 0x207efe18
Found token: softhsm
Found 1 private key:
1 P id=a67ded529c7faeea455b90589c1003e4b95df7e9 label=httpd
AH00016: Configuration Failed
/var/log/httpd/ssl_error_log:
[...] [ssl:debug] [...] ssl_engine_pphrase.c(872): Init: Initialized engine pkcs11 for private key pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=45e2053c207efe18;token=softhsm;id=%a6%7d%ed%52%9c%7f%ae%ea%45%5b%90%58%9c%10%03%e4%b9%5d%f7%e9;object=httpd;type=private?pin-value=123456
[...] [ssl:emerg] [...] AH10130: Failed to configure private key pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=45e2053c207efe18;token=softhsm;id=%a6%7d%ed%52%9c%7f%ae%ea%45%5b%90%58%9c%10%03%e4%b9%5d%f7%e9;object=httpd;type=private?pin-value=123456 from engine
[...] [ssl:emerg] [...] SSL Library Error: error:0B080075:x509 certificate routines:X509_check_private_key:unknown key type
Expected results:
no problems
(In reply to Stanislav Zidek from comment #0)
> Description of problem:
...
> Steps to Reproduce:
> 1. cd into directory with /CoreOS/p11-kit/Integration/httpd-pkcs11-uri
> 2. change KEYTYPES array to test rsa-pss - "KEYTYPES=(ecdsa)"
I meant ecdsa, not rsa-pss, of course. There is separate rsa-pss bug - bz1664802
The root of this issue is because the openssl-pkcs11 engine does not extract the public key from the certificate, but tries to find a matching public key object inside the device when initializing the EVP_PKEY structure for the private key. So, if the public key is not present in the device, the EVP_PKEY structure returned by ENGINE_load_private_key() will not hold a reference to the public key.
When httpd calls X509_check_private_key() to verify if the private key matches with the certificate, it ends up calling EC_KEY_get0_public_key() to get the public key from the EVP_PKEY structure, which will return NULL, since the reference is not there. This causes a failure in the matching check and consequently the failure in httpd start up.
The solution for ECDSA, is to store both private and public keys in the device.
I've attached a minimal reproducer for this issue in comment 3.
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.
For information on the advisory, and where to find the updated
files, follow the link below.
If the solution does not work for you, open a new bug report.
https://access.redhat.com/errata/RHBA-2020:1871