tpm2-software / tpm2-pkcs11

A PKCS#11 interface for TPM2 hardware
https://tpm2-software.github.io
Other
270 stars 106 forks source link

Fedora 36 ErrorCode (0x00070001) Could not create rsa key. #766

Closed traxtopel closed 2 years ago

traxtopel commented 2 years ago

Following the instructions on the main page for EAP-TLS Configuration. Worked previously tests on Centos 8. Any ideas to what to check? Tried removing the sqlite3 database and running tpm2_clear.

root:~# openssl req -new -engine pkcs11 -keyform engine -key "${PRIVATE_KEY};pin-value=userpin" -subj "${SUBJ}" -out client.csr Engine "pkcs11" set. WARNING: Listing FAPI token objects failed: "fapi:Provisioning was not executed." Please see https://github.com/tpm2-software/tpm2-pkcs11/blob/1.7.0/docs/FAPI.md for more details WARNING: Getting tokens from fapi backend failed. ERROR:esys_crypto:src/tss2-esys/esys_crypto_ossl.c:754:iesys_cryptossl_pk_encrypt() ErrorCode (0x00070001) Could not create rsa key. ERROR:esys:src/tss2-esys/esys_iutil.c:521:iesys_compute_encrypted_salt() During encryption. ErrorCode (0x00070001) ERROR:esys:src/tss2-esys/api/Esys_StartAuthSession.c:226:Esys_StartAuthSession_Async() Error in parameter encryption. ErrorCode (0x00070001) ERROR:esys:src/tss2-esys/api/Esys_StartAuthSession.c:113:Esys_StartAuthSession() Error in async function ErrorCode (0x00070001) ERROR: Esys_StartAuthSession: esapi:Catch all for all errors not otherwise specified ERROR: Could not start Auth Session with the TPM. ERROR: Error unsealing wrapping key Login failed Login to token failed, returning NULL... PKCS11_get_private_key returned NULL Could not read private key from org.openssl.engine:pkcs11:pkcs11:manufacturer=STMicro;serial=0000000000000000;token=label;id=%38%32%33%66%63%62%33%30%65%63%64%32%32%64%39%32;type=private;pin-value=userpin 402C537C3B7F0000:error:03000096:digital envelope routines:fromdata_init:operation not supported for this keytype:crypto/evp/pmeth_gn.c:354: 402C537C3B7F0000:error:41800005:PKCS#11 module:ERR_CKR_error:General Error:p11_slot.c:260: 402C537C3B7F0000:error:13000080:engine routines:ENGINE_load_private_key:failed loading private key:crypto/engine/eng_pkey.c:79:

williamcroberts commented 2 years ago

Iv'e seen this before and I'm assuming you're on OpenSSL 3. In essence, you can't use the engine interface you have to use the provider interface and use the tpm2-openssl project under this org. Under the hood, the tpm2-tss uses of the EVP code fall back to the current loaded engine and that engine doesn't support that operation and you get this weird error.

I really need to document this, I thought I did but I didn't. So the fix here is to document:

  1. With openssl3 you have to use the provider
  2. How to use the provider to interact with tpm2-pkcs11 (note that tpm2_ptool has an export commandlet and those keys can be loaded with tpm2-openssl)
traxtopel commented 2 years ago

I have built installed on fedora tpm2-pkcs11 1.8.0 tpm2-pytss 1.1.0 tpm2-openssl 1.1.0 When you have time to write up the changes, I am more than willing to assist in testing them.

traxtopel commented 2 years ago

There is a post here, will give it a try on Fedora 36. https://bugs.launchpad.net/ubuntu/+source/tpm2-pkcs11/+bug/1964975 "When using tpm2-pkcs11, in the current Ubuntu version 1.7.0, creating of certificate signing requests (CSR) will not work correctly anymore which renders tpm2-pkcs11 partially useless. Specially enviroments where a TLS network (IEEE 802.1X) connection (over NetworkManager) or OpenConnect VPN is required tpm2-pkcs11 will not work with the current 1.7.0 version.

This is because of the shift to openssl3. Openssl is required to create the certificate signing requests while the method in tpm2-pkcs11 1.7.0 is using the deprecated "-engine" api, while openssl3 requires "-provider" to be used.

The old openssl1 command for 1.7.0:

openssl req \ -new \ -engine pkcs11 \ -keyform engine \ -key "pkcs11:token=$TOKEN_LABEL;object=$KEY_LABEL;type=private;pin-value=$USER_PIN" \ -subj "${SUBJ}" \ -out "$HOSTNAME".csr

The new openssl3 command for 1.8.0 (extracted, and tested as well, from tpm2-pkcs11 integration tests, because of lack of updated documentation):

yaml_rsa0=$(tpm2_ptool export --label="${TOKEN_LABEL}" --key-label="${KEY_LABEL}" --userpin="${USER_PIN}") auth_rsa0=$(echo "$yaml_rsa0" | grep "object-auth" | cut -d' ' -f2-) openssl req \ -new \ -provider tpm2 \ -provider base \ -key "${KEY_LABEL}".pem \ # created by the tpm2_ptool export above -passin "pass:$auth_rsa0" \ -subj "${SUBJ}" \ -out "$HOSTNAME".csr

Be aware that tpm2-openssl now a dependency for creating CSR's and tpm2-pytss is a dependency of tpm2-pkcs11."

williamcroberts commented 2 years ago

Yeah I reported that bug to get them to update. Before, CSR's we're generated using openssl + pkcs11 engine. However, the pkcs11 engine doesn't work right with openssl3 because we updated to the newer openssl3 apis. So now instead of 2 pieces to generate a CSR, you can just use tpm2-openssl and everything has a way to work together.

nwf-msr commented 2 years ago

I just encountered this and it's remarkably unfortunate that tpm2_ptool export from https://github.com/tpm2-software/tpm2-pkcs11/commit/042e56b004653101ea03264bde26068647ec655d did not make it into the 1.7 release, because that's what's being shipped in Debian and Ubuntu now, alongside their OpenSSL 3 packages. AFAICT the result is that as soon as the system is updated to OpenSSL 3, the keys managed in the tpm2_ptool database are not usable with openssl req. gnutls, on the other hand, with p11-kit, still can use them for the same tasks, just spelled using certtool instead; similarly, openssh is happy to use its PKCS#11 support (which is built atop OpenSSL). Ask me how long it took to figure all that out. :(

It looks like the tpm2-openssl replacement provider presently does not understand the sqlite database format that tpm2-pkcs11 does? Is the long-term intention that most software continues to use PKCS#11 for the low-level cryptographic operations but the OpenSSL provider for high-level commands?

williamcroberts commented 2 years ago

It looks like the tpm2-openssl replacement provider presently does not understand the sqlite database format that tpm2-pkcs11 does?

tpm2-openssl is the update to tpm2-tss-engine and uses the TSS2 PrivateKey PEM format. The simplest way for interoperability is to just export the key from tpm2-pkcs11 to the PrivateKey PEM format.

Is the long-term intention that most software continues to use PKCS#11 for the low-level cryptographic operations but the OpenSSL provider for high-level commands?

You can use either, some pieces of software support openssl providers, some don't and just support PKCS11. I would recommend using openssl provider tpm2-openssl unless you specifically need PKCS11 support. The provider is much more simple compared to the complexities of managing PKCS11 state and APIs.

Lasklu commented 1 year ago

Hi, I would like to completely rely on packages that are already built and available on apt. I have learnt that I can use tpm2-openssl for the openssl req command. But how can I get the private key? tpm2-pkcs11 is only available in version 1.7.0 on apt, so I cannot use the export command. Is there another way? Thank you very much!

williamcroberts commented 1 year ago

Hi, I would like to completely rely on packages that are already built and available on apt. I have learnt that I can use tpm2-openssl for the openssl req command. But how can I get the private key?

What do you mean "get the private key"? Are you looking for a PEM file you can pass into openssl commands with the TPM2 OpenSSL Engine or provider?

tpm2-pkcs11 is only available in version 1.7.0 on apt, so I cannot use the export command. Is there another way? Thank you very much!

Not simply, but you can go into the database and extract it. tpm2_ptool commandlet has support for getting the object id.

For example:

  1. Start by listing your primary objects

    tpm2_ptool listprimaries --path=$HOME/tmp
  2. List your tokens for a primary object

    tpm2_ptool listtokens --pid=1 --path=$HOME/tmp
    - id: 1
    label: label
    - id: 4
    label: empty-pin
  3. Step 3 list your objects in that token

    tpm2_ptool listobjects --label=label --path=$HOME/tmp
    - CKA_CLASS: CKO_PUBLIC_KEY
    CKA_ID:
    - '39333838633962643330363833346566'
    CKA_KEY_TYPE: CKK_RSA
    CKA_LABEL: rsa0
    id: 5
    - CKA_CLASS: CKO_PRIVATE_KEY
    CKA_ID:
    - '35363061653461363039363062333731'
    CKA_KEY_TYPE: CKK_RSA
    CKA_LABEL: rsa1
    id: 6
    ...
  4. Use objmod to dump the public and private TPM portions Public portion is keyed on: 2399141890 Private Portion is keyed on 2399141891

tpm2_ptool objmod --id=6 --key=2399141890 --path=$HOME/tmp | cut -d' ' -f2- | xxd -p -r > tpm.pub
tpm2_ptool objmod --id=6 --key=2399141891 --path=$HOME/tmp | cut -d' ' -f2- | xxd -p -r > tpm.priv
  1. Get the persistent handle for the primary object the token is under, mine is under primary one

    tpm2_ptool listprimaries --path=$HOME/tmp
    - config:
    esys-tr: 810000010022000bf740715848e7f7e50c414b339e1a2284f18e5fe852970caba6a168306f9707d300000001011a0001000b00030072000000060080004300100800000000000100add5fe747aec24b17fdcd7b3b0d34bb86a8ff390ddc62496dd2a20d71dabbcb05406190dd9af0f2a185a2c176245b24caa6e509ed289b0b10dde491026e58716d3a52b7142b3ed7075b595cb0e14536176f8ee639e76949f2110a4a1b8dd94ec9ca0c389edac3d3ef211381f34cce399c8dd2fbccc23e0feb4cc8772d5378981937bf81fadd9719175693e55976adc1de8c1707c39e4dc30d6059d6d28f9e4d81fa52e04f92a21093c0f548f171dbcef2c310d84baaa253d24488c79536205bde9428c9bebfb075e42729451a92305c7e4b1a8f6beeba86ed17ae04445314e21e6fc3b2b67ea40502ea896bac41524746d2426b1553fc492159240699d143ffb
    transient: false
    id: 1
  2. Make an ESYS_TR blob from the esys-tr field

    echo -n '810000010022000bf740715848e7f7e50c414b339e1a2284f18e5fe852970caba6a168306f9707d300000001011a0001000b00030072000000060080004300100800000000000100add5fe747aec24b17fdcd7b3b0d34bb86a8ff390ddc62496dd2a20d71dabbcb05406190dd9af0f2a185a2c176245b24caa6e509ed289b0b10dde491026e58716d3a52b7142b3ed7075b595cb0e14536176f8ee639e76949f2110a4a1b8dd94ec9ca0c389edac3d3ef211381f34cce399c8dd2fbccc23e0feb4cc8772d5378981937bf81fadd9719175693e55976adc1de8c1707c39e4dc30d6059d6d28f9e4d81fa52e04f92a21093c0f548f171dbcef2c310d84baaa253d24488c79536205bde9428c9bebfb075e42729451a92305c7e4b1a8f6beeba86ed17ae04445314e21e6fc3b2b67ea40502ea896bac41524746d2426b1553fc492159240699d143ffb
    ' | xxd -r -p > primary.tr
  3. The first 4 bytes, 8 hex characters, are the persistent handle 81000001

  4. Verify the name is same as esys tr blob:

    
    tpm2_readpublic -c 0x81000001 | grep '^name: '
    name: 000bf740715848e7f7e50c414b339e1a2284f18e5fe852970caba6a168306f9707d3

tpm2_readpublic -c primary.tr | grep '^name: ' name: 000bf740715848e7f7e50c414b339e1a2284f18e5fe852970caba6a168306f9707d3


9. Encode the object as a PEM file
```bash
tpm2_encodeobject -C 0x81000001 -u tpm.pub -r tpm.priv -o tpm.pem
  1. Now you need to get the password:
    tpm2_ptool verify --label=label --userpin=myuserpin --path=$HOME/tmp
    - auth: 342c915e8ed29c72576a4dd7b035c3af
    encauth: 62e050988d624249fbb6bb24:e11b74d424e946cac1201130b1419480:6db20b04a57563df4cd10ecfe992789971ec5ae95566e2fd58e728c9e85d77f8
    id: 6
  2. Primary Object Password. You're primary object may have a password on it.
    sqlite3 ~/tmp/tpm2_pkcs11.sqlite3 'SELECT objauth FROM pobjects WHERE id=1;'
    mypobjpin

    Now you know the primary object password, the object (key) password and you can do with the pem file or the blobs as you wish. For example:

    
    tpm2_load -C primary.tr -P mypobjpin -u tpm.pub -r tpm.priv -c key.ctx
    name: 000baafa321768d2961836eba5944c6a238976357545d22b3b1c9348ce2e64f145c5

tpm2_sign -c key.ctx -p 342c915e8ed29c72576a4dd7b035c3af ~/.bashrc -f plain -o signature.dat

Lasklu commented 1 year ago

Hi, thanks for your explanation!

What do you mean "get the private key"? Are you looking for a PEM file you can pass into openssl commands with the TPM2 OpenSSL Engine or provider?

Yes. So, my goal is to create a CSR using openssl req and tpm2. As described, I need to rely for this on official package sources without building the packages manually. As I can only use openssl3, I figured out that I need to use the "new" req-command from openssl with -provider and specifying the place of the pem file with -key. However, when using apt, the latest installable version of tpm2-pkcs11 is 1.7.0. So I cannot use its export-possibility to get the pem-file. Therefore, I was looking for a different way to get the pem-file, in order to create the CSR. Does the solution you described works for this use case? Or is there maybe a completely different solution out there? :)

I'm relatively new to this field, so thanks for your help!

williamcroberts commented 1 year ago

Hi, thanks for your explanation!

What do you mean "get the private key"? Are you looking for a PEM file you can pass into openssl commands with the TPM2 OpenSSL Engine or provider?

Yes. So, my goal is to create a CSR using openssl req and tpm2. As described, I need to rely for this on official package sources without building the packages manually. As I can only use openssl3, I figured out that I need to use the "new" req-command from openssl with -provider and specifying the place of the pem file with -key. However, when using apt, the latest installable version of tpm2-pkcs11 is 1.7.0. So I cannot use its export-possibility to get the pem-file. Therefore, I was looking for a different way to get the pem-file, in order to create the CSR. Does the solution you described works for this use case? Or is there maybe a completely different solution out there? :)

No thats the painful way of doing it by hand without the export feature being available.

The other option is to use pkcs11 engine for libp11 project. Engines still work within OpenSSL IIUC, they're just deprecated. But IIRC, I had issues using pkcs11 engine in openssl3, so your mileage may vary.

I'm relatively new to this field, so thanks for your help!

Luk164 commented 1 year ago

@williamcroberts Hi, I seem to have a problem very similar to what @Lasklu described, with the same limitations as well (would highly prefer to use apt packages only). I was trying to follow your conversation to find a solution, but I am getting lost.

What I would like to achieve is simmilar to Lasklus use case as well. I want to generate a keypair and then from it a CSR request. The major thing is that I want the private key to be unexportable, so that any communication signed by it is guaranteed to originate from that specific device. After that I would like SSH and OpenVPN to use the said key to sign all traffic. I am also new to all this so if possible a detailed explanation would be much appreciated.

williamcroberts commented 1 year ago

@williamcroberts Hi, I seem to have a problem very similar to what @Lasklu described, with the same limitations as well (would highly prefer to use apt packages only). I was trying to follow your conversation to find a solution, but I am getting lost.

What I would like to achieve is simmilar to Lasklus use case as well. I want to generate a keypair and then from it a CSR request. The major thing is that I want the private key to be unexportable, so that any communication signed by it is guaranteed to originate from that specific device. After that I would like SSH and OpenVPN to use the said key to sign all traffic. I am also new to all this so if possible a detailed explanation would be much appreciated.

This is the detailed explanation which is pretty much step by step:

SherZCHR commented 8 months ago

Hi, I'm trying to get my csr by tpm2_tools. I don't know why but I don't have the command : tpm2_encodeobject or tpm2_ptool export. I tried to initialize / build / using the git repository and with the package on my Ubuntu 22.04 LTS, but any of it have those commands. Can you explain why I haven't those command ? it's very annoying because I'm trying to export a .csr in order to use the tpm service ... Regards,