One day I became curious to see if I could use a security token/smart card with pfSense to log into OpenVPN. Why not? It beats storing unencrypted keys and/or passwords on mobile computers. If you can't get users to change their passwords as often as you'd like, smart cards are one kind of mitigation. You'll just need card readers or USB ports on client devices and the open-source pkcs11 dll or shared object. And get your users not to leave the tokens/cards in their computers. (Which is why it's great to also make them proximity cards for doors.) If you needed your smart card to go to the restroom, I'm guessing you wouldn't leave it in the computer.
This does NOT cover Windows domain authentication, or one-time-password tokens such as inSecureID.
It turns out that it is possible -- provided you follow some simple steps. The best part is that smartcard authentication to pfSense's implementation of OpenVPN doesn't require any server-side configuration changes. (Assuming you're already doing certificate-based authentication -- tls key too, if you want.) That's right. If you've got certificate-based authentication working, you don't need to change a single parameter on the pfSense side. You can also use your smart card to log in via SSH with Putty-SC and via https with Firefox.
Smart cards and tokens are often misunderstood. Mention "hardware security module" and people start to think you're a security geek. But smart cards are mini-HSMs. The card stores your certificate and key. It protects your key with a PIN. Some cards can store more certificates and keys than others, but that's the main concept. It separates your private key from the computer and protects it. Get the PIN wrong a few times and your card gets locked. Forget the PIN unlock code (PUK) and you may lock out the card permanently, which is exactly what should happen in a hardware security module.
But this is IT, where simple concepts are blown up by implementations. Every smart card brand and model is different. The middleware is all different. You have to get married to a card and its vendor's middleware to make it work. Even the HSPD-12/PIV standard is a standard for reading cards only. Administration is different for all vendor PIV implementations, creating millions of dollars in opportunities for card middleware vendors. (Hmmm, I wonder what the US national ID card is going to look like.)
Until OpenSC. OpenSC is the Smart Card project that's been open-sourcing card solutions for a number of years, and it pretty much works if you stick to cards they support.
Problem: they don't support that many cards and the cards they do support aren't sold many places. But you can buy ones that work for shipment to the US and Wassenar countries. I chose Aventra and it worked. Gooze's 2003 PKI USB tokens are up next for testing.
One key point: pkcs15 is a file structure for cards. pkcs11 is a software interface for cards. Read the OpenSC documentation twice before starting -- once for concepts and again for details.
When you buy the cards, you'll be offered a proprietary driver and middleware. Don't use it. Everything you need is at OpenSC-project.org. Stick with those drivers and their process. OpenSSL has an engine for cards: the PKCS11 engine. That lets you issue OpenSSL commands to get a CSR from the card's key. The other software component is pkcs11 shared object/dll file, or "driver." You point your smartcard-aware application at that so it knows where to find the software interface, which knows where to find certificates and ask for keys. (In windows, it's c:\windows\system32\opensc-pkcs11.dll; in Linux, it's wherever you stuck opensc-pkcs11.so.)
Once you get the card, install Open-SC, and stick the card in the reader. (You can install Open-SC on Linux or Windows and maybe Mac.)
1. Initialize the card:
pkcs15-init --create-pkcs15 --profile pkcs15 --use-default-transport-key --pin xxxxxxx --puk xxxxxxxxxx --label "larry" --so-pin xxxxx --so-puk xxxxxxx
(There are many different options, you'll need to read the documentation...)
2. Get the certificates on the card:
Method 1: Fast using your existing OpenVPN certificates:
In a nutshell, here's what you do. Take your OpenVPN client certificate and key, (and your CA chain if necessary), and export it using OpenSSL into a pkcs12 file. Then use OpenSC's pkcs15-init tool to get the pkcs12 file onto the card.
The command below exports your certificate and private key in the same form you can get it out of pfSense. It contains your private key, so don't leave it lying around.
openssl pkcs12 -export -out larry.p12 -in larry.pem -inkey larry.key
Once you've got that, get it on the card thus:
pkcs15-init --store-private-key larry.p12 --format pkcs12 --auth-id 01 --pin xxxxx
Method 2: Create a new card-only key, use your own CA
For advanced users with their own CA, there's another way: issue the command to the card to create a private key, then use the OpenSSL pkcs11 engine and the pkcs11 interface to generate a certificate request.
pkcs15-init --generate-key rsa2048 --auth-id 01 --pin xxxxx
This should take about 40 seconds on the MyEID card. Then get the slot ID for the key:
pkcs15-tool --list-keys
Using reader with a card: SCM SCR 3310 [CCID Interface] 00 00
Private RSA Key [Private Key]
Object Flags : [0x3], private, modifiable
Usage : [0x10E], decrypt, sign, signRecover, derive
Access Flags : [0x0]
ModLength : 2048
Key ref : 1 (0x1)
Native : yes
Path : 3f0050154b01
Auth ID : 01
ID : d5e583c9fc7835231e94369f0f066d5ca5039814
GUID : {d5e583c9-fc78-3523-1e94-369f0f066d5c}
The fire up OpenSSL:
openssl
And then load the pkcs11 engine. (This is what requires you to install the extra engine.)
engine dynamic -pre SO_PATH:/usr/lib64/openssl/engines/engine_pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:/usr/local/lib/opensc-pkcs11.so
If all is successful, you can forge ahead. If not, figure out what's wrong with your compile.
(dynamic) Dynamic engine loading support
[Success]: SO_PATH:/usr/lib/engines/engine_pkcs11.so
[Success]: ID:pkcs11
[Success]: LIST_ADD:1
[Success]: LOAD
[Success]: MODULE_PATH:opensc-pkcs11.so
Loaded: (pkcs11) pkcs11 engine
Using the key ID from above, you can create a certificate signing request without getting the key off the card. Just put "slot_x-id_" in front of the number.
OpenSSL>req -engine pkcs11 -new -key slot_1-id_d5e583c9fc7835231e94369f0f066d5ca5039814 -keyform engine -out mynewrequest.csr
Then sign the CSR with your CA and import the certificate to the card. If you don't know how to sign a CSR, then Google it... Once you have the certificate, get it onto the card:
pkcs15-init --store-certificate larry.crt --auth-id 01 --id d5e583c9fc7835231e94369f0f066d5ca5039814 --format pem
Notice that the private key never leaves the card. (My dream is to get TinyCA working and store the CA key on a smart card....)
Now you're ready to test using the card:
OpenVPN:
Then change your client OpenVPN configuration file to use pkcs11. One catch is that the OepnVPN client supports pkcs11 but doesn't give you any way to input the PIN. Nor does OpenVPN-GUI. Viscosity does, but it's proprietary. OpenVPN-GUI has a modded version that supports it that I have not tested yet. Thus I use Viscosity. You'll need to load your pkcs11 module. In windows, it's c:\windows\system32\opensc-pkcs11.dll.
Once you get OpenVPN working, you can try using the key to access logins via SSH using Putty's smart card version. To get your public key off the card in ssh form, just try:
ssh-keygen -D /usr/lib/opensc-pkcs11.so
You can also configure Apache's httpd to use client certificates for authentication. Just change your /etc/httpd/conf.d/ssl.conf to include these two lines:
SSLCACertificateFile /etc/httpd/conf.d/mycafile.pem
where mycafile.pem is your cert authority's public cert.
and then
SSLVerifyClient require
And all your SSL connections will then require client certificates. Apache tends to reset the connection when you don't have a client certificate available.
Firefox has security token support built in. Go to options | encryption | security devices, and load your pkcs11 module. In windows it's c:\windows\system32\opensc-pkcs11.dll. Then you'll be able to choose a client certificate from the card.
When you're done configuring and testing the card, issue the following command to finalize the card:
pkcs15-init --finalize
TrueCrypt supports smart cards, but I have not figured out how to store a keyfile on the card. Yet.
And this assumes OpenVPN, Viscosity, and the cards are all engineered secure.