########################### Using Yubikey 4 for OpenVPN ########################### This is gross but it works. I use this stunt to avoid storing cryptographic keys in customized OpenWRT firmware images. Importing keys to card ###################### Readying Card For Use ===================== Follow instructions at https://developers.yubico.com/yubico-piv-tool/YubiKey_PIV_introduction.html to use ``yubico-piv-tool`` to personalize the PIV application (set admin keys, PUK, and PIN). That amounts to:: dd if=/dev/random bs=24 count=1 | hexdump -v -e '/1 "%02X"' > mgmt.key.hex yubico-piv-tool -a set-mgm-key -n `cat mgmt.key.hex` yubico-piv-tool -k `cat mgmt.key.hex` -a change-pin -P 123456 -N $NEW_PIN yubico-piv-tool -k `cat mgmt.key.hex` -a change-puk -P 12345678 -N $NEW_PUK Keep the management key only on the high side machine; the PIN will doubtless need to be on the low-side machine and the PUK may merit being on a midlingly-secure piece of paper. Importing Keys ============== I used slots 9a and 9d. The others claim to have some special features associated with them, but may be viable. (In particular, with a modern Yubikey and ``yubico-piv-tool`` program, 82-95 may be of interest, though I have not been able to test this.) Import the key and certificate to the slot of your choosing This is perhaps most easily done from a PKCS#12 file containing both key and certificate:: yubico-piv-tool -k `cat mgmt.key.hex` -s 9a -a import-key -a import-cert -K PKCS12 -i ${FILE}.p12 Note that the Yubikey has only 2005 bytes of storage for PKCS#11 material, which limits the number of keys that can exist on the device. I am not sure if the certificate has to be present for the key to be useful. Check the Card ############## Use ``pkcs11-tool`` to verify that the card is configured as you expect: * Show objects on card: ``pkcs11-tool -O`` * Read object to stdout from card by name: ``pkcs11-tool -r -y cert -a 'Certificate for Key Management'`` OpenVPN ####### Testing ======= Check that ``openvpn --show-pkcs11-ids /usr/lib/pkcs11/opensc-pkcs11.so`` sees your key(s). Caveats ======= * It is necessary to tell OpenVPN not to ``fork()``, as somewhere in OpenSC / pcsc-lite cannot deal with its clients forking. Thankfully, OpenVPN only forks to run scripts and ``ip`` and ``route``, which are not mandatory features for me. If they are for you, it is likely that things will have to be patched (ick; I'm sorry). In any case, use these directives in the config file :: ifconfig-noexec route-noexec and avoid the use of ``up``, ``down``, etc. * While you can (and I do) use two OpenVPN servers using two different keys on the same card, this is apparently far more fragile than it should be. Using ``--show-pkcs11-ids``, for example, will work but will cause all running daemons to be unable to do any more signatures ever, requiring restarts of the daemons. Don't do that, especially not remotely. * The use of OpenSC PKCS#11 is incompatible with GnuPG's scdaemon, which locks the card exclusively. This is incredibly annoying, meaning that although the card has both PIV and OpenPGP support, only one is usable at a time. I suppose the pain is less than the cost of another card. Configuration ============= Then, tell OpenVPN about OpenSC:: pkcs11-providers /usr/lib/pkcs11/opensc-pkcs11.so And use the output from ``--show-pkcs11-ids`` above to derive the appropriate ``pkcs11-id`` line. For me, that looks like :: pkcs11-id 'piv_II/PKCS\x2315\x20emulated/1e06775fbfccbb86/PIV_II\x20\x28PIV\x20Card\x20Holder\x20pin\x29/01' You may wish to use ``--management-query-passwords``, too, so that OpenVPN asks on its management interface for the card's PIN. Alternatively, I have :download:`a (gross) patch ` which adds an option (``--pkcs11-pinfile``) for reading the PIN in from a file. Thanks to Ondra Medek in https://openvpn.net/archive/openvpn-devel/2005-12/msg00014.html for pointing out what needed to change.