I’m attempting to wipe a HSM2 entirely, and generate a new ECC key. I have an existing singular key on the HSM, plugged into ca-alpha
:
[root@ca-alpha ~]# sc-hsm-tool | egrep 'DENK|Version|check'
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
Version : 3.5
DKEK key check value : 17AE9454DE4923FB
[root@ca-alpha ~]# pkcs15-tool -D | egrep 'DENK|Card|Version|PIN|EC Key|ID'
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
PKCS#15 Card [HSM-H1]:
Version : 0
Serial number : DENK0200834
Manufacturer ID: www.CardContact.de
PIN [UserPIN]
Auth ID : 02
ID : 01
PIN [SOPIN]
ID : 02
Private EC Key [Private Key]
Auth ID : 01
ID : 2caf2c01df2eb911514a169cc885c73d3a8dd07a
Public EC Key [Private Key]
ID : 2caf2c01df2eb911514a169cc885c73d3a8dd07a
Key points:
- DKEK: 17AE9454DE4923FB
- Private key ID: 2caf2c01df2eb911514a169cc885c73d3a8dd07a
Straight forward enough setup. So, let’s wipe the private key, and reset the HSM:
[root@ca-alpha ~]# pkcs11-tool -l --delete-object --type privkey --id 2caf2c01df2eb911514a169cc885c73d3a8dd07a
Using slot 0 with a present token (0x0)
Logging in to "HSM-H1 (UserPIN)".
Please enter User PIN:
[root@ca-alpha ~]# sc-hsm-tool -X --label "HSM-H1" --dkek-shares 1
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
Enter SO-PIN (16 hexadecimal characters) :
Enter initial User-PIN (6 - 16 characters) :
[root@ca-alpha ~]# sc-hsm-tool
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
Version : 3.5
Config options :
User PIN reset with SO-PIN enabled
SO-PIN tries left : 15
User PIN tries left : 3
DKEK shares : 1
DKEK import pending, 1 share(s) still missing
[root@ca-alpha ~]# pkcs15-tool -D | egrep 'DENK|Card|Version|PIN|EC Key|ID'
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
PKCS#15 Card [HSM-H1]:
Version : 0
Serial number : DENK0200834
Manufacturer ID: www.CardContact.de
PIN [UserPIN]
Auth ID : 02
ID : 01
PIN [SOPIN]
ID : 02
Okay, great. The HSM is in a state where it needs a DKEK share imported, and it only has a UserPIN and SOPIN defined. There are no other keys present on the HSM. When I re-initialized the card, I did change the User PIN to a similar (but different) value.
For somewhat paranoid reasons (that will make sense in a moment), I’m going to disconnect the HSM from ca-alpha
, wait five minutes, and plug it into ca-beta
. From there, I’ll initialize the HSM, and generate a new key.
[root@ca-beta ~]# date
Mon Jan 2 15:29:33 MST 2023
[root@ca-beta ~]# sc-hsm-tool
No smart card readers found.
Failed to connect to card: Success
[root@ca-beta ~]# date
Mon Jan 2 15:35:16 MST 2023
[root@ca-beta ~]# sc-hsm-tool
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
Version : 3.5
Config options :
User PIN reset with SO-PIN enabled
SO-PIN tries left : 15
User PIN tries left : 3
DKEK shares : 1
DKEK import pending, 1 share(s) still missing
Okay, moved to ca-beta
, still in the same state. Great. Let’s actually initialize it and generate a new private key.
[root@ca-beta ~]# sc-hsm-tool --create-dkek-share dkek.pbe
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
The DKEK share will be enciphered using a key derived from a user supplied password.
The security of the DKEK share relies on a well chosen and sufficiently long password.
The recommended length is more than 10 characters, which are mixed letters, numbers and
symbols.
Please keep the generated DKEK share file in a safe location. We also recommend to keep a
paper printout, in case the electronic version becomes unavailable. A printable version
of the file can be generated using "openssl base64 -in <filename>".
Enter password to encrypt DKEK share :
Please retype password to confirm :
Enciphering DKEK share, please wait...
DKEK share created and saved to dkek.pbe
[root@ca-beta ~]# sc-hsm-tool --import-dkek-share dkek.pbe
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
Enter password to decrypt DKEK share :
Deciphering DKEK share, please wait...
DKEK share imported
DKEK shares : 1
DKEK key check value : DC9305A025ED1AFE
[root@ca-beta ~]# pkcs11-tool -l --keypairgen --key-type EC:prime256v1
Using slot 0 with a present token (0x0)
Logging in to "HSM-H1 (UserPIN)".
Please enter User PIN:
Key pair generated:
Private Key Object; EC
label: Private Key
ID: 6e5182b957014bfff8a7dc1da6b2f325c73dbee0
Usage: sign, derive
Access: none
Public Key Object; EC EC_POINT 256 bits
EC_POINT: 044104a2d3a474f9e2c07997e221654b1357f9407440b6bab16a279c566486c2591ce6a6085da7d9d480d8d23a8f884db47d9701db49c622beba9280dddf38680731fe
EC_PARAMS: 06082a8648ce3d030107
label: Private Key
ID: 6e5182b957014bfff8a7dc1da6b2f325c73dbee0
Usage: verify, derive
Access: none
So far so good:
- Old DKEK: 17AE9454DE4923FB
- Old private key ID: 2caf2c01df2eb911514a169cc885c73d3a8dd07a
- New DKEK: DC9305A025ED1AFE
- New private key ID: 6e5182b957014bfff8a7dc1da6b2f325c73dbee0
At this point, I’m going to remove the key from ca-beta
, leave if for another five minutes, power off ca-alpha
for five minutes, power it back on, insert the HSM, and confirm that everything is good in the new PC:
[root@ca-alpha ~]# uptime
15:58:02 up 1 min, 1 user, load average: 0.10, 0.04, 0.01
[root@ca-alpha ~]# date
Mon Jan 2 15:58:03 MST 2023
[root@ca-alpha ~]# sc-hsm-tool
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
Version : 3.5
Config options :
User PIN reset with SO-PIN enabled
SO-PIN tries left : 15
User PIN tries left : 3
DKEK shares : 1
DKEK key check value : DC9305A025ED1AFE
[root@ca-alpha ~]# pkcs15-tool -D | egrep 'DENK|Card|Version|PIN|EC Key|ID'
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
PKCS#15 Card [HSM-H1]:
Version : 0
Serial number : DENK0200834
Manufacturer ID: www.CardContact.de
PIN [UserPIN]
Auth ID : 02
ID : 01
PIN [SOPIN]
ID : 02
Private EC Key [Private Key]
Auth ID : 01
ID : 2caf2c01df2eb911514a169cc885c73d3a8dd07a
Public EC Key [Private Key]
ID : 2caf2c01df2eb911514a169cc885c73d3a8dd07a
Well that’s… strange. The DKEK has in fact changed, and matches the new value. But the EC key… the ID has changed. It’s the old value. Let’s move the HSM one more time back to ca-beta
:
[root@ca-beta ~]# sc-hsm-tool | egrep 'DENK|Version|check'
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
Version : 3.5
DKEK key check value : DC9305A025ED1AFE
[root@ca-beta ~]# pkcs15-tool -D | egrep 'DENK|Card|Version|PIN|EC Key|ID'
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
PKCS#15 Card [HSM-H1]:
Version : 0
Serial number : DENK0200834
Manufacturer ID: www.CardContact.de
PIN [UserPIN]
Auth ID : 02
ID : 01
PIN [SOPIN]
ID : 02
Private EC Key [Private Key]
Auth ID : 01
ID : 6e5182b957014bfff8a7dc1da6b2f325c73dbee0
Public EC Key [Private Key]
ID : 6e5182b957014bfff8a7dc1da6b2f325c73dbee0
This is extremely confusing. The private key ID has changed back to the value that was shown when I re-initialized the HSM. You know what? Let’s power off ca-beta for a moment and try again.
[root@ca-beta~]# uptime
16:08:48 up 0 min, 1 user, load average: 1.00, 0.24, 0.08
[root@ca-beta~]# sc-hsm-tool | egrep 'DENK|Version|check'
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
Version : 3.5
DKEK key check value : DC9305A025ED1AFE
[root@ca-beta ~]# pkcs15-tool -D | egrep 'DENK|Card|Version|PIN|EC Key|ID'
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
PKCS#15 Card [HSM-H1]:
Version : 0
Serial number : DENK0200834
Manufacturer ID: www.CardContact.de
PIN [UserPIN]
Auth ID : 02
ID : 01
PIN [SOPIN]
ID : 02
Private EC Key [Private Key]
Auth ID : 01
ID : 6e5182b957014bfff8a7dc1da6b2f325c73dbee0
Public EC Key [Private Key]
ID : 6e5182b957014bfff8a7dc1da6b2f325c73dbee0
All right, well, the key IDs seem to change relative to which device it is plugged into, which doesn’t make a lot of sense, but at least it is consistent between the devices. Let’s move it back into where I want it to be installed, which is ca-alpha
, and try to sign a new root certificate with it.
[root@ca-alpha rootca]# LD_PRELOAD=/usr/lib64/faketime/libfaketime.so.1 FAKETIME="@2022-12-31 23:59:58" OPENSSL_CONF=./openssl.conf openssl req -new -x509 -days 14600 -sha256 -keyform engine -engine pkcs11 -key id_2caf2c01df2eb911514a169cc885c73d3a8dd07a -subj '/O=TestCA/CN=TestCA1'
Engine "pkcs11" set.
Enter PKCS#11 token PIN for HSM-H1 (UserPIN):
-----BEGIN CERTIFICATE-----
MIIBqzCCAVCgAwIBAgIUARZ8mYmu6NuKqi49ZHiZq6YJSx4wCgYIKoZIzj0EAwIw
IzEPMA0GA1UECgwGVGVzdENBMRAwDgYDVQQDDAdUZXN0Q0ExMCAXDTIzMDEwMTA3
MDAwMFoYDzIwNjIxMjIyMDcwMDAwWjAjMQ8wDQYDVQQKDAZUZXN0Q0ExEDAOBgNV
BAMMB1Rlc3RDQTEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASPfoX+xwOhXYCA
OqnyllgjMUW42x3aiBFvY7XjT3yA5kbeG56eazubYVk2H4EnWzSLULjsFcaCdeS2
guYSbFb4o2AwXjAdBgNVHQ4EFgQUQ/mGCx6cCHZP+/cAI812XjXHLZ0wHwYDVR0j
BBgwFoAUQ/mGCx6cCHZP+/cAI812XjXHLZ0wDwYDVR0TAQH/BAUwAwEB/zALBgNV
HQ8EBAMCAQYwCgYIKoZIzj0EAwIDSQAwRgIhAO63o/TyaGL+B/dm3ggMSQr+h4FY
fVn77loCVDCg8sBXAiEAnSYPehW4jE7jkLBL3F63lclayBjfHOiHnOAH7XPNgTU=
-----END CERTIFICATE-----
[root@ca-alpha rootca]# openssl x509 -text -noout -in root.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
01:16:7c:99:89:ae:e8:db:8a:aa:2e:3d:64:78:99:ab:a6:09:4b:1e
Signature Algorithm: ecdsa-with-SHA256
Issuer: O = TestCA, CN = TestCA1
Validity
Not Before: Jan 1 07:00:00 2023 GMT
Not After : Dec 22 07:00:00 2062 GMT
Subject: O = TestCA, CN = TestCA1
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:8f:7e:85:fe:c7:03:a1:5d:80:80:3a:a9:f2:96:
58:23:31:45:b8:db:1d:da:88:11:6f:63:b5:e3:4f:
7c:80:e6:46:de:1b:9e:9e:6b:3b:9b:61:59:36:1f:
81:27:5b:34:8b:50:b8:ec:15:c6:82:75:e4:b6:82:
e6:12:6c:56:f8
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Subject Key Identifier:
43:F9:86:0B:1E:9C:08:76:4F:FB:F7:00:23:CD:76:5E:35:C7:2D:9D
X509v3 Authority Key Identifier:
43:F9:86:0B:1E:9C:08:76:4F:FB:F7:00:23:CD:76:5E:35:C7:2D:9D
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage:
Certificate Sign, CRL Sign
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:46:02:21:00:ee:b7:a3:f4:f2:68:62:fe:07:f7:66:de:08:
0c:49:0a:fe:87:81:58:7d:59:fb:ee:5a:02:54:30:a0:f2:c0:
57:02:21:00:9d:26:0f:7a:15:b8:8c:4e:e3:90:b0:4b:dc:5e:
b7:95:c9:5a:c8:18:df:1c:e8:87:9c:e0:07:ed:73:cd:81:35
All right. Well, we have a certificate. Cool. Let’s see if windows accepts it as a root cert:
… nope. It generated a certificate with an invalid signature. Which to me, says that something is up with the key. After all, if I generate a new cert without the HSM2, just using a standalone key:
[root@ca-alpha rootca]# openssl ecparam -name prime256v1 -genkey -noout -out testB.key
[root@ca-alpha rootca]# cat testB.key
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEINMaWKxJBQbFtg18AIdPq8Ei/r3B+mjeWL20EhDGGe9toAoGCCqGSM49
AwEHoUQDQgAE9asccI5sxF2HqufeHqQQQQF5yTyPTyG8ARXTTzJLbIAqB7xRtbst
3nXSSr1zEoizG29PbiNJCG/0Zs0W66bCoA==
-----END EC PRIVATE KEY-----
[root@ca-alpha rootca]# LD_PRELOAD=/usr/lib64/faketime/libfaketime.so.1 FAKETIME="@2022-12-31 23:59:58" OPENSSL_CONF=./openssl.conf openssl req -new -x509 -days 14600 -sha256 -key testB.key -subj '/O=TestCA/CN=TestCA2'
-----BEGIN CERTIFICATE-----
MIIBqzCCAVCgAwIBAgIUAWDK1hvLjuMKFRISFyp0EbdSJdkwCgYIKoZIzj0EAwIw
IzEPMA0GA1UECgwGVGVzdENBMRAwDgYDVQQDDAdUZXN0Q0EyMCAXDTIzMDEwMTA2
NTk1OFoYDzIwNjIxMjIyMDY1OTU4WjAjMQ8wDQYDVQQKDAZUZXN0Q0ExEDAOBgNV
BAMMB1Rlc3RDQTIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT1qxxwjmzEXYeq
594epBBBAXnJPI9PIbwBFdNPMktsgCoHvFG1uy3eddJKvXMSiLMbb09uI0kIb/Rm
zRbrpsKgo2AwXjAdBgNVHQ4EFgQUUvGwKSOdEVDmM7ZKvEp6NkCT088wHwYDVR0j
BBgwFoAUUvGwKSOdEVDmM7ZKvEp6NkCT088wDwYDVR0TAQH/BAUwAwEB/zALBgNV
HQ8EBAMCAQYwCgYIKoZIzj0EAwIDSQAwRgIhAIWBIP3CGOvOMDWzCt2fdKeuBQIl
HeUBSOhB4HT5KSneAiEA4fXrwTRe2CSjsWTvGPzUUV4U+fRUUs4wD2GE3xi3fV8=
-----END CERTIFICATE-----
How does this certificate fare in windows?
Just fine.
So I have a theory that there is some mismatch between the public and private key on the card, or some other internal state error. So let’s confirm that theory. Can I sign and then verify some data with that key?
[root@ca-alpha rootca]# echo -n 'Sample Data' > sampledata
[root@ca-alpha rootca]# openssl dgst -sha256 -keyform engine -engine pkcs11 -sign id_2caf2c01df2eb911514a169cc885c73d3a8dd07a -out sampledata.sign sampledata
Engine "pkcs11" set.
Enter PKCS#11 token PIN for HSM-H1 (UserPIN):
[root@ca-alpha rootca]# cat sampledata.sign | xxd
00000000: 3045 0221 00fc d917 fd63 2cf1 3a25 2792 0E.!.....c,.:%'.
00000010: 0181 6332 dbc8 9f3c 15df 69c1 f060 0282 ..c2...<..i..`..
00000020: 8f16 44fd fe02 200f d8a2 331e 26c8 6fc9 ..D... ...3.&.o.
00000030: 27e3 dacd b8d4 aec4 a4d7 e73f 412d de3b '..........?A-.;
00000040: f751 a200 acdb d4 .Q.....
[root@ca-alpha rootca]# openssl dgst -sha256 -keyform engine -engine pkcs11 -verify id_2caf2c01df2eb911514a169cc885c73d3a8dd07a -signature sampledata.sign sampledata
Engine "pkcs11" set.
Verification failure
Well that’s frustrating. The key can’t even sign some sample data.
I got curious to see if maybe I needed to delete the public key and the private key independently.
[root@ca-alpha rootca]# pkcs15-tool -D | egrep 'DENK|Card|Version|PIN|EC Key|ID'
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
PKCS#15 Card [HSM-H1]:
Version : 0
Serial number : DENK0200834
Manufacturer ID: www.CardContact.de
PIN [UserPIN]
Auth ID : 02
ID : 01
PIN [SOPIN]
ID : 02
Private EC Key [Private Key]
Auth ID : 01
ID : 2caf2c01df2eb911514a169cc885c73d3a8dd07a
Public EC Key [Private Key]
ID : 2caf2c01df2eb911514a169cc885c73d3a8dd07a
[root@ca-alpha rootca]# pkcs11-tool -l --delete-object --type pubkey --id 2caf2c01df2eb911514a169cc885c73d3a8dd07a
Using slot 0 with a present token (0x0)
Logging in to "HSM-H1 (UserPIN)".
Please enter User PIN:
[root@ca-alpha rootca]# pkcs11-tool -l --delete-object --type privkey --id 2caf2c01df2eb911514a169cc885c73d3a8dd07a
Using slot 0 with a present token (0x0)
Logging in to "HSM-H1 (UserPIN)".
Please enter User PIN:
[root@ca-alpha rootca]# pkcs15-tool -D | egrep 'DENK|Card|Version|PIN|EC Key|ID'
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
PKCS#15 Card [HSM-H1]:
Version : 0
Serial number : DENK0200834
Manufacturer ID: www.CardContact.de
PIN [UserPIN]
Auth ID : 02
ID : 01
PIN [SOPIN]
ID : 02
All right, wiped. Let’s create a new key:
[root@ca-alpha rootca]# pkcs11-tool -l --keypairgen --key-type EC:prime256v1
Using slot 0 with a present token (0x0)
Logging in to "HSM-H1 (UserPIN)".
Please enter User PIN:
Key pair generated:
Private Key Object; EC
label: Private Key
ID: 93ed81be96dded1557b0beb27350aee44e3bfba6
Usage: sign, derive
Access: none
Public Key Object; EC EC_POINT 256 bits
EC_POINT: 0441049e14ff1a6ae297b7a55599f36830c5f71fd4d89f55e07bfcf3fe1f5ae4d119b3ae307a90046719167b9364879730ba667c230913ec3668326ce4a5051d8b31af
EC_PARAMS: 06082a8648ce3d030107
label: Private Key
ID: 93ed81be96dded1557b0beb27350aee44e3bfba6
Usage: verify, derive
Access: none
[root@ca-alpha rootca]# pkcs15-tool -D | egrep 'DENK|Card|Version|PIN|EC Key|ID'
Using reader with a card: Nitrokey Nitrokey HSM (DENK02008340000 ) 00 00
PKCS#15 Card [HSM-H1]:
Version : 0
Serial number : DENK0200834
Manufacturer ID: www.CardContact.de
PIN [UserPIN]
Auth ID : 02
ID : 01
PIN [SOPIN]
ID : 02
Private EC Key [Private Key]
Auth ID : 01
ID : 2caf2c01df2eb911514a169cc885c73d3a8dd07a
Public EC Key [Private Key]
ID : 2caf2c01df2eb911514a169cc885c73d3a8dd07a
… I get a new key ID when I run --keypairgen, but the old key ID returns when I try to enumerate it. And when I try to generate a new signature against some sample data, the verification still fails. (And if I try to reference the newly generated key ID, I just get an error, pkcs11 engine:ERR_ENG_error:object not found
.)
Before I forget, versions:
[root@ca-alpha rootca]# rpm -qa |egrep 'pkcs11|opensc|openssl' | sort
opensc-0.23.0-2.fc37.x86_64
openssl-3.0.5-3.fc37.x86_64
openssl-libs-3.0.5-3.fc37.x86_64
openssl-pkcs11-0.4.12-2.fc37.x86_64
So, questions:
- How do I properly re-initialize the HSM2? Did I do anything wrong?
- Did I do anything wrong with the key generation process?
- Should the key ID be the same across distinct computers, or should it persist?
- How do I get a working HSM2 again?