Hardware Security Modules
Category : security
Introduction
Hardware Security Module (HSM) is a physical crypto device that is designed to creates, manages and protects in a safe manner crypto keys against tampering.
HSMs are used for different applications cases such as :
- secure cryptographic key generation
- secure key storage at least for master keys which other keys are derived
- key management
- encryption or digital signature
- offloading of crypto operations (symetric/asymetric)
HSMs have different form-factor ranging from small USB sticks to server-like devices.
The difference between those devices is speed and storage capacity.
In this article we will show how to setup a HSM (Nitrokey) and how to use it perform a digital signature.
Nitrokey HSM
The Nitrokey HSM is a very affordable USB device:
It supports the following crypto operation:
- RSA 1024-2048 Bit
- ECC 192-521 Bit
- AES 128-256 Bit
Software Installation
On an Ubuntu 18.04 the following packages are required:
$ sudo apt-get install opensc opensc-pkcs11 libengine-pkcs11-openssl
First let’s check if device is connected and available:
dmesg output after inserting the key:
[19264.240419] usb 1-1.3: New USB device found, idVendor=20a0, idProduct=4230
[19264.240426] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[19264.240430] usb 1-1.3: Product: Nitrokey HSM
[19264.240433] usb 1-1.3: Manufacturer: Nitrokey
[19264.240437] usb 1-1.3: SerialNumber: DENK01020420000
Everything is fine we can list the device using pkcs11-tool:
$ pkcs11-tool --list-slots
Available slots:
Slot 0 (0x0): Nitrokey Nitrokey HSM (DENK01020420000 ) 00 00
token label : UserPIN (SmartCard-HSM)
token manufacturer : www.CardContact.de
token model : PKCS#15 emulated
token flags : login required, rng, token initialized, PIN initialized
hardware version : 24.13
firmware version : 3.1
serial num : DENK0102042
pin min/max : 6/15
PIN Setup
The HSM has factory default settings so needs to be initialized before it can be used in a secure way.
SO-PIN
The Security Officer Pin is the admin user pin which can manage all the slots (in our case we have only one slot)
For the Nitrokey HSM the default SO pin is 3537363231383830
$ pkcs11-tool --login --login-type so --so-pin 3537363231383830 --change-pin --new-pin 3537363231383830
User-PIN
Each HSM Slot can be initilaized with a User-Pin, we can set it in the following way:
$ sc-hsm-tool --initialize --so-pin 3537363231383830
Using reader with a card: Nitrokey Nitrokey HSM (DENK01020420000 ) 00 00
Enter initial User-PIN (6 - 16 characters) :
*After Initialization all keys, certificates are erased.
Generate a RSA keypair
$ pkcs11-tool --keypairgen --key-type rsa:2048 --id 1 --login --usage-sign --label "testkey"
Using slot 0 with a present token (0x0)
Logging in to "UserPIN (SmartCard-HSM)".
Please enter User PIN:
Key pair generated:
Private Key Object; RSA
label: testkey
ID: 01
Usage: sign, unwrap
Public Key Object; RSA 2048 bits
label: testkey
ID: 01
Usage: verify, wrap
Check the slot:
$ pkcs15-tool -D
Using reader with a card: Nitrokey Nitrokey HSM (DENK01020420000 ) 00 00
PKCS#15 Card [SmartCard-HSM]:
Version : 0
Serial number : DENK0102042
Manufacturer ID: www.CardContact.de
Flags :
PIN [UserPIN]
Object Flags : [0x3], private, modifiable
Auth ID : 02
ID : 01
Flags : [0x812], local, initialized, exchangeRefData
Length : min_len:6, max_len:15, stored_len:0
Pad char : 0x00
Reference : 129 (0x81)
Type : ascii-numeric
Path : e82b0601040181c31f0201::
Tries left : 3
PIN [SOPIN]
Object Flags : [0x1], private
ID : 02
Flags : [0x9A], local, unblock-disabled, initialized, soPin
Length : min_len:16, max_len:16, stored_len:0
Pad char : 0x00
Reference : 136 (0x88)
Type : bcd
Path : e82b0601040181c31f0201::
Tries left : 15
Private RSA Key [testkey]
Object Flags : [0x3], private, modifiable
Usage : [0x2C], sign, signRecover, unwrap
Access Flags : [0x1D], sensitive, alwaysSensitive, neverExtract, local
ModLength : 2048
Key ref : 1 (0x1)
Native : yes
Auth ID : 01
ID : 01
MD:guid : 20f72851-1f5c-4436-0350-fbb2627fa1ce
Public RSA Key [testkey]
Object Flags : [0x0]
Usage : [0x51], encrypt, wrap, verify
Access Flags : [0x2], extract
ModLength : 2048
Key ref : 0 (0x0)
Native : no
ID : 01
DirectValue : <present>
OpenSSL Integration
OpenSSL can interact with different HSMs using the standard PKCS#11 API.
For the Nitrokey we can use the OpenSC implementation as follow:
$ cat > openssl.cnf << EOF
#
# OpenSSL config to use PKCS11 engine
#
openssl_conf = openssl_engine
[openssl_engine]
engines=engine_section
[engine_section]
pkcs11 = pkcs11_section
[pkcs11_section]
engine_id = pkcs11
MODULE_PATH = /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
init = 0
[req]
distinguished_name = req_distinguished_name
[req_distinguished_name]
EOF
Now OpenSSL is ready to access the HSM.
To generate a certificate out of the testkey (ID: 1) we created before:
$ OPENSSL_CONF=openssl.cnf openssl req -engine pkcs11 -new -key 1 -keyform engine -out cert.pem -text -x509 -subj "/O=Embetrix/CN=HSM-Test/emailAddress=info@embetrix.com"
Check the created certificate:
$ openssl x509 -in cert.pem -text
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
65:bc:66:3a:5b:4b:27:09:f9:54:0d:38:23:5a:5a:0a:7e:f9:16:53
Signature Algorithm: sha256WithRSAEncryption
Issuer: O = Embetrix, CN = HSM-Test, emailAddress = info@embetrix.com
Validity
Not Before: Jul 22 11:54:52 2020 GMT
Not After : Aug 21 11:54:52 2020 GMT
Subject: O = Embetrix, CN = HSM-Test, emailAddress = info@embetrix.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:82:2c:96:fb:79:2d:a4:91:a0:23:ad:10:37:c6:
fa:88:d5:f3:21:31:a3:de:68:c8:6e:d8:6e:85:f7:
30:52:0e:a1:c2:1b:64:0f:0c:9b:09:ed:05:24:35:
e8:3d:75:78:ee:d3:1b:58:39:70:ed:33:ca:4f:06:
bd:ba:b4:ba:1e:57:29:e3:76:df:33:7e:17:3b:ae:
96:c7:9d:c4:eb:0c:50:cb:65:85:45:86:1d:c7:14:
9a:4a:48:27:df:ae:1d:23:3e:61:df:7e:04:68:3a:
5f:3f:24:6c:ac:36:d9:07:a5:96:3f:54:8d:48:20:
a1:54:36:da:c8:ec:78:dd:c1:d7:1b:65:51:66:71:
da:c1:39:fd:18:71:19:d9:4b:b0:a1:9a:1f:eb:ab:
14:57:6f:e8:0c:72:5e:1d:fb:c9:18:89:a5:35:c3:
8d:85:fa:ef:e3:52:3c:8a:95:40:fc:f3:68:0a:c3:
5d:a1:54:9e:e3:bd:4e:8a:57:21:a9:7a:71:ae:4d:
41:9d:1c:88:76:37:a2:d0:d4:8b:fe:0e:c9:d0:16:
63:ee:63:77:c3:e8:7c:22:70:3b:09:63:85:45:84:
52:f7:6f:5f:24:24:9e:7a:06:6d:12:3e:13:9c:55:
2d:c7:e3:47:f2:7b:bf:7d:2f:3c:73:ec:ce:3f:3b:
6a:25
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
3d:e1:53:15:e4:29:88:d6:b1:1c:52:d3:b9:61:0d:fc:e6:bd:
55:a0:8d:1f:fa:a6:63:07:14:4a:10:a0:f5:a2:23:f7:ac:48:
29:86:19:a9:0d:a9:fe:9f:08:fb:a7:08:5e:f3:48:ea:29:f5:
89:02:3a:39:dc:c9:f8:d4:67:e3:ca:e7:4c:cb:ad:05:35:fc:
fc:5e:e7:1b:00:f5:e6:ea:7d:35:aa:82:ee:d2:09:79:1c:4e:
4c:8f:fa:28:0b:8e:25:d9:7c:25:0f:ed:ec:fb:7d:4c:55:ce:
da:cf:50:16:f5:d8:e7:71:b0:01:05:12:f3:2d:d6:43:49:31:
10:72:48:c8:d9:5b:bc:3f:9f:21:c0:7e:69:d2:37:fd:4b:54:
4b:27:31:9c:03:9b:8e:59:02:2a:e3:1e:d3:17:e1:40:c7:10:
22:40:66:03:ef:20:03:98:9a:57:3f:91:66:0a:f7:d4:30:04:
82:0c:14:8e:92:5c:a6:13:18:fc:20:f4:18:ac:e5:34:32:e6:
64:97:22:b6:de:33:7e:64:49:d5:ac:be:94:d4:ad:8b:62:28:
90:5e:5e:97:bc:32:29:fd:34:22:67:64:6c:7b:29:8c:98:fa:
4b:fe:99:36:d4:f7:53:eb:11:f0:37:31:8a:ac:0f:a3:95:9f:
02:65:c3:f1
-----BEGIN CERTIFICATE-----
MIIDEzCCAfsCFGW8ZjpbSycJ+VQNOCNaWgp++RZTMA0GCSqGSIb3DQEBCwUAMEYx
EDAOBgNVBAoMB0VtYmV4dXMxETAPBgNVBAMMCEhTTS1UZXN0MR8wHQYJKoZIhvcN
AQkBFhBpbmZvQGVtYmV4dXMuY29tMB4XDTIwMDcyMjExNTQ1MloXDTIwMDgyMTEx
NTQ1MlowRjEQMA4GA1UECgwHRW1iZXh1czERMA8GA1UEAwwISFNNLVRlc3QxHzAd
BgkqhkiG9w0BCQEWEGluZm9AZW1iZXh1cy5jb20wggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQCCLJb7eS2kkaAjrRA3xvqI1fMhMaPeaMhu2G6F9zBSDqHC
G2QPDJsJ7QUkNeg9dXju0xtYOXDtM8pPBr26tLoeVynjdt8zfhc7rpbHncTrDFDL
ZYVFhh3HFJpKSCffrh0jPmHffgRoOl8/JGysNtkHpZY/VI1IIKFUNtrI7Hjdwdcb
ZVFmcdrBOf0YcRnZS7Chmh/rqxRXb+gMcl4d+8kYiaU1w42F+u/jUjyKlUD882gK
w12hVJ7jvU6KVyGpenGuTUGdHIh2N6LQ1Iv+DsnQFmPuY3fD6HwicDsJY4VFhFL3
b18kJJ56Bm0SPhOcVS3H40fye799Lzxz7M4/O2olAgMBAAEwDQYJKoZIhvcNAQEL
BQADggEBAD3hUxXkKYjWsRxS07lhDfzmvVWgjR/6pmMHFEoQoPWiI/esSCmGGakN
qf6fCPunCF7zSOop9YkCOjncyfjUZ+PK50zLrQU1/Pxe5xsA9ebqfTWqgu7SCXkc
TkyP+igLjiXZfCUP7ez7fUxVztrPUBb12OdxsAEFEvMt1kNJMRBySMjZW7w/nyHA
fmnSN/1LVEsnMZwDm45ZAirjHtMX4UDHECJAZgPvIAOYmlc/kWYK99QwBIIMFI6S
XKYTGPwg9Bis5TQy5mSXIrbeM35kSdWsvpTUrYtiKJBeXpe8Min9NCJnZGx7KYyY
+kv+mTbU91PrEfA3MYqsD6OVnwJlw/E=
-----END CERTIFICATE-----
Let’s create and sign a file using OpenSSL command line:
$ dd if=/dev/urandom of=DATA bs=1M count=1
We use the testkey (ID: 1) to sign the file:
$ OPENSSL_CONF=openssl.cnf openssl cms -sign -signer cert.pem -engine pkcs11 -inkey 1 -keyform engine -binary -in DATA -outform der -out DATA.sig
Engine interaction with the HSM is also possible using libcrypto C native code, you can check our implementation example:
https://github.com/embetrix/cms-sign-pkcs11
Finally let’s verify if the signature is correct:
$ openssl cms -verify -binary -content DATA -in DATA.sig -certfile cert.pem -noverify -inform DER -outform DER -out /dev/null
Verification successful