opendnssec / SoftHSMv2

SoftHSM version 2
http://www.softhsm.org/
Other
766 stars 338 forks source link

Curl using ECC key and SoftHSM PKCS11 engine #670

Open pm1992 opened 2 years ago

pm1992 commented 2 years ago

I am trying to use SoftHSMv2 and curl to make a request with an ECC Key. Originally I was having this issue with OP-TEE's pkcs11 engine, but now I see the issue here.

SoftHSM 2.6.1 OpenSSL 1.1.1 curl 7.81.0

I have an existing EC prime256v1 private key and an x509 certificate. I can import these to secure storage with pkcs11-tool, but Curl cant read the private key. Curl always returns

curl: (58) unable to set private key .

As a test, I made an RSA key pair externally, then created a x509 certificate with that. I imported the certificate and RSA private key to SoftHSMv2 PKCS11 storage

Certificate Object; type = X.509 cert
  label:      importkey
  ID:         88
Private Key Object; RSA
  label:      importkey
  ID:         99
  Usage:      decrypt, sign, unwrap

I then run this curl command with the pkcs11 engine curl --engine pkcs11 -E 'pkcs11:token=TEST;id=%88' --key 'pkcs11:token=TEST;id=%99;pin-value=1234567890' -k "mywebsite.com" --trace –

This works and I get a response from my website.

But when I do the above steps with an ECC key, Curl always gives me this error.

curl: (58) unable to set private key.

Both the EC key and certificate imported fine in secure storage. And the builtin --keypairgen --key-type EC:prime256v1 works also.

Certificate Object; type = X.509 cert
  label:      eccert.crt
  ID:         81
Private Key Object; EC
  label:      eccert.key
  ID:         80
  Usage:      decrypt, sign, unwrap

Upon googling, someone said this is related to a cert/key mismatch, But that’s not the case. If I run

openssl x509 -pubkey -in eccert.crt -noout | openssl md5 openssl pkey -pubout -in eccert.key | openssl md5

Both hashes are the same.

I regenerated an EC prime256v1 key in case my existing ones weren't compatible.

openssl req -new -x509 -nodes -newkey ec:<(openssl ecparam -name prime256v1) -keyout eccert.key -out eccert.crt -days 365

But I still get the same curl: (58) error as before.

Does the private key have to be in a special format for curl to be read from secure storage?

stuomas commented 6 days ago

Hi, did you ever get any clarity to your issue? I'm facing an "unable to set private key" issue with (py)curl + SoftHSM2 too, but little different.

I have keypair1 stored in softhsm and making a request with that works as expected (using tornado.curl_httpclient).

But if I generate a new EC keypair keypair2 in the same token (using python-pkcs11), the same curl request fails to get the private key of the original keypair1 and I get an error tornado.curl_httpclient.CurlError: HTTP 599: unable to set private key. So somehow generating a new keypair affects whether I can access the old keypair or not.

I have not faced this issue in OP-TEE, so I'm leaning towards suspecting SoftHSM2. I welcome any advice on the issue!

dengert commented 5 days ago

To address the original problem, PKCS11 expects the CK_ID of a certificate, public key and private key to be the same. If you need to authenticate with one key and encrypt with another then the would have different IDs and different certs.

To help with the problem, you could use the OpenSC opensc-spy to log the PKCS11 calls and responses. See https://github.com/OpenSC/OpenSC/wiki/Using-OpenSC

ECC keys do not encrypt/decrypt, but can be used for key derivation so one of the parties may not support this. Also key usage in the certificates need to be correct too. See: https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/pkcs11-base-v3.0.pdf https://docs.oasis-open.org/pkcs11/pkcs11-curr/v3.0/pkcs11-curr-v3.0.pdf

stuomas commented 4 days ago

Thank you @dengert, the ID seemed to be the issue at least in my case. I had created two keypairs in the test suite without setting their IDs (all keys had blank ID) and thought label is enough to differentiate them, but apparently curl didn't agree. Sorry for suspecting SoftHSM2! (I didn't face the issue in OP-TEE because there one of the real keys had ID...)