1

I've created an RSA private key in SoftHSM 2 via EJBCA with the following config:

attributes(*, CKO_PUBLIC_KEY, *) = {
  CKA_TOKEN = false
  CKA_ENCRYPT = true
  CKA_VERIFY = true
  CKA_WRAP = false
}

attributes(*, CKO_PRIVATE_KEY, *) = {
  CKA_TOKEN = true
  CKA_PRIVATE = true
  CKA_SENSITIVE = false
  CKA_EXTRACTABLE = true
  CKA_DECRYPT = false
  CKA_SIGN = true
  CKA_UNWRAP = true
  CKA_DERIVE = false
}

In PKCS#11 spec v2.20:

If the CKA_SENSITIVE attribute is CK_TRUE, or if the CKA_EXTRACTABLE attribute is CK_FALSE, then certain attributesof the secret key cannot be revealed in plaintext outside the token. Which attributes these are is specified for each type of secret key in the attribute table in the section describing that type of key

So I thought that if I set CKA_SENSITIVE to False and CKA_EXTRACTABLE to true I'll be able to extract the key.

I've tried to export the key using pkcs11-tool, but it did not work for me:

$ pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so -r -y privkey -d OBJECT_ID --pin PIN
Using slot 0 with a present token (0x2ed1a744)
sorry, reading private keys not (yet) supported

I've also tried to use this tool, but it did not work neither (CKR_MECHANISM_INVALID):

# ./pkcs-11-key-extractor-1.0/bin/pkcs-11-key-extractor -l /usr/lib/softhsm/libsofthsm2.so -s 785491780 -p 1234
[*] PKCS#11 Key Extractor - Release 1.0
[*] Registering PKCS#11 Module '/usr/lib/softhsm/libsofthsm2.so'
[*] Opening session on slot '785491780'
[*] Found 1 RSA private key(s) with CKA_EXTRACTABLE set to TRUE
[*] Generating an in memory (CKA_TOKEN: FALSE) 256 bits AES key
[*] Extracting RSA Private Key (CKA_EXTRACTABLE: true) with modulus 'E9:F3:44:CE:9B:90:32:83:69:7E:80:5E:48:A0:9E:00:7A:71:AD:84:6B:CD:DE:AE:10:16:AA:91:61:66:B4:57:EB:9B:9E:A0:51:D4:C6:2C:33:59:A8:7B:F4:44:4A:9B:39:28:44:69:08:58:38:DF:7C:D2:25:2F:29:9C:BD:C7:EE:60:00:DE:77:72:70:CA:7C:A2:38:D1:4C:49:CF:99:1D:7D:2E:DC:62:C1:27:5E:2C:3F:AD:25:D7:36:35:08:77:DE:56:58:8F:E1:AF:D3:C2:8E:B7:7E:D3:E9:80:77:B1:91:77:BE:D1:54:0C:E8:19:97:AD:39:48:4F:51:00:F1:43:8D:41:97:E3:F6:B8:79:18:82:A7:60:C7:6E:AF:D3:27:B5:00:19:CD:0D:40:14:11:47:38:2D:FE:DD:14:2F:B9:1A:3B:2C:FE:B0:52:FC:7E:30:13:1E:6F:41:30:B6:1A:F5:B2:17:62:19:EE:90:B1:8A:79:DA:70:E7:A5:7A:E1:54:86:86:69:A3:A1:8E:AD:12:0F:D0:28:16:0A:43:75:3B:69:46:10:DE:13:D3:F0:6C:57:F6:91:A4:72:14:04:9B:BD:72:82:B7:33:C3:57:55:18:F3:8F:54:3F:A7:80:9D:3E:67:EB:46:94:FD:F4:9F:AA:C7:D7:41:29:AC:0F:C8:2E:DF:C5:8D:D9:A2:77:13:BD:90:5D:D4:CD:05:7E:DA:85:58:F6:4B:62:E6:3E:0C:6C:E6:5F:5F:1D:C0:0C:FA:2C:CB:F4:FD:E7:08:32:DA:9D:EC:BB:1B:C9:56:45:91:C1:41:64:47:02:9F:AE:1F:B8:B1:84:DA:5F:F3:86:6E:6A:F1:06:84:CA:98:1D:F0:B0:F3:73:67:37:36:1D:C8:0E:26:DF:67:5D:DA:70:62:23:AD:22:6B:47:6B:33:BC:D8:41:7E:EA:28:09:EF:8D:12:D3:26:2D:DF:2F:03:75:1B:CE:DF:D4:95:62:DB:39:0A:72:46:4A:79:98:86:0E:E6:82:95:60:4D:FD:0F:16:4A:F8:D1:71:5B:39:5A:A4:D1:1A:52:06:89:C0:B8:6E:1B:B7:D3:27:5D:5D:AF:2E:94:82:D5:F5:12:32:AB:5F:70:20:29:65:56:73:04:EA:2E:F8:73:DF:BF:EC:CC:3C:22:8E:CA:42:90:E1:C5:08:9A:15:AA:45:2D:61:6E:A5:05:7E:9D:4C:C1:5D:73:79:2F:43:71:AA:E2:25:AB:D5:9E:D6:9B:19:D0:D6:80:B0:CF:F3:DE:08:12:53:72:46:CE:F4:40:65:F2:D4:3D:7E:33:A6:30:B7:3F:5B:34:C9:0F:20:6B:DD:9B'
[!] Error extracting private key: 'CKR_MECHANISM_INVALID'
[*] Closing session on slot '785491780'
[*] Unregistering PKCS#11 Module '/usr/lib/softhsm/libsofthsm2.so'

I know it's against the point of having an HSM, but I want to investigate it nevertheless.

Does anyone have an Idea/resources on how to do it ?

If it not possible, I read that a secure alternative would be wrapping the key with a secret key that stays inside the HSM, can someone share any resources on how to do it ? is it possible to do it with openssl and pkcs11-tool ?

No name
  • 93
  • 7

2 Answers2

3

First of all, the template you are using in EJBCA is kind of strange. I assume that this template is used to generate a key pair for a Certificate Authority.

attributes(*, CKO_PUBLIC_KEY, *) = {
  CKA_TOKEN = false ==> The public key will be generated on the HSM not be stored in the HSM (lost once the session is closed)
  CKA_ENCRYPT = true . ==> The public key is usable to encrypt (not necessary for a CA)
  CKA_VERIFY = true ==> The public key can be used to verify signature (which is required for a CA)
  CKA_WRAP = false . => The public key cannot be sued to wrap another key (also normal)
}
attributes(*, CKO_PRIVATE_KEY, *) = {
  CKA_TOKEN = true ==> The private key will be stored on the HSM
  CKA_PRIVATE = true ==> This is a private key
  CKA_SENSITIVE = false ==> This means that the object is readable from the HSM if you have the associated PIN. This would be insane for private key of a Certificate Authority
  CKA_EXTRACTABLE = true ==> The key can be extracted but it must be wrapped with another key
  CKA_DECRYPT = false ==> The key cannot be use to decrypt data
  CKA_SIGN = true ==> The key can be use to sign data (required for a CA)
  CKA_UNWRAP = true ==> the key cannot be used to wrap another one
  CKA_DERIVE = false  ==> the key cannot be used to perform derivation
}

With such a template, you should be able to read all the PKCS#11 of the private key (CKA_SENSITIVE is set to false) directly using PKCS#11, no need to use our key extraction tool which should also work as the attribue CKA_EXTRACTABLE is set to true.

Here is what the tool does:

  • Step 1: Generating a non persistent AES key in the HSM
  • Step 2: Wrap any private key with the CKA_EXTRACTABLE attribute with the key generated step 1
  • Step 3: Unwrap the keys wrapped during step 2 with the key generated step 1.

The fact that you are getting a CKR_MECHANISM_INVALID error mainly mean that SoftHSMv2 does not support the wrapping mechanism the tool is program to use.

When I developed this tool, I tested it on a Atos Proteccio HSM.

It seems that it is not working on a SoftHSMv2.

Here is the output I get using test mode:

./pkcs-11-key-extractor -l /usr/local/lib/softhsm/libsofthsm2.so -s 1598976893 -p 1234 -t                             pantin@pantinmbp
[*] PKCS#11 Key Extractor - Release 1.0
[*] Registering PKCS#11 Module '/usr/local/lib/softhsm/libsofthsm2.so'
[*] Opening session on slot '1598976893'
[*] Generating Test RSA key pair (CKA_EXTRACTABLE: TRUE, CKA_WRAP: FALSE, CKA_UNWRAP: FALSE)
[*] Generating Test RSA key pair (CKA_EXTRACTABLE: TRUE, CKA_WRAP: FALSE, CKA_UNWRAP: TRUE)
[*] Generating Test RSA key pair (CKA_EXTRACTABLE: TRUE, CKA_WRAP: TRUE, CKA_UNWRAP: FALSE)
[*] Generating Test RSA key pair (CKA_EXTRACTABLE: TRUE, CKA_WRAP: TRUE, CKA_UNWRAP: TRUE)
[*] Generating Test RSA key pair (CKA_EXTRACTABLE: FALSE, CKA_WRAP: FALSE, CKA_UNWRAP: FALSE)
[*] Generating Test RSA key pair (CKA_EXTRACTABLE: FALSE, CKA_WRAP: FALSE, CKA_UNWRAP: TRUE)
[*] Generating Test RSA key pair (CKA_EXTRACTABLE: FALSE, CKA_WRAP: TRUE, CKA_UNWRAP: FALSE)
[*] Generating Test RSA key pair (CKA_EXTRACTABLE: FALSE, CKA_WRAP: TRUE, CKA_UNWRAP: TRUE)
[*] Found 4 RSA private key(s) with CKA_EXTRACTABLE set to TRUE
[*] Generating an in memory (CKA_TOKEN: FALSE) 256 bits AES key
[*] Extracting RSA Private Key (CKA_EXTRACTABLE: true) with modulus '9D:89:CF:B3:32:B3:8E:50:31:32:33:2C:BC:2C:77:8A:8B:87:70:2C:85:3F:80:0B:32:2A:AB:26:20:52:F8:0F:BB:63:88:14:7C:E0:52:C3:46:BA:80:AA:56:29:06:48:D3:3A:4C:13:5E:FC:D2:93:FF:3E:DD:BC:3A:E7:75:0A:10:C4:AF:B4:29:31:85:11:03:73:EF:52:08:3D:AC:CC:81:5F:C9:77:23:68:6D:68:BC:5D:79:7A:F1:78:DA:AB:7B:50:35:EE:70:DF:E9:37:27:D1:C9:48:ED:03:B0:25:05:01:B0:EE:79:E9:63:6C:64:66:A8:4E:8A:EE:A3:E4:8B:1B:D4:63:17:8E:E9:65:B8:B9:2E:7A:76:2E:51:CF:9D:5E:CB:9D:BA:DD:3B:1D:DB:30:A9:A8:40:BE:F2:58:46:EE:9F:D2:D8:12:95:40:88:B8:D6:73:64:17:60:74:22:33:DB:18:15:6C:00:E0:B7:EB:DA:FC:F8:2F:95:A6:DE:D8:91:6D:67:51:5E:67:FB:DD:C8:4A:0F:3A:B8:BA:07:E5:B4:F1:69:E9:A9:8E:E5:98:97:69:05:D4:63:75:2D:52:DA:FF:EF:3A:DC:63:4F:A6:59:18:1D:87:E3:39:7B:3B:55:5A:D3:8E:26:5D:A9:62:72:2E:7C:A7:A2:91'
[!] Error extracting private key: 'CKR_MECHANISM_INVALID'
[*] Extracting RSA Private Key (CKA_EXTRACTABLE: true) with modulus 'B7:3E:DA:3C:0C:40:A8:59:D5:FB:30:A9:25:6E:14:55:48:BD:7A:82:85:3E:CE:51:DF:A0:7F:9E:95:98:39:5B:CB:1E:6B:92:F4:C9:39:0D:E9:6C:53:B0:DE:C8:2B:19:37:F6:21:F1:90:14:24:E0:B0:32:FB:F6:7D:31:C1:EF:CD:11:1C:4D:5F:CA:90:67:2C:EB:BA:A8:25:8F:D3:DF:9F:0A:4C:F9:30:94:AA:05:9C:E1:5E:28:D2:F6:95:9E:5D:88:6E:D1:81:7D:C2:50:A3:45:F4:1D:E3:6F:22:55:C3:34:83:DA:9D:15:36:B9:B3:8C:8D:AC:1C:B4:29:62:51:15:30:97:62:E5:CE:42:AB:FB:A5:72:F6:77:50:A0:65:0C:AC:7F:3D:70:1C:F5:F0:76:21:AF:2F:B5:5D:63:1E:7D:2D:24:9C:D5:A3:24:20:64:0B:29:82:96:65:79:04:75:C3:6B:02:01:8D:4E:5D:C2:BF:8F:E6:D0:FA:7B:D0:34:59:D5:E5:77:4E:7F:01:FC:D1:2B:48:A7:3B:DB:6C:9A:45:CE:44:1A:FB:88:A3:34:4D:13:F2:8B:14:9A:11:5E:FF:1C:1C:E9:F7:95:46:AE:C0:4E:7F:8A:04:68:4F:23:8A:83:8D:81:6A:11:C6:C4:2A:36:EB:3A:4D:47'
[!] Error extracting private key: 'CKR_MECHANISM_INVALID'
[*] Extracting RSA Private Key (CKA_EXTRACTABLE: true) with modulus 'D4:11:96:CA:68:CE:A0:A2:0E:E7:B6:91:28:33:10:E2:21:A2:27:80:46:50:13:44:8B:27:56:D9:41:95:48:7B:14:F7:18:4A:AA:03:3C:79:DF:C6:11:84:CB:30:EC:5D:B0:20:A1:35:57:0D:6F:4A:21:29:77:23:94:51:B2:52:B7:1D:E8:04:68:5A:B9:1C:6C:B3:57:27:84:8E:A9:37:BC:9D:0F:D3:3E:DE:68:9C:14:29:55:F8:19:E4:9F:77:57:AD:E3:3D:69:64:1B:00:1D:25:9F:1F:58:C7:48:62:62:F8:D9:B8:48:96:F1:76:71:CB:FA:A9:95:4C:EA:D5:57:48:8A:56:EE:B8:9E:35:82:00:2C:49:6B:10:9E:FA:66:94:DE:46:E6:DC:BC:6E:6A:52:CC:70:FE:ED:E7:AC:A7:6E:54:07:65:F7:9F:92:C9:30:3A:57:F4:AE:91:5D:3F:D9:53:93:5B:D0:CB:A8:D7:73:C7:2A:92:63:54:26:1A:AB:BE:C5:F6:9F:EE:EC:21:16:90:DF:DC:45:39:7D:6E:C7:83:0A:A7:74:33:34:B3:9C:7F:82:74:5C:13:A7:83:1D:28:6D:57:11:51:5F:D7:09:59:7B:7B:2A:E2:DD:84:A8:66:B5:1A:50:9F:91:BF:FE:23:94:29:BF:05:0D'
[!] Error extracting private key: 'CKR_MECHANISM_INVALID'
[*] Extracting RSA Private Key (CKA_EXTRACTABLE: true) with modulus 'AD:C9:0B:06:53:6B:D3:47:F2:C2:16:F6:48:85:31:7F:FD:B4:2B:F0:E2:73:87:0B:FE:34:59:75:8A:A6:95:E1:16:B7:A7:B3:75:B2:E5:69:AE:5F:47:5D:56:D7:3F:2D:14:1B:46:C1:5E:5A:ED:FD:28:6F:76:EF:4E:16:FC:CD:35:54:A2:36:52:89:80:DA:87:55:AF:BF:69:FA:FC:2C:0F:99:8C:27:DF:32:96:72:EC:AA:A3:72:9E:78:05:99:68:D5:18:70:15:C0:18:F1:C0:1E:4A:E6:BF:93:C3:12:D1:80:6F:71:1E:66:EB:39:DD:56:1B:A1:08:2B:66:6D:40:67:EF:16:15:1F:14:73:C6:66:20:46:11:57:AC:15:4F:45:FE:89:83:A3:B0:7D:5B:2E:4D:5F:8C:1F:7B:D3:5E:85:F3:61:0A:AD:86:B2:2E:03:AA:2D:6A:CC:39:7B:3E:0E:65:85:6B:8D:5B:71:F8:5C:D7:A0:C5:8B:E2:B5:9A:B4:0C:C6:C1:C1:ED:D5:D0:00:53:E3:08:41:B0:6F:1D:62:66:11:FD:C4:63:2C:B0:CC:EB:24:9B:AD:C5:2D:5E:4C:E1:C4:4B:F8:9C:31:A3:D0:B3:C6:9B:BA:2A:2B:7B:5F:35:4E:CA:3B:DB:9E:F2:90:A7:6B:C0:DF:7C:3B'
[!] Error extracting private key: 'CKR_MECHANISM_INVALID'
[*] Closing session on slot '1598976893'
[*] Unregistering PKCS#11 Module '/usr/local/lib/softhsm/libsofthsm2.so'

If you look at the code of the tool, you will see that the key is wrapped using the 'CKM_AES_CBC_PAD' mechanism.

If you list the mechanisms supported by SoftHSMv2:

pkcs11-tool --module /usr/local/lib/softhsm/libsofthsm2.so -M                                                         pantin@pantinmbp
Using slot 0 with a present token (0x5f4e737d)
Supported mechanisms:
  MD5, digest
  SHA-1, digest
  SHA224, digest
  SHA256, digest
  SHA384, digest
  SHA512, digest
  MD5-HMAC, keySize={16,512}, sign, verify
  SHA-1-HMAC, keySize={20,512}, sign, verify
  SHA224-HMAC, keySize={28,512}, sign, verify
  SHA256-HMAC, keySize={32,512}, sign, verify
  SHA384-HMAC, keySize={48,512}, sign, verify
  SHA512-HMAC, keySize={64,512}, sign, verify
  RSA-PKCS-KEY-PAIR-GEN, keySize={512,16384}, generate_key_pair
  RSA-PKCS, keySize={512,16384}, encrypt, decrypt, sign, verify, wrap, unwrap
  RSA-X-509, keySize={512,16384}, encrypt, decrypt, sign, verify
  MD5-RSA-PKCS, keySize={512,16384}, sign, verify
  SHA1-RSA-PKCS, keySize={512,16384}, sign, verify
  RSA-PKCS-OAEP, keySize={512,16384}, encrypt, decrypt, wrap, unwrap
  SHA224-RSA-PKCS, keySize={512,16384}, sign, verify
  SHA256-RSA-PKCS, keySize={512,16384}, sign, verify
  SHA384-RSA-PKCS, keySize={512,16384}, sign, verify
  SHA512-RSA-PKCS, keySize={512,16384}, sign, verify
  RSA-PKCS-PSS, keySize={512,16384}, sign, verify
  SHA1-RSA-PKCS-PSS, keySize={512,16384}, sign, verify
  SHA224-RSA-PKCS-PSS, keySize={512,16384}, sign, verify
  SHA256-RSA-PKCS-PSS, keySize={512,16384}, sign, verify
  SHA384-RSA-PKCS-PSS, keySize={512,16384}, sign, verify
  SHA512-RSA-PKCS-PSS, keySize={512,16384}, sign, verify
  GENERIC-SECRET-KEY-GEN, keySize={1,2147483648}, generate
  DES-KEY-GEN, generate
  DES2-KEY-GEN, generate
  DES3-KEY-GEN, generate
  DES-ECB, encrypt, decrypt
  DES-CBC, encrypt, decrypt
  DES-CBC-PAD, encrypt, decrypt
  mechtype-0x1100, derive
  mechtype-0x1101, derive
  DES3-ECB, encrypt, decrypt
  DES3-CBC, encrypt, decrypt
  DES3-CBC-PAD, encrypt, decrypt
  mechtype-0x1102, derive
  mechtype-0x1103, derive
  mechtype-0x138, sign, verify
  AES-KEY-GEN, keySize={16,32}, generate
  AES-ECB, keySize={16,32}, encrypt, decrypt
  AES-CBC, keySize={16,32}, encrypt, decrypt
  AES-CBC-PAD, keySize={16,32}, encrypt, decrypt
  mechtype-0x1086, keySize={16,32}, encrypt, decrypt
  mechtype-0x1087, keySize={16,32}, encrypt, decrypt
  mechtype-0x2109, keySize={16,2147483648}, wrap, unwrap
  mechtype-0x210A, keySize={1,2147483648}, wrap, unwrap
  mechtype-0x1104, derive
  mechtype-0x1105, derive
  mechtype-0x108A, keySize={16,32}, sign, verify
  DSA-PARAMETER-GEN, keySize={512,1024}, generate
  DSA-KEY-PAIR-GEN, keySize={512,1024}, generate_key_pair
  DSA, keySize={512,1024}, sign, verify
  DSA-SHA1, keySize={512,1024}, sign, verify
  mechtype-0x13, keySize={512,1024}, sign, verify
  mechtype-0x14, keySize={512,1024}, sign, verify
  mechtype-0x15, keySize={512,1024}, sign, verify
  mechtype-0x16, keySize={512,1024}, sign, verify
  DH-PKCS-KEY-PAIR-GEN, keySize={512,10000}, generate_key_pair
  DH-PKCS-PARAMETER-GEN, keySize={512,10000}, generate
  DH-PKCS-DERIVE, keySize={512,10000}, derive
  ECDSA-KEY-PAIR-GEN, keySize={112,521}, generate_key_pair, other flags=0x1900000
  ECDSA, keySize={112,521}, sign, verify, other flags=0x1900000
  ECDH1-DERIVE, keySize={112,521}, derive

You can see that the 'AES-CBC-PAD' mechanism is only usable to perform encrypt and decrypt operation.

Here are the mechanisms which could be used to wrap/unwrap a key in SoftHSMv2:

pkcs11-tool --module /usr/local/lib/softhsm/libsofthsm2.so -M | grep wrap                                             pantin@pantinmbp
Using slot 0 with a present token (0x5f4e737d)
  RSA-PKCS, keySize={512,16384}, encrypt, decrypt, sign, verify, wrap, unwrap
  RSA-PKCS-OAEP, keySize={512,16384}, encrypt, decrypt, wrap, unwrap
  mechtype-0x2109, keySize={16,2147483648}, wrap, unwrap
  mechtype-0x210A, keySize={1,2147483648}, wrap, unwrap

This mainly means that to make our tool work with SoftHSMv2, you would have to modify it to generate, wrap and unwrap the key with a RSA key pair.

Feel free to contact me directly on may email to explain me why you want to do that and we will see what can be done.

  • Thank you for your response, The template is for testing purposes only, I took from : [EJBCA Doc](https://download.primekey.com/docs/EJBCA-Enterprise/latest/Generic_PKCS_11_Provider.html). I'll continue to investigate, and learn about pkcs11. Merci beaucoup !! – No name Dec 21 '19 at 18:36
0

I've managed to do it by using python-pkcs11 and asn1crypto

First, I've implemented a function that encode an RSA private key into PKCS#1 DER-encoded format, it gets the attributes (PRIVATE_EXPONENT, PRIME_1, PRIME_2 ...) from a given key.

Then, I retrieved the private key object and encoded it with previous function (i.e it extracted all the necessary attribute to reconstruct the Private Key).

And finally converted it to PEM format.

No name
  • 93
  • 7