Tag Archives: hsm

Use a smart card or HSM to securely store your SSH CA keys

Depending on the use case, SSH CA keys can be extremely sensitive. Possession of the private key gives you the ability to sign new certificate for arbitrary usernames that will grant access to all machines where this CA is trusted. This is why you should keep your CA keys very safe, preferably offline and of course encrypted (password protected).

One big problem with digital encryption keys is that it is extremely difficult to find out if you lost control over they keys. If they where copied you have no way of finding out. This is where hardware tokens comes in. If you can be sure that the key will never leave the hardware token, you have a better chance of knowing when they keys are lost or stolen.

OpenSSH have support for storing keys onto hardware tokens that talk PKCS#11 such as smart cards and hardware security modules.

If you want to store your personal SSH key on a smart card you can read more about that here: Using Smart Card enabled yubikey for ssh authentication in FreeBSD

Since a SSH CA is just a regular SSH key they can also be stored on smart cards. But there is a few subtle differences in how you use it. First of all you need a token with a RSA key present. There is no option in OpenSSH to ask for a specific key stored on the token, instead we specifiy the public key that matches the private key we want to use. Lets download the public key from the token:

$ ssh-keygen -D /usr/local/lib/opensc-pkcs11.so
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCOvhEqFq9Ualp1iYiNs0JFs3MgvGU+By/VvyW4qkymW+w/MmHAaHl+/UFnE+kgXChdYHaGEVxxGi6dQlSq+1ZKAWPJsOEbkysK6cgjgvP21gVNjL62TlQz+QfGF82mv0hfSGXQrZQR7VDs+6xJOe3S/0i1HvnnRTdR2v9QSJzd2EWNLmUcPy7+4x4rEB11G0oPt+Xyx60WaleJctwJHHhJS/jqHdvuf7HO6MS/EQn2NTnwIjChlmm2kUT7obnev/r6uEwz87NubnYJUrYImRDMafjS9taq8l7y33ydT00QHEI76kmrSSi7hTfmxUgStQWuQ2mq10YEVd8kZ2sqmC3N

We put this into a file, let say ssh_ca.pub. Now we are ready to start using the token for certificate signing.

$ ssh-keygen -s ssh_ca.pub -D /usr/local/lib/opensc-pkcs11.so -I key_id wack.pub 
Enter PIN for 'Framkant HSM Test (UserPIN)': 
Signed user key wack-cert.pub: id "key_id" serial 0 valid forever

To look at the certificate we can use ssh-keygen.

% ssh-keygen -L -f wack-cert.pub 
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:AtPyAu1DL5cFruTo9XnsVz7tdec7xF9SbpX8DzsQrbs
        Signing CA: RSA SHA256:Pbdx6TAvXvwZTKQVMRYWsWYPomw6AxBVoqbtXgy9pfs
        Key ID: "key_id"
        Serial: 0
        Valid: forever
        Principals: (none)
        Critical Options: (none)

In a real life scenario I would recommend against this kind of certificate. Give it some validity and specify principals.

Two nice affordable options for hardware tokens are the Yubikey and the Smart Card HSM

Running OpenDNSSEC

During the years there have been several vulnerabilities found in the DNS protocol making it possible to fool clients in different ways. Maybe the most well known is called dns cache poisoning. To resolve some of these problems people came up with DNSSEC. DNSSEC is a way to cryptographically prove the authenticity of a DNS response by validating signatures all the way up to the root zone. You can read more about it on wikipedia.

This article is an attempt to describe how to implement DNSSEC on your own authoritative name servers. The first and most important step before you even begin to think about implementing DNSSEC is to find out if your registrar supports publishing DS records in the parent zone. If this is not the case your chain of trust will be broken and dnssec will fail.

OpenDNSSEC uses a PKCS#11 enabled backend to store cryptographic material (Hardware Security Module). These could be very expensive, so they also provide a software version of a HSM. This way you can start using OpenDNSSEC without having to pay thousands of dollars on crypto hardware. I’ve been looking into a quite affordable HSM for my (very small) needs. http://www.smartcard-hsm.com

We start by installing the software from packages

# pkg install opendnssec
# pkg install softhsm

We start by setting up the SoftHSM. It comes default with this configuration which will work just fine for us.

# SoftHSM configuration file
# Format:
# :
# The given paths are just an indication to SoftHSM on where it should
# store the information for each token.


We then need to initialize the HSM by running

# softhsm --init-token --slot 0 --label "OpenDNSSEC"
The SO PIN must have a length between 4 and 255 characters.
Enter SO PIN: 
The user PIN must have a length between 4 and 255 characters.
Enter user PIN: 
The token has been initialized.

You will later use the SO PIN to reset/reinit the HSM and the user PIN will be used to access your keys.

Now we can start looking at OpenDNSSEC. First make sure that /usr/local/etc/opendnssec/conf.xml looks reasonable (it does for most people). Just make sure the repository section matches information you gave to OpenHSM.

Then we have a quick look at the kasp.xml “Key and Signature Policy”. This file specifies at which intervals you want to renew the cryptographic keys in you setup. You have have two types of keys for every domain you handle within OpenDNSSEC. KSK and ZSK. The KSK is the “Key Signing Key”. If you are familiar with Certificate authorities this is sort of the Root CA. Its the signature this of key you pass upwards to the parent in the chain of trust. The ZSK is the “Zone Signing Key” and its used to sign the Records in the zone. In the CA anology this is a Intermidiate CA. The purpose of using two keys is to give the opportunity to store the KSK more securely (even offline) when its not used. If you store your keys very securley you can extend the lifetime of the KSK without any problems. The lifetime of your KSK defines how often you need to talk to your registrar and publish new fingerprints in the parent zone. OpenDNSSEC will manage ZSK key rollover for you.

Now we can start opendnssec and begin to have some zones signed. First of all we need to create the databases needed

# ods-ksmutil setup
*WARNING* This will erase all data in the database; are you sure? [y/N] y

Then we can start the opendnssec daemons.

# sh /usr/local/etc/rc.d/opendnssec onestart
Starting enforcer...
OpenDNSSEC ods-enforcerd started (version, pid 42305
Starting signer engine...
OpenDNSSEC signer engine version
Engine running.

To have it start at boot put opendnssec_start=”YES” in /etc/rc.conf.

Key management
I run OpenDNSSEC and my DNS-server (nsd) on the same machine so I sign the zones and put them in a folder that nsd can reach. It is also possible to send your zones with zone transfers if you are having a separate machine for OpenDNSSEC. Anyway, this is how you add a new zone to OpenDNSSEC and then tell it to sign it.

# ods-ksmutil zone add --zone framkant.org --input /usr/local/etc/nsd/chroot/zones/framkant.org --output /usr/local/etc/nsd/chroot/zones/signed/framkant.org
zonelist filename set to /usr/local/etc/opendnssec/zonelist.xml.
Imported zone: framkant.org
# ods-ksmutil update zonelist
zonelist filename set to /usr/local/etc/opendnssec/zonelist.xml.
kasp filename set to /usr/local/etc/opendnssec/kasp.xml.
Zone framkant.org found; policy set to default
Notifying enforcer of new database...
# ods-signer sign framkant.org
Zone framkant.org scheduled for immediate re-sign.

An here is the before and after:

$TTL 300
@ SOA ns3.jails.se. peter.jails.se. (
				3H	; Refresh after three hours
				1H	; Retry after one hour
				1W	; Expire after one week
				1D )	; Minimum one day TTL

		NS	ns3.jails.se.
		NS	mx3.jails.se.
		MX	10 mail.jails.se.
		MX	20 mx3.jails.se.
@		A
		AAAA	2001:470:6c08::1

www		A
		AAAA	2001:470:6c08::1


framkant.org.	3600	IN	SOA	ns3.jails.se. peter.jails.se. 2015032504 10800 3600 604800 3600
framkant.org.	3600	IN	RRSIG	SOA 8 2 3600 20151214230507 20151130173240 26386 framkant.org. iheuqDSSeLdoXJpYOI9ICFSDETnxXbls5K8YnnLBqeQOqgvxNRESWqy1rgAtnReFHnijcMpwly3ttFGUVtd9C4x3dQwMSbgwe9mXY0Tp/ojDdXG0UQLUXHgys0jFen1Go+c3r97lRH8RblIDVu5D5tVynO8+fN9FKzy29ZWfcbc=
framkant.org.	3600	IN	DNSKEY	257 3 8 AwEAAdbN+hOWIvhXB/M4R6KUPPALZA+DUcsW/jEl/Q/1BNi2ff9JZECgNi+2sv1nTdZ+6nOchKNP8UoZ41X4d82MQsO+mGIZeXW5Cb0Riqk7+B7EQWd6jH/pXs9/wNBRQHCNGk1NsyHQNgGxdAq3w99oeIaEbiI+4r/fnwjqKpg3boMyWZlNW30XcJMObXu57hO3S6f09I/+r+7d1bH8FbPBI1VWqiDPgQqjMOkJHrroJ3QWNr8qqSJSsxe2Zb9rTmkx6htrS2XQT2v1kvTT3iBO/Vf+JNbSNYOX4BnR5otgwr9I9OteLDFW4NGn5JNm3Q+kvrLAjByGyOsq0hI3TbvXp20= ;{id = 60509 (ksk), size = 2048b}
framkant.org.	3600	IN	DNSKEY	256 3 8 AwEAAfNwi9djf7sYUVQpqScBOBMqjFD9GqHeI11Y/62SWINheq8+sQ8H/yN2H3eqmW9+ffBVNU8VTCVcdLOwkPGEF5Q1lE7hIbHGLunCAUo5OC8yFhuEtXNFoYo/EuGGbgUmcgYLNKIu8+RxzL5VO9dV7FTUy60tnCsYi/tKDGBP376p ;{id = 26386 (zsk), size = 1024b}
framkant.org.	3600	IN	RRSIG	DNSKEY 8 2 3600 20151214194904 20151130173136 60509 framkant.org. G6+/6njI1NSCvWIeOhyvFo/+v1uSSFRx2Art3bv7Gw2nSJA2aMiu1ZVaIw7uGf75xdWr6lSj6ndb61UmTl+N6ccdbTU80HxwPmBA/fVZpGIAJrQ8psLgx8uDY3AxCfZdEq3YM0JzPewLnKGUaoVFsTzoWNNw2NRYqUuRiBnlebibcci70vaI0QpyRlXfSJ4DWls3H0isk0BWdukcpYEKNx4hl6GsRDCpNRoNs27TXgHnAcv7YV1528gyrgbw63DT6yyyL49nlN+TEV5aiDlNsjnkYJqgy869xfMROAw0VScHderqnixW4LlAGX0QYuPuOoK2dPx874i7xH7JhOoTbQ==
framkant.org.	0	IN	NSEC3PARAM	1 0 5 c2d153cf47fb60fa 
framkant.org.	0	IN	RRSIG	NSEC3PARAM 8 2 0 20151214120059 20151130173136 26386 framkant.org. DlSk0ye1kcP7g0z6QJy0QYpB75ZPpWhbypyRJ3a+L0BaL4cY/cdRS9SACxmhXu/kEkrmadJ/IcfDMhMHOj9D0uY+8ksbKfVhpAX237sFp18V8rsH0zkOPjMjD1O4c30N+isLVdnaPX3OyIRxqRFrRL2XH4kMOR9c8uBpBtin/MU=
framkant.org.	300	IN	NS	ns3.jails.se.
framkant.org.	300	IN	NS	mx3.jails.se.
framkant.org.	300	IN	RRSIG	NS 8 2 300 20151214130253 20151130173136 26386 framkant.org. X9V2dv2+tyWoom6SC5zwkgkMj0buTu/wvGO/ClE7KveJ3YwmG/kPH0z37sS6GWK+j1MzNTzDepcUdxxghO/shDZvSz/7WAtvuHVPWfo2lg+iGG7nxCmYqcmq7Vo2+GZCU5TRjivsCDxen9w+e8+AuZtpuTkEppTQMbEIq+qNGyw=
framkant.org.	300	IN	MX	10 mail.jails.se.
framkant.org.	300	IN	MX	20 mx3.jails.se.
framkant.org.	300	IN	RRSIG	MX 8 2 300 20151215000707 20151130173136 26386 framkant.org. Yw1eRGRESXu1bGh/RNhqJNFpjv+MsDzoyxoPOTNTZiBr+OmlCq6p8M6QgfEPIipmg0VzrHJjzEFfpb4WQmPTKKehH/nEoevKLAogPjbozucr+lgjAXh3AoXr15OYF9dyJilyuTLQ3TyyWDAOxSHtnHy5w704ibaIyGoeKniTf3k=
framkant.org.	300	IN	A
framkant.org.	300	IN	RRSIG	A 8 2 300 20151214104407 20151130173136 26386 framkant.org. zmVjO5Rh1R+lpIUdIvsyTCmhGt2qL1wHUIOlZJbBkiiVpdE051MhRTShRjU79LQ5a+SlBeE5jjVeRrAXhTAb6KhNzZ5j5JaTjPYXzqxe//ddpMYEDzGhmuO1zkfUjtKCFhxgk92lFqimHXJFTj3nXdgbmqvK1io7aqYWCRvKxt4=
framkant.org.	300	IN	AAAA	2001:470:6c08::1
framkant.org.	300	IN	RRSIG	AAAA 8 2 300 20151214075539 20151130173136 26386 framkant.org. ymUD9mz9uQ6on0SF8TSFbb5xU100mJZuZeJafub1YkeolsxmcyXP0HQl0c20QFHWWp7qX4L7rY7QKIgc9aeaMkskrT9BEmwFoTB/MMu9nrweZyyAUdnnrD06mJ6BumBM0ZWBt6qHLe4tiPh8YVqCCjhFBo+SUvDOfelg3k/QAkY=
rl1jo83jomo43daiudaavkfofbmtkks2.framkant.org.	3600	IN	NSEC3	1 0 5 c2d153cf47fb60fa  h0gt9jkpqemi2oumlejri2lvo60uc2qt A NS SOA MX AAAA RRSIG DNSKEY NSEC3PARAM 
rl1jo83jomo43daiudaavkfofbmtkks2.framkant.org.	3600	IN	RRSIG	NSEC3 8 3 3600 20151214151238 20151130173240 26386 framkant.org. 6iNFSodcFOSydizrXrduzAsTPkZB+wqqr0IrdqEL+YcoM1aefmHfX3l5Kems01KCihozii5O23oprGXw0niYk4ESvXjYH0pOK/J6KWes9PirDQj0P8w//FiX9I7jYL4YkfAqf+pKU1vx2mVDT5ATD2Dkty4GX7eKg4h7qDvgSUM=
www.framkant.org.	300	IN	A
www.framkant.org.	300	IN	RRSIG	A 8 3 300 20151214080233 20151130173136 26386 framkant.org. TqG3vzzO3vIPVLZpWHh5Sh6ijNBr61u+7jEMlpl/kfj7S5wvmMgUkWl+hmNaokgrDvrEahpCdTQ0yjSmWl+m5aVFlV17x0x5lJN+Fcx+SuOqqdkHkYKDyTShWdyfDRj9rAQxThbrhvOz3+6gfTJ1HMeGBXIkLMzf1MEojHDlhEg=
www.framkant.org.	300	IN	AAAA	2001:470:6c08::1
www.framkant.org.	300	IN	RRSIG	AAAA 8 3 300 20151214134021 20151130173136 26386 framkant.org. reaA1ca5Jly76YPU+Nfq6CEwgqx7/T2xYh7IzfJ4aZ034vF7djYJFvNMvKMF5wuX7hbP44B3lQk/mnYlzmuVsKGYIwNvU+4+ggIsahgdCItasFOLdJln3oY7f+ch/o6XljE9JKusWFYT2GcPLCsr73PcEIF3QkdXDgXZzSDuZBc=
h0gt9jkpqemi2oumlejri2lvo60uc2qt.framkant.org.	3600	IN	NSEC3	1 0 5 c2d153cf47fb60fa  rl1jo83jomo43daiudaavkfofbmtkks2 A AAAA RRSIG 
h0gt9jkpqemi2oumlejri2lvo60uc2qt.framkant.org.	3600	IN	RRSIG	NSEC3 8 3 3600 20151215051041 20151130173240 26386 framkant.org. lbAGEJm+kCHy68wZ9YqbAFuESnabPvL5TwA0MnwtliUa+lB5DEI2/DIPa+QS7sekjWUxmve2FQoQC+0gFbCP9gOFle8bTwZsAf7ZtZJeVuzEI/HcisNbJk5bV/E/p6xyIBwUDKbcdPh1vhmyDXkhSOZ0o16vLbPgZwuBKtk8J2s=

To handle your created keys you can use ods-ksmutil

# ods-ksmutil key list --verbose
SQLite database set to: /usr/local/var/opendnssec/kasp.db
Zone:                           Keytype:      State:    Date of next transition (to):  Size:   Algorithm:  CKA_ID:                           Repository:                       Keytag:
framkant.org                    KSK           publish   2015-12-01 09:31:35 (ready)    2048    8           adcfe72699de3bb9afe511d67a112580  SoftHSM                           60509
framkant.org                    ZSK           active    2016-02-28 19:31:35 (retire)   1024    8           fcf02532b68b64f7f0dbccf85be3677f  SoftHSM                           26386

Now you need to publish a fingerprint of you key in the parent zone. Please refer to your registrar on how to do this. In sweden at least .SE, binero and loopia have support for this. To get the DS record you can use:

ods-ksmutil key export --ds --zone framkant.org
;active KSK DS record (SHA1):
framkant.org.	3600	IN	DS	65041 8 1 766dee3e0d5cac1c19529d4474eb828d72a91d24
;active KSK DS record (SHA256):
framkant.org.	3600	IN	DS	65041 8 2 a5aba22e70dcc7ad0ee9d31210f87b4f8e99bf6222463eb9c53f3d7a46143129

This is the information you need to send to your registrar. When you can see the DS-record in the parent zone

# drill DS framkant.org @b2.org.afilias-nst.org
;; ->>HEADER<

it is time to tell OpenDNSSEC that the keys are in place and its time to mark the KSK as active.

# ods-ksmutil key ds-seen --zone framkant.org --keytag 60509

Now you are up and running, and if all goes well it will work just fine for one year, until you will need to change the DS records present at the tld. Please refer to the OpenDNSSEC documentation for more information.