Freitag, 3. Juli 2015

Adventures in PKI


Disclaimer: This text is a collection of observations and complaints about the state of PKI in general, PKCS#11 in particular, and about some software products. Let me preface that the provider of the cryptotoken (and software) that this text is based on has three things in their favor: 1. Their products work, 2. Their support is good, 3. Their products work.
It cannot be stressed enough that spending lots of money on crypto hardware is no guarantee whatsoever that what you get works, or works better, or is better supported.

The goal

Save important secrets in a cryptotoken to be safe from theft of file based secrets.

Ideal turn of events

  1. Acquire cryptotoken at an affordable price (under 20$)
  2. Generate Keypair(s) on cryptotoken
  3. Simply point SSH and GPG at cryptotoken instead of file based secrets
  4. Profit! I will now know that I have lost my secrets when I lose the physical token. But then I know I have to take action and can safely revoke trust in any of the data that was on the token.
Sounds great, right?

Actual turn of events

  1. Cheap cryptotokens are available, but you might not want to buy the cheapest ones as they're built by people with a reputation of coordinating with Nation State Attackers. Also, they don't work. If you need a working Cryoptotoken, the price is at 25$ plus shipping for a slow one where some features are disabled.
  2. Generating the keys on the cryptotoken is pretty easy. But only if you forgo the vendor software and dive right back into the world of dynamically loading c libraries into command line tools you might need to build from scratch because the ones that come with your computer are broken or outdated or both. And if your command line tool's test run crashes and burns with a segfault, it's probably not a big deal; you won't know whether it's your command line tool, your token, or the library module interfacing between the two that's messing things up. You probably don't want to use that specific operation anyway.
With SSH, this should be relatively straightforward:
    eval $(ssh-agent -s)
    ssh-add -s /path/to/cryptotoken_pkcs.dylib
    ssh-copy-id user@target # to copy over the token backed public key
    ssh user@target # to try the new hotness
In reality, if you're on a Mac, trying the ssh-add line above triggers a bug ssh-agent will forkbomb you with ssh-pkcs11-helper processes. So if you were a purist before, this is where you go and turn to homebrew for help. Even Yubico mentions this in their official documentation!
OK, you rebuilt all of ssh, modified your environment so that your bespoke ssh client and associated programs run instead of the system provided one. That was almost straightforward.
Do you like to poke your eye out with a rusty nail? Then you will also like the hoops you have to jump through to get GPG to talk to your cryptotoken.
Don't worry that the gnupg-pkcs11-scd software is hosted on a site that's turned so toxic in the four years since the last update to the software that any decent ad blocker will warn you not to go there. Don't worry that you have to run openssl with a dynamically loaded pkcs11 engine which you need to configure in arcane ways even for UNIX standards. Don't worry at all that you may need to manually kill the already running gpg-agent so a new one that knows it needs to talk to the smart card daemon which talkes PGPCard in the direction of gnupg and PKCS11 in the direction of your cryptotoken. Don't worry that the man page for said daemon mentions that the protocol the different components use is unprotected plaintext. Just don't worry, and be enlightened why even smart people stick with file based secrets.

In the future

Just hope that you have the instructions how to renew the certificate you need to emulate the PGP card when your key eventually expires. Just hope that you will never need to import another pre-existing keypair to save it from prying eyes. Just hope that apparently everyone who decided to give up was right to do so.


  1. Buy cryptotoken at they're affordable and deliver quickly.
  2. Download and install their software (but see the Apocrypha below) and reboot.
  3. I hid step 3 at the end of the previous step.
  4. Using homebrew, install (at the bare minimum)
    • homebrew/dupes/openssh (for non-broken PKCS#11 support)
    • opensc (for pkcs11-tool)
    • openssl (because Apple provides a randomly patched OpenSSL 0.9.8 ...)
    • engine_pkcs11(to sign your cert with the key in the token for PGP)
  5. Initialize your token and set your PINs. Don't forget that PINs do not need to be numbers, you can actually use proper password like strings. Depending on your token, you may run into strange limitations like maximum length.
  6. On the token, generate a keypair. Don't forget to set a key label and id. Do not despair if your token has limits on RSA bit size
  7. With engine_pkcs11, coax openssl into signing a Certificate Signing Request with the key material on the token. I followed random, ancient instructions and things worked, but it's quite a brittle procedure.
  8. As it doesn't seem to be possible to save the signed cert into the token directly, import the cert into your token. Don't forget to set a label and id identical to the keys above, or gnupg_pkcs11_scd will not work.
  9. Go through the five step procedure to get the hash that gnupg_pkcs11_scd needs to fake the PGPCard side of the deal. I followed some other random, ancient instructions, ignoring everything before "Use eToken with GnuPG", since the instructions begin creating the secrets in files and then importing them, kind of defeating the purpose of having keys in a secure token. I still don't fully understand why gpg --card-status says I can only use my key for auth, but then the website states Don’t worry about the missing encryption key, actually it is same as the auth key.
  10. Create a revocation cert for your on-token GPG key in case you lose the token. You want to be able to tell the world when you stop being identified by it. Or don't, because why should they trust anyone claiming that a key isn't in use anymore if that information is signed by another key with no history.
  11. Make sure that all the necessary agents and stuff are automatically loaded and correctly configured. This is where I seriously consider self-managing stuff with puppet, and/or storing pertinent information on the crypto token so I am less likely to lose it. I should have backups somewhere anyway ...


So, step two in the instructions looks quite innocuous, but I am used from previous and current engagements to check out what Mac installers, especially by companies that are not Mac shops, do. Luckily, most of the installer stuff is preserved in /etc/Athena. Let's take a look:
hwagener:~ hwagener$ cd /etc/Athena/
hwagener:Athena hwagener$ ls -la
total 232
drwxr-xr-x  13 root  wheel    442  2 Jul 23:38 .
drwxr-xr-x  90 root  wheel   3060  3 Jul 00:31 ..
-rwxrwxrwx   1 root  wheel  85852  1 Mai  2014 EditPInfoList
-rwxrwxrwx   1 root  wheel   2087 14 Mai  2013 IDPClientDB.xml
-rwxrwxrwx   1 root  wheel   2411  7 Apr  2013 IDProtectManager.png
-rwxrwxrwx   1 root  wheel   1029 14 Feb  2013 IDProtectPINTool.png
-rwxrwxrwx   1 root  wheel    160 20 Jun  2013 Manager
-rwxrwxrwx   1 root  wheel   2606 19 Jun  2013 Mozilla
-rwxrwxrwx   1 root  wheel    159 20 Jun  2013 PinTool
-rwxrwxrwx   1 root  wheel   1823  5 Mai 15:01 postflight
drwxrwxrwx   3 root  wheel    102  2 Jul 14:36 ppc
-rwxrwxrwx   1 root  wheel   3104 20 Jun  2013 uninstall
drwxrwxrwx   3 root  wheel    102  2 Jul 14:36 x86
hwagener:Athena hwagener$
Don't worry for now that we have root-owned world writable binaries and other files here. Don't worry that the installer packs it's own EditPInfoList even though /usr/libexec/PlistBuddy and plutil exist. I'll get back to that in a bit, let's first bask in a little taste of what all this does:
hwagener:Athena hwagener$ cat PinTool
for i in $(dscl . list /Users UniqueID | grep -v Old | awk '$2 >= 500') ; do  ln -s /Applications/  /Users/$i/Desktop/PINTool ; done
Yes, that one-liner creates a symlink on the Desktop of all users pointing to the PinTool. +1 Point for using dscl . list /Users, -5 points for lamely assuming that all UIDs > 500 are game for this. 'Manager' does the same, only for the card manager. The Mozilla script does abominable things and still references PPC architecture. What year is it?! Oh, and -100,000,000 points for not allowing you to disable this in the installer in the first place!
OK, these are small little scripts that try to be nice and set up things for users so it works easily when you use Firefox. But the real nuggets are in the postflight script.
  • Patching system files that may be clobbered by any upcoming OS updates. Will this even continue working in OS X 10.11?
    sudo "/etc/Athena/EditPInfoList" "0x0DC3" "0x1004" "Athena ASEDrive CCID"  "/usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist"
    sudo "/etc/Athena/EditPInfoList" "0x0DC3" "0x1007" "Athena ASEDrive IIIe KB BIO-PIV" "/usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist"
    sudo "/etc/Athena/EditPInfoList" "0x0DC3" "0x0900" "Athena IDProtect Key" "/usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist"
    sudo "/etc/Athena/EditPInfoList" "0x0DC3" "0x1102" "Athena ASEDrive IIIe KB" "/usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist"
    sudo "/etc/Athena/EditPInfoList" "0x0DC3" "0x100F" "Athena ASEKey CCID" "/usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist"
    sudo "/etc/Athena/EditPInfoList" "0x24DC" "0x0101" "Aladdin RD JaCarta PKI" "/usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist"
    sudo "/etc/Athena/EditPInfoList" "0x24DC" "0x100F" "Aladdin RD JaCarta PKI Flash" "/usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist"
  • Creating random directories in the home directory of the user that originally started the installer. And then copies random XML files in there:
    if [ ! -d $HOME/.ase ]
            mkdir -p $HOME/.ase
    ls -l *.xml
    mv -f /private/tmp/*.xml "$HOME/.ase"
    The one file that will end up in $HOME/.ase on a non-hostile system is IDPClientDB.xml, but it looks eminently different than /etc/Athena/IDPClientDB.xml
  • Deleting random directories in the home directory of the user that originally started the installer
    if [ -f "$HOME/real_fox" ]
    export DB_PATH=`cat "$HOME/temp_path"`
    if [ -f "$HOME/real_fox" ]
            rm "$HOME/real_fox"
    if [ -f "$HOME/temp_path" ]
            rm "$HOME/temp_path"
  • Hiding cleanup jobs to remove another application's configuration. This is great for people that need backwards compatibility, I guess?
    if [ -f "/Library/Application Support/Athena/SCLauncher" ]
    rm "/Library/Application Support/Athena/SCLauncher"
    if [ -f "/Library/LaunchAgents/SCLauncher.plist" ]
    rm "/Library/LaunchAgents/SCLauncher.plist"
In a nutshell, if you need to deploy this in a managed environment, you want to try to isolate the necessary steps and re-roll the install package so that:
  • Only the necessary files are installed (I omitted that the pin tool and manager bring their own QT and plunk that somewhere in /usr/local; the only reason to keep them around is that you cannot reset the SO-PIN with pkcs11-tool — you need the proprietary PinTool for that.).
  • Changes to system files are self-contained and can be re-done after OS updates without having to effectively re-run a bunch of hostile shell scripts.
  • The package can be managed with the likes of munki and that uninstalls are possible.
By the way, the real bad news is that all this is not as bad as I've seen before from other security companies that realized their business model should embrace Apple products.