Signing RPMs using the Nitrokey hardware security module (HSM)

The CloudRouter project takes security very seriously. Cryptographic signatures are used to ensure the integrity of the software we distribute. CloudRouter 1.0 beta is a Fedora Remix. Most packages are provided by the Fedora repositories. For details on how these packages are signed, see the Fedora documentation. Additional packages such as OpenDaylight are provided by the CloudRouter repositories. These packages are signed using the CloudRouter Project key.

In order to ensure maximum security for our community, we are using a dedicated signing server with a hardware security module (HSM) that is not connected to the Internet. This drastically reduces the risk of a remote attacker compromising the CloudRouter Project key and attempting to sign malicious packages as legitimate components.

Selecting a HSM

A huge variety of HSMs are available. We went with Nitrokey as it had several key benefits:

Installing the HSM

Nitrokey provides great installation documentation, but it is Debian-specific, and we’re using Fedora. On Fedora 21 or RHEL/CentOS 7, the following steps are required to install the Nitrokey:

  • # yum install -y libusb
  • Copy 40-nitrokey.rules to /etc/udev/rules.d/
  • # udevadm control –reload

At this point the system is able to communicate with the Nitrokey device. To complete installation we need to upgrade to the latest firmware package. Upgrading firmware is clearly documented by Nitrokey. There is one gotcha – Nitrokey App’s graphical interface is based on a QT system tray widget. If you are using a non-KDE Linux desktop environment that does not support system tray widgets, then you may be unable to access the graphical interface. On Fedora 21, we had to temporarily switch from GNOME to KDE to make it work.

Preparing the key

Preparing the key is straightforward, but we ran into two limitations of Nitrokey that took some time to figure out. First, Nitrokey does not yet consistently support keys greater than 2048 bits in length. Second, making an off-card backup of the encryption key would consistently fail. With those constraints in mind, here is the process we used to generate the actual CloudRouter Project key:

$ gpg2 --card-edit
gpg/card> admin
Admin commands are allowed

gpg/card> generate
Make off-card backup of encryption key? (Y/n) n

gpg: NOTE: keys are already stored on the card!

Replace existing keys? (y/N) y

What keysize do you want for the Signature key? (2048)
What keysize do you want for the Encryption key? (2048)
What keysize do you want for the Authentication key? (2048)
Please specify how long the key should be valid.
0 = key does not expire
<n>  = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: CloudRouter Project
Email address: security@cloudrouter.org
Comment:
You selected this USER-ID:
"CloudRouter Project <security@cloudrouter.org>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
gpg: key 191F16B0 marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   4  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 4u
pub   2048R/191F16B0 2015-02-10
Key fingerprint = 0FE8 73A5 A682 EFB1 8B05  D8B6 0A1E 8B12 191F 16B0
uid       [ultimate] CloudRouter Project <security@cloudrouter.org>
sub   2048R/85F05C49 2015-02-10
sub   2048R/9EE6A049 2015-02-10

Signing packages

The CloudRouter Project maintains a dedicated signing server that is not connected to the internet. To ensure that the HSM-based key is used, the following line is added to ~/.rpmmacros on the signing server:

%_gpg_name CloudRouter Project <security@cloudrouter.org>

Signing can then be performed using the command:

$ rpm --resign <package>.rpm

GPG is invoked and asks for a pass phase for the key:

Enter pass phrase:

Since we’re using a HSM, this is actually asking for the device PIN. As we continue to enhance our build infrastructure, we aim to completely automate this process. Mozilla have developed an automatic PIN entry tool that we intend to use. Stay tuned for more details as our build infrastructure moves forward!