[PKI/CA] Nitrokey HSM Does Not Support Signing?

Hello,

I just got a Nitrokey HSM 2, and I’m trying to use it to build an internal PKI infrastructure. I have generated a root CA certificate on the HSM, and generated the intermediate CA on the HSM, I also generated a CSR from the intermediate certificate onto my computer. My next objective is to sign the intermediate CA with the root certificate. I’ve tried running variations on the following commands:

openssl ca -config ../ca.ini -engine pkcs11 -keyform engine -key b842f3b4f356373056fc6ec71318404b541498c4 -extensions v3_intermediate_ca -days 1963 -notext -md sha512 -in csr/intermediate.csr -out certs/intermediate.crt
openssl ca -config ../ca.ini -engine pkcs11 -keyform engine -key 'pkcs11:object=root;type=private?pin-source=builtin-dialog' -extensions v3_intermediate_ca -days 1963 -notext -md sha512 -in csr/intermediate.csr -out certs/intermediate.crt

In both cases, and in other variations of the above, I get the following error:

engine "pkcs11" set.
Using configuration from ../ca.ini
Format not recognized!
The key ID is not a valid PKCS#11 URI
The PKCS#11 URI format is defined by RFC7512
The legacy ENGINE_pkcs11 ID format is also still accepted for now
Format not recognized!
The key ID is not a valid PKCS#11 URI
The PKCS#11 URI format is defined by RFC7512
The legacy ENGINE_pkcs11 ID format is also still accepted for now
PKCS11_get_private_key returned NULL
cannot load CA private key from engine
139786102428992:error:80065064:pkcs11 engine:ctx_load_key:invalid id:eng_back.c:659:
139786102428992:error:26096080:engine routines:ENGINE_load_private_key:failed loading private key:crypto/engine/eng_pkey.c:77:
unable to load CA private key

I’m not sure why I’m getting that error, except that when I run the following command, I get a message that reading the private key is not supported.

$ pkcs11-tool -l --read-object --type privkey --label rootUsing slot 0 with a present token (0x0)
Logging in to "SmartCard-HSM (UserPIN)".
Please enter User PIN: 
sorry, reading private keys not (yet) supported

Is signing from HSM generated private keys supported on the Nitrokey HSM 2?

Thank you!

Hi!

The cited error says, that OpenSC cannot get the proper key handle to the key.

  1. Have you tried specifying the slot ID, under which the key was stored instead of the URI? E.g. a number from range 1-15? As far as I see you do not use any label for the key to identify in the URI as well - maybe that’s the cause. Something like:
    ca -engine pkcs11 -keyfile "15" -keyform engine -config ./openssl-rootca.conf 
    
    (from https://github.com/sektioneins/micro-ca-tool/blob/master/micro-ca-tool#L507)
  2. See examples of the PKCS#11 URIs:
  3. Perhaps any of these tools/guides would help:

Have you tried specifying the slot ID?

Yes, you can see the slot ID here:

$ pkcs11-tool -O
Using slot 0 with a present token (0x0)
Public Key Object; EC  EC_POINT 384 bits
  EC_POINT:   04610461695d48f7b6a19059f6929445ad99b5e74b25c2cd8b944827531acbe582bf29531faca7cf92da25fd0d91656e25d87eed940a04d7e4f98006f38e3b09a25ae51423224af1ce599d33fd0d7480a50f0e6e02b3242f9822076104d5483349b6c4
  EC_PARAMS:  06052b81040022
  label:      root
  ID:         b842f3b4f356373056fc6ec71318404b541498c4
  Usage:      verify
  Access:     none

Thus, I try to sign the key using that ID and I get the error as shown above:

openssl ca -config ../ca.ini -engine pkcs11 -keyform engine -key b842f3b4f356373056fc6ec71318404b541498c4 -extensions v3_intermediate_ca -days 1963 -notext -md sha512 -in csr/intermediate.csr -out certs/intermediate.crt

and also:

openssl ca -config ../ca.ini -engine pkcs11 -keyform engine -key 0:b842f3b4f356373056fc6ec71318404b541498c4 -extensions v3_intermediate_ca -days 1963 -notext -md sha512 -in csr/intermediate.csr -out certs/intermediate.crt`

(edit by @szszszsz: difference in the --key switch parameter).
I found this page to have the best description for a PCKS11 URI format. Therefore, I tried several permutations on the PKCS11 URI scheme. Here are some that I’ve tried:

'pkcs11:type=private;object=b842f3b4f356373056fc6ec71318404b541498c4'
'pkcs11:type=private;object=root'
'pkcs11:type=private;token=SmartCard-HSM%20%28UserPIN%29;object=root'
'pkcs11:type=private;token=SmartCard-HSM%20%28UserPIN%29;object=b842f3b4f356373056fc6ec71318404b541498c4'
'pkcs11:object=root;type=private?pin-source=file:///pin'
'pkcs11:object=root;type=private?pin-source=builtin-dialog'
'pkcs11:id=b842f3b4f356373056fc6ec71318404b541498c4;type=private?pin-source=builtin-dialog'

All of those appear to valid URIs according to that page I linked, but I get URI format errors all the same.

I found out that ‘p11tool’ will show you the proper format for the PKCS11 URI, so I copied that, and it’s still not working. I’m still getting the following error message:

PKCS11_get_private_key returned NULL
cannot load CA private key from engine

Is that because I can’t get the private key?

$ pkcs11-tool -l --read-object --type privkey --label root
Using slot 0 with a present token (0x0)
Logging in to "SmartCard-HSM (UserPIN)".
Please enter User PIN: 
sorry, reading private keys not (yet) supported

The message is about reading the private key in a raw format from the device. Nitrokey HSM does not allow to do so, unless in encrypted form using DKEK, hence the error (this is expected).

  1. Could you run signing using OpenSC (e.g. with pkcs11-tool) to confirm the key is correctly written to the device and usable?
  2. I saw in the micro-ca-tool, that they use OpenSSL shell/REPL instead of command switch to set the environment. Could you do the same?
  3. I see you are using -key switch in the OpenSSL call. Should not that be -keyfile (as in micro-ca-tool#L507)?

Figured it out!

My ca.ini file needed to be updated. Instead of using the -key field, I needed to reference the smartcard in the ini file:

private_key       = pkcs11:model=PKCS%2315%20emulated;manufacturer=www.CardContact.de;serial=DENK0104068;token=SmartCard-HSM%20%28UserPIN%29%00%00%00%00%00%00%00%00%00;id=%88%D5%BF%49%14%CD%B1%3C%7B%AD%73%D8%05%77%96%0D%5F%93%41%EC;object=root;type=private
certificate       = root.crt

Remove the -key <key_id> from the command:

openssl ca -config create_root.ini -engine pkcs11 -keyform engine -extensions v3_intermediate_ca -days 1963 -notext -md sha512 -in intermediate.csr -out intermediate.crt

Then, you are correctly prompted to enter your pin and have your certificate signed.

engine "pkcs11" set.
Using configuration from create_root.ini
Enter PKCS#11 token PIN for SmartCard-HSM (UserPIN):
Check that the request matches the signature
Signature ok
Certificate Details:
...

Thanks for your help!

1 Like

Hey,
I have been trying to do this for a while. Could you post a copy of your ca.ini file?

The process looks more intimidating than it actually is. I put it up on Github.

2 Likes

Nice tutorial. Thank you! Can we copy (and modify) your tutorial to our documentation?

I ran through the tutorial again this morning to make sure that I couldn’t find any problems, and everything works exactly as expected. So, feel free to use and change it in any way that you want!

Thank you! I copied and published the document with some minor text modifications.