This is a text-only version of the following page on https://raymii.org:
---
Title : Use the Nitrokey HSM or SmartCard-HSM with sc-hsm-embedded, mod_nss and Apache (read only module)
Author : Remy van Elst
Date : 15-07-2016
URL : https://raymii.org/s/articles/Use_the_Nitrokey_HSM_or_SmartCard-HSM_with_sc-hsm-embedded_mod_nss_and_Apache_read_only_module.html
Format : Markdown/HTML
---
![][1]
> The NitroKey HSM in a sealed package
This is a guide on using the Nitrokey HSM with sc-hsm-embedded module instead of
the PC/SC daemon and OpenSC, mod_nss and the Apache webserver. This is an
extension on the earlier guide, with new benchmarks. The sc-hsm-embedded module
is not using a global lock like OpenSC, therefore providing better performance.
The sc-hsm-embedded module is also a read only module, suitable for embedded
systems. Read only also makes it more secure when deployed, even when the user
pin leaks out an attacker cannot create new keypairs or delete the current ones.
The HSM allows you to store the private key for a SSL certificate inside the HSM
(instead of on the filesystem), so that it can never leave the device and thus
never be stolen.
The guide covers the installation of the sc-hsm-embedded module, configuration
of and benchmarks from Apache with the HSM and different key sizes.
### Introduction
![][2]
> The SmartCard-HSM
The [Nitrokey HSM][3] is an open hardware and open software device. It is a USB
version of the [SmartCard-HSM][4]. Both the [SmartCard-HSM][5] as the [Nitrokey
HSM][6] have sources available and are fully supported by the [OpenSC][7]
project.
If you are new to the NitroKey HSM/SmartCard HSM, please also [read my getting
started][8] article. It explains what the HSM is, how to set it up and how to
use it with OpenSSH for example.
I have [multiple articles][9] on this nice device, so make sure to read the
others as well.
To follow this article, I recommend you first read the [article on the Nitrokey
HSM with mod_nss and Apache][10] I wrote earlier. The other article has more
explanation and examples, this article will focus on the installation of the
module and the benchmarks.
In a recent conversation I had with Andreas Schwier, one of the people behind
the [SmardCard-HSM][4] project, I was informed about the `sc-hsm-embedded`
module. Andreas told me that they, in [their load tests][11], experienced bad
performance with OpenSC because of a global lock. Their benchmarks were done
with their own PKCS#11 module, which we are covering here in this article.
The `sc-hsm-embedded` is described as:
Light-weight, read-only PKCS#11 library for using the SmartCard-HSM in embedded systems.
So you will not be able to create keypairs with this module or write
certificates to the HSM.
This guide was tested on Ubuntu 14.04 and Arch Linux with a NitroKey HSM.
Recently I removed all Google Ads from this site due to their invasive tracking, as well as Google Analytics. Please, if you found this content useful, consider a small donation using any of the options below:
### Installation of the sc-hsm-embedded module
For Arch Linux [I made an AUR package][13] of the module [and an AUR
package][14] for the OpenSSL Engine.
Do note that you can install this module next to the OpenSC package. They don't
conflict with one another.
On Ubuntu, install the development tools and pcsclite packages:
apt-get install automake build-essential pkg-config libtool libusb-1.0-0-dev libpcsclite-dev checkinstall
Clone the git repository:
git clone https://github.com/CardContact/sc-hsm-embedded.git sc-hsm-embedded-2.9
cd sc-hsm-embedded-2.9
Execute the following commands to generate a `/.configure` file using the
`autotools`:
libtoolize --force
aclocal
autoheader
automake --force-missing --add-missing
autoconf
Continue the compilation:
./configure
make
I like to create a debian package with `checkinstall` instead of a `make
install`. It's certainly not the official way to create debian packages, but it
does allow you to keep a system clean and allows for easier upgrading. Also, a
package is much more convinient if you are distributing it in a repo or with
Ansible. Create the package:
checkinstall
The default settings should be OK, but change them as you like. The final output
should be along the lines of:
**********************************************************************
Done. The new package has been installed and saved to
/root/repo/sc-hsm-embedded-2.9/sc-hsm-embedded_2.9-1_amd64.deb
You can remove it from your system anytime using:
dpkg -r sc-hsm-embedded
**********************************************************************
On any other distro, use their native way to build a package (hi `PKGBUILD`) or
just do a plain simple `make install`.
There should now be a new library on your system:
file /usr/local/lib/libsc-hsm-pkcs11.so
/usr/local/lib/libsc-hsm-pkcs11.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=1ede3f07f0094711931f5e25d9716622742356da, stripped
On Arch:
file /usr/lib/libsc-hsm-pkcs11.so
/usr/lib/libsc-hsm-pkcs11.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=3854bdd3a096b19c927817a486140bc2750555f8, stripped
Later in the article, place the correct path to this `.so` file in the
configuration. Or, if you want to be able to copy and paste the commands, create
a symlink:
ln -s /usr/lib/libsc-hsm-pkcs11.so /usr/local/lib/libsc-hsm-pkcs11.so
You can test the new module with their own test tool or `pkcs11-tool`:
pkcs11-tool --module libsc-hsm-pkcs11.so --login --pin 648219 --show-info
Output:
Cryptoki version 2.20
Manufacturer CardContact (www.cardcontact.de)
Library SmartCard-HSM R/O with PC/SC (ver 2.8)
Using slot 1 with a present token (0x5)
Compared with the `opensc-pkcs11` module:
pkcs11-tool --module opensc-pkcs11.so --login --show-info --pin 648219
Output:
Cryptoki version 2.20
Manufacturer OpenSC Project
Library OpenSC smartcard framework (ver 0.16)
Using slot 1 with a present token (0x4)
You will notice that most operations with `pkcs11-tool`, like creating a
keypair, will fail:
pkcs11-tool --module libsc-hsm-pkcs11.so --login --pin 648219 --keypairgen --key-type rsa:1024 --id 1 --label "HSM RSA Key Remy"
Output:
Using slot 1 with a present token (0x5)
error: Generate RSA mechanism not supported
Aborting.
This is expected since it's a read only module. Read only also makes it more
secure when deployed, even when the user pin leaks out an attacker cannot create
new keypairs or delete the current ones.
A delete operation will not give any error messages:
pkcs11-tool --module libsc-hsm-pkcs11.so --login --pin 648219 --delete-object --type privkey --id 3
Output:
Using slot 1 with a present token (0x5)
But, if you list the objects before and after you will see that the key you
tried to delete is still there.
Just listing data does work:
pkcs11-tool --module libsc-hsm-pkcs11.so --login --pin 648219 --list-objects --id 01
Output:
Using slot 1 with a present token (0x5)
Public Key Object; RSA 2048 bits
label: 1024cert
ID: 03
Usage: encrypt, verify
Certificate Object, type = X.509 cert
label: 1024cert
ID: 03
Reading the data does work as well:
pkcs11-tool --module libsc-hsm-pkcs11.so --login --pin 648219 --read-object --id 1 --type cert | base64
Output:
Using slot 1 with a present token (0x5)
MIIDcjCCAloCCQDIi8zcoGtnejANBgkqhkiG9w0BAQsFADB7MQswCQYDVQQGEwJOTDEVMBMGA1UE
[...]
qJ49qqLd5I24yKXxh9qTYrXDxHPAExqXHnwydXiDRQ==
### Creating the keys and certificates
We will now start with creating the keypairs in the HSM and generating the
certificates.
Please do read the [article on the Nitrokey HSM with mod_nss and Apache][10] to
find out how to fully configure the NitroKey HSM/SmartCard HSM with `mod_nss`.
This is a more compact version without all the explanation.
I did create three test keypairs, one `RSA 1024` bit, one `RSA 2048` bit and one
`EC` pair. They have ID 1, 2 and, suprisingly, 3. If you want to follow along,
also create the keys. Start with the 1024 bit key:
pkcs11-tool --module opensc-pkcs11.so --login --pin 648219 --keypairgen --key-type rsa:1024 --id 1 --label "httpd1024"
Output:
Key pair generated:
Private Key Object; RSA
label: httpd1024
ID: 01
Usage: decrypt, sign, unwrap
Public Key Object; RSA 1024 bits
label: httpd1024
ID: 01
Usage: encrypt, verify, wrap
2048 bit key:
pkcs11-tool --module opensc-pkcs11.so --login --pin 648219 --keypairgen --key-type rsa:2048 --id 2 --label "httpd2048"
Output:
Key pair generated:
Private Key Object; RSA
label: httpd2048
ID: 02
Usage: decrypt, sign, unwrap
Public Key Object; RSA 2048 bits
label: httpd2048
ID: 02
Usage: encrypt, verify, wrap
And the EC key:
pkcs11-tool --module opensc-pkcs11.so --login --pin 648219 --keypairgen --key-type EC:prime256v1 --id 3 --label "httpdECprime256v1"
Output:
Private Key Object; EC
label: httpdECprime256v1
ID: 03
Usage: sign, derive
Public Key Object; EC EC_POINT 256 bits
EC_POINT: 044104ca3ff52e48bd85f3878ef8e1b59498c9fcc7741a1e547f2849ff4a5f716d96ea49ab8f25c61e7b4ad899fd3df8996767e70672ceb9297758695810fbc30ba660
EC_PARAMS: 06082a8648ce3d030107
label: httpdECprime256v1
ID: 03
Usage: verify
We need to generate (self signed) certificates for all of these keypairs. We
will use OpenSSL with a configfile do to that. See [my tutorial on the Nitrokey
if you want to generate a CSR and what to put in][15] `hsm.conf`.
I did have some issues when providing the slot and ID, OpenSSL gave errors like
these:
engine "pkcs11" set.
Invalid slot number: 1
PKCS11_get_private_key returned NULL
cannot load Private Key from engine
140378622912152:error:26096080:engine routines:ENGINE_load_private_key:failed loading private key:eng_pkey.c:124:
unable to load Private Key
Turns out, I was using the wrong slot number:
pkcs11-tool --list-slots
Output:
Available slots:
Slot 0 (0x0): Lenovo Integrated Smart Card Reader 00 00
(empty)
Slot 1 (0x4): Nitrokey Nitrokey HSM (010000000000000000000000) 01 00
token label : SmartCard-HSM (UserPIN)
token manufacturer : www.CardContact.de
token model : PKCS#15 emulated
token flags : rng, login required, PIN initialized, token initialized
hardware version : 24.13
firmware version : 2.0
serial num : DENK0100186
I was using slot 1, but that did not work. Slot 4 (`0x4`) did work. You can
provide the slot and ID to OpenSSL in multiple formats:
supported formats: , :, id_, slot_-id_, label_