open-quantum-safe / oqs-provider

OpenSSL 3 provider containing post-quantum algorithms
https://openquantumsafe.org
MIT License
225 stars 88 forks source link

Enable correct operation of openssl ca #115

Closed baentsch closed 1 year ago

baentsch commented 1 year ago

Discussed in https://github.com/open-quantum-safe/oqs-provider/discussions/110

Originally posted by **Dechen2333** February 8, 2023 Hello, I want to create my own CA and OCSP server to test a program with oqsprovider implementation. I'm using the docker image provided by this link: https://github.com/open-quantum-safe/oqs-provider/wiki/Interoperability#ietf-115-hackathon In the container, I created a falcon1024 key and selfsigned certification for the CA, a dilithium2 key and then sign the dilithium2 key with the falcon CA key. If I verify the dilithium certification using the CAfile, it ends up with an error in asn1 encoding routines. If I use a rsa 2048 key as root CA key instead, everything will be fine. Step to reproduce: 1. docker run -it openquantumsafe/oqs-ossl3:ietf115 2. mkdir -p demoCA/newcerts 3. touch demoCA/index.txt 4. echo '01' > demoCA/serial 5. openssl req -x509 -new -newkey falcon1024 -keyout falc_rootCA.key -out falc_rootCA.crt -subj "/CN=test CA" -nodes 6. openssl req -new -newkey dilithium2 -keyout dilithium2.key -out dilithium2.csr -nodes -config openssl.cnf -subj "/CN=test Server" 7. openssl ca -batch -startdate 150123080000Z -enddate 250823090000Z -keyfile falc_rootCA.key -cert falc_rootCA.crt -policy policy_anything -config openssl.cnf -notext -out dilithium2.crt -infiles dilithium2.csr 8. openssl verify -CAfile falc_rootCA.crt dilithium2.crt Then I receive the error codes: error 7 at 0 depth lookup: certificate signature failure error dilithium2.crt: verification failed 487BBAB4387F0000:error:4000000E:lib(128):oqs_sig_verify:reason(14):/opt/oqs-provider/oqsprov/oqs_sig.c:405: 487BBAB4387F0000:error:06880006:asn1 encoding routines:ASN1_item_verify_ctx:EVP lib:crypto/asn1/a_verify.c:215: openssl version: OpenSSL 3.2.0-dev-pr19312 (Library: OpenSSL 3.2.0-dev-pr19312 ) If I use the certification that signed by a PQC CA key in my program with oqsprovider implementation, the same error appear while the TLS handshake oqsprovider version: OQS Provider v.0.5.0-dev-nopub based on liboqs v.0.7.3-dev openssl.cnf: https://github.com/Dechen2333/opensslcnf/blob/main/openssl.cnf
martinschmatz commented 1 year ago

Sali Michael - not sure it relates, but I'm getting errors when using openssl req to generate a csr:

$my_openssl req \
                     -config $Intermediate_CA_conf_file \
                     -extensions server_cert \
                     -subj "/C=CH/ST=Switzerland/L=Zurich/O=IBM Research ZRL/OU=IBM ZRL Server/CN=$server_name" \
                     -key private/$server_name.key \
                     -new \
                     -out csr/$server_name.csr

with server_cert extension as follows:

[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate by IBM"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @server_alt_names

Error I get is:

Error adding request extensions from section server_cert
C054C20A2C7F0000:error:11000079:X509 V3 routines:v2i_AUTHORITY_KEYID:no issuer certificate:crypto/x509/v3_akid.c:156:
C054C20A2C7F0000:error:11000080:X509 V3 routines:X509V3_EXT_nconf_int:error in extension:crypto/x509/v3_conf.c:48:section=server_cert, name=authorityKeyIdentifier, value=keyid,issuer:always

Suspicion is that the subjectKeyIdentifier = hash is not taken into account (such that authorityKeyIdentifier would be filled with the keyid and more doesn't need to be known about the authority at this point in time).
I need to debug some more but thought I already share this here.

En liebe Gruess - Martin

PS:

OpenSSL 3.2.0-dev  (Library: OpenSSL 3.2.0-dev ) 
OQS_liboqs_Commit=4916446
OQS_OpenSSL3provider_Commit=ecb095d
OpenSSL3_Commit=359d6a2
martinschmatz commented 1 year ago

Observation: When adding -md NULL to step 7 openssl ca... or change the default_md in the openssl.cnf file to NULL, the certificate is not generated, without error message.

I was under the impression that QSC signatures as per NIST API do not use an external digest function....?!? Formulated differently: Is there a dgst function in the openssl ca applied or not applied for QSC signatures?

Remark: When generating the certificate with openssl x509 -req ..., verification works just fine:

openssl x509 -req \
                -in dilithium2.csr \
                -out dilithium2b.crt \
                -CA falc_rootCA.crt \
                -CAkey falc_rootCA.key \
                -CAcreateserial \
                -days 300 \
                -extfile openssl.cnf \
                -extensions usr_cert
../openssl verify -CAfile falc_rootCA.crt dilithium2b.crt 
==> dilithium2b.crt: OK
martinschmatz commented 1 year ago

Observation: The value of dgst here is whatever is specified via -md option or as default_md in the config file.

martinschmatz commented 1 year ago

Observation: If I add dgst=NULL before this line, the verification succeeds.

martinschmatz commented 1 year ago

If if (def_ret == -2) dgst = NULL; else is inserted before this line, the verification succeeds.

Explanation: The documentation for EVP_PKEY_get_default_digest_name (used in the preceding line) states: "In particular a return value of -2 indicates the operation is not supported by the public key algorithm." If getting a default digest name is not supported, it should be OK that the dgst value is set to NULL. With that, the dgst value in the later call to do_X509_sign is still 'NULL'.

@baentsch Any opinion on that?

baentsch commented 1 year ago

At first glance, it seems the use of EVP_PKEY_get_default_digest_name is incorrect for provider-based sigalgs as the documentation also states "This function is only reliable for legacy keys", but I'll take a closer look; thanks for the "digging" to this point.

martinschmatz commented 1 year ago

The way I read it is that "This function is only reliable for legacy keys" means that it only reliably returns 1 or 2 for legacy keys, but reliably returns -2 for keys that don't support the function. --> Irrespective of provider-based or not, it seems to me that the -2 case should be handled explicitly.

For provider-based, one could also look here --> here --> here and enable EVP_PKEY_get_default_digest_name to return 2 and "UNDEF" such that dgst = NULL is executed here. Implies that the ameth for provider-based appropriately implemnets pkey_ctrl.

baentsch commented 1 year ago

The comment regarding legacy keys anyway only applies to EVP_PKEY_get_default_digest_nid. Looking at the implementation of EVP_PKEY_get_default_digest_name in turn shows correct OSSL_PARAM usage. ~Accordingly, the minimal code change in this branch resolves that issue. Unfortunately, it seems to unearth another problem in the CSR-generation logic we need to resolve.~ Thanks to @Dechen2333 for providing a complete test setup! (Edit/add: Code was wrong, need to re-do).

baentsch commented 1 year ago

@Dechen2333 could you please check #119 resolves the issue for you? Also, are you OK with us using your CA test setup in CI?

Dechen2333 commented 1 year ago

Hello, yes, you can use it of course. I can still reproduce the bug in the container built with the image openquantumsafe/oqs-ossl3:ietf115 or latest tags, is it only fixed on the branch https://github.com/open-quantum-safe/oqs-provider/pull/119?

baentsch commented 1 year ago

is it only fixed on the branch https://github.com/open-quantum-safe/oqs-provider/pull/119

Yes. But you're making a good point with the container reference. I just created a new interop test container in preparation for IETF116: This contains all the latest code (incl. #119 as I assume that will merge in the coming days): You may thus want to test using openquantumsafe/oqs-ossl3:ietf116.

Dechen2333 commented 1 year ago

Yes, I have tried openssl ca and ocsp operations in the container created by ietf116, it worked as expected. Thank you very much for the help.