tpm2-software / tpm2-openssl

OpenSSL Provider for TPM2 integration
BSD 3-Clause "New" or "Revised" License
83 stars 37 forks source link

Can't cms sign with the private key in a TPM and the certificate in a file #80

Closed fhars closed 1 year ago

fhars commented 1 year ago

I am using tpm-openssl 1.1.1 with openssl 3.0.9 (on a custom yocto build) and try to cms sign a file using a key stored in the TPM and a certificate in the file system So far, I had no luck:

# openssl cms -sign -signer Cert.pem -inkey handle:0x81008000 -in foo.txt -text || echo "Failed: $?"
Failed: 3
# openssl cms -sign -signer Cert.pem -inkey handle:0x81008000 -in foo.txt -text -propquery 'provider = default' || echo "Failed: $?"
Could not open file or uri for loading signing key from handle:0x81008000
40B706C4E87F0000:error:16000069:STORE routines:ossl_store_get0_loader_int:unregistered scheme:../openssl-3.0.9/crypto/store/store_register.c:237:scheme=file
40B706C4E87F0000:error:80000002:system library:file_open:No such file or directory:../openssl-3.0.9/providers/implementations/storemgmt/file_store.c:267:calling stat(handle:0x81008000)
40B706C4E87F0000:error:16000069:STORE routines:ossl_store_get0_loader_int:unregistered scheme:../openssl-3.0.9/crypto/store/store_register.c:237:scheme=handle
40B706C4E87F0000:error:1608010C:STORE routines:inner_loader_fetch:unsupported:../openssl-3.0.9/crypto/store/store_meth.c:383:No store loader found. For standard store loaders you need at least one of the default or base providers available. Did you forget to load them? Info: Global default library context, Scheme (handle : 118), Properties (provider = default)
Failed: 2
# openssl cms -sign -signer Cert.pem -inkey handle:0x81008000 -in foo.txt -text -propquery 'provider = tpm2' || echo "Failed: $?"
Could not open file or uri for loading signer certificate from Cert.pem
40A7D4B6C77F0000:error:16000069:STORE routines:ossl_store_get0_loader_int:unregistered scheme:../openssl-3.0.9/crypto/store/store_register.c:237:scheme=file
40A7D4B6C77F0000:error:1608010C:STORE routines:inner_loader_fetch:unsupported:../openssl-3.0.9/crypto/store/store_meth.c:383:No store loader found. For standard store loaders you need at least one of the default or base providers available. Did you forget to load them? Info: Global default library context, Scheme (file : 0), Properties (provider = tpm2)
Unable to load signer certificate
Failed: 2
# openssl cms -sign -signer Cert.pem -inkey handle:0x81008000 -in foo.txt -text -propquery '?provider = default' || echo "Failed: $?"
Failed: 3
# openssl cms -sign -signer Cert.pem -inkey handle:0x81008000 -in foo.txt -text -propquery '?provider = tpm2' || echo "Failed: $?"
Could not open file or uri for loading signing key from handle:0x81008000
40B79090277F0000:error:16000069:STORE routines:ossl_store_get0_loader_int:unregistered scheme:../openssl-3.0.9/crypto/store/store_register.c:237:scheme=file
40B79090277F0000:error:80000002:system library:file_open:No such file or directory:../openssl-3.0.9/providers/implementations/storemgmt/file_store.c:267:calling stat(handle:0x81008000)
40B79090277F0000:error:16000069:STORE routines:ossl_store_get0_loader_int:unregistered scheme:../openssl-3.0.9/crypto/store/store_register.c:237:scheme=handle
40B79090277F0000:error:1608010C:STORE routines:inner_loader_fetch:unsupported:../openssl-3.0.9/crypto/store/store_meth.c:383:No store loader found. For standard store loaders you need at least one of the default or base providers available. Did you forget to load them? Info: 
Global default library context, Scheme (handle : 0), Properties (?provider = tpm2)
Failed: 2
# openssl cms -sign -signer Cert.pem -inkey handle:0x81008000 -in foo.txt -text -propquery '?provider != default' || echo "Failed: $?"
Failed: 3
# openssl cms -sign -signer Cert.pem -inkey handle:0x81008000 -in foo.txt -text -propquery '?provider != tpm2' || echo "Failed: $?"
Failed: 3

One might also say that the error messages leave a bit to be desired...

I don't know if this is a problem in tpm2_openssl or with providers in general or just a case of not finding things in the documentation, but given this comment I file it here first:

As I said, it is most probably a bug in the tpm2 provider around key export function. When a private key is loaded via store URL through the tpm2 provider, the provider should not export the public key. The libcrypto then ensures the tpm2 provider is always used for the private key operations with that key. If OTOH the tpm2 provider exports the public key if asked for exporting the key, the subsequent private key operation with the exported public key fails.

The cofiguration used is

openssl_conf = openssl_init

[openssl_init]
providers = provider_section

[provider_section]
tpm2 = tpm2_section
default = default_section

[tpm2_section]
activate = 1

[default_section]
activate = 1

The key itself works, and I can use it with the old engine:

# openssl cms -provider default -engine libtpm2tss -keyform engine -sign -signer Cert.pem -inkey 0x81008000 -in foo.txt -text
Engine "tpm2tss" set.
MIME-Version: 1.0
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha-256"; boundary="----D89E9D77B86902EE4D1C9C8DA93E8EB1"

This is an S/MIME signed message

------D89E9D77B86902EE4D1C9C8DA93E8EB1
Content-Type: text/plain

Foo

------D89E9D77B86902EE4D1C9C8DA93E8EB1
Content-Type: application/pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"

MIIDhgYJKoZIhvcNAQcCoIIDdzCCA3MCAQExDTALBglghkgBZQMEAgEwCwYJKoZI
[...]

------D89E9D77B86902EE4D1C9C8DA93E8EB1--
fhars commented 1 year ago

I see similar behaviour (i.e. plain text keys and the tpm2tss engine work, while the tpm2_openssl provider doesn't) with pkeyutl -sign:

$ openssl pkeyutl -engine libtpm2tss -keyform engine -sign -in foo.hash -inkey 0x81008000 -out sig.engine
Engine "tpm2tss" set.
$ openssl pkeyutl -verify -in foo.hash -sigfile sig.engine -pubin -inkey Pub.pem 
Signature Verified Successfully
$ openssl pkeyutl -provider tpm2 -provider default  -sign -in foo.hash -inkey handle:0x81008000 -out sig.provider
WARNING:esys:../git/src/tss2-esys/api/Esys_Sign.c:311:Esys_Sign_Finish() Received TPM Error 
ERROR:esys:../git/src/tss2-esys/api/Esys_Sign.c:105:Esys_Sign() Esys Finish ErrorCode (0x000001d5) 
Public Key operation error
40076724327F0000:error:4000000F:tpm2::cannot sign::-1:469 tpm:parameter(1):structure is the wrong size

The outlier is cms -decrypt, where neiter the provider nor the engine work in OpenSSL 3.0.9, while the engine worked in OpenSSL 1.1.1:

$ openssl cms -encrypt -recip Cert.pem -in foo.txt -out foo.enc
$ openssl cms -decrypt -in foo.enc -inkey Priv.pem
Foo
$ openssl cms -engine libtpm2tss -keyform engine -decrypt -in foo.enc -inkey 0x81008000
Engine "tpm2tss" set.
Error decrypting CMS using private key
40375679817F0000:error:170000BA:CMS routines:ecdh_cms_set_shared_info:kdf parameter error:../openssl-3.0.9/crypto/cms/cms_ec.c:174:
40375679817F0000:error:170000BD:CMS routines:ecdh_cms_decrypt:shared info error:../openssl-3.0.9/crypto/cms/cms_ec.c:243:
$ openssl cms -provider default -provider tpm2 -decrypt -in foo.enc -inkey handle:0x81008000 
Error decrypting CMS using private key
40578484777F0000:error:03000099:digital envelope routines:EVP_PKEY_copy_parameters:different parameters:../openssl-3.0.9/crypto/evp/p_lib.c:174:
40578484777F0000:error:170000BC:CMS routines:ecdh_cms_decrypt:peer key error:../openssl-3.0.9/crypto/cms/cms_ec.c:237:
$
fhars commented 1 year ago

The pkeyutil -sign and cms -decrypt issues seem to be gone from 1.2.0-rc1, but the cms -sign behaviour still seems to be broken.

fhars commented 1 year ago

This is just a symptom of #81.