| |
| Testing PKCS11 on a development box |
| =================================== |
| |
| It's quite useful to be able to unit test and debug actual PKCS11 calls on |
| your dev machine. It saves the time of fumbling with the little netbook and |
| makes iteration much faster. |
| |
| Our typical z600's don't have a hardware TPM, but that's actually not a problem. |
| It turns out it's much easier to unit test with a software TPM, since they |
| never require hard reboots to clear the TPM. |
| |
| So, if you get to the point where you want to hack on pkcs11 calls on your |
| dev box, this document can help you get a working software TPM. |
| |
| Install "TPM Emulator" |
| ---------------------- |
| |
| TPM Emulator requires cmake, which wasn't installed on my machine. In addition, |
| the version of it that apt-get wanted to install was too old. I downloaded |
| the latest binary tarball from <http://www.cmake.org/cmake/resources/ |
| software.html> and expanded it on my local disk. I ran cmake using an |
| absolute path to the binary. You might want to properly install it in your |
| path somewhere, but I was in a rush. |
| |
| TPM Emulator also requires GMP, from <http://gmplib.org/>. This installed (on |
| the host, outside of the chroot) without a hitch. Just remember to build it |
| on the local disk so you can install it when it's done*. |
| |
| Finally, TPM Emulator comes with a kernel module, and needs your kernel |
| headers to compile it. In my case `sudo apt-get install |
| linux-headers-2.6.24-gg804006` did the trick. You are almost definitely |
| running a different version of the kernel. Check it with `uname -a`, find the |
| appropriate headers package, and install it. |
| |
| Once you've got the requirements installed, download the latest tarball from |
| <http://tpm-emulator.berlios.de/>. Build it on your machine, outside of the |
| chroot. Make sure to build it on the local disk, so you can |
| `sudo make install` when it's done*. The TPM Emulator page has build |
| instructions. In my case it went like: |
| |
| $ cd ~/local/src/tpm-emulator/ |
| $ mkdir build |
| $ cd build |
| $ ~/local/cmake/bin/cmake ../ |
| $ make install |
| |
| Once you've got that build, insert the kernel module. The module doesn't seem |
| to get installed as part of `make install`, so you need to install it from the |
| build directory... |
| |
| $ cd ~/local/src/tpm-emulator/ |
| $ sudo insmod build/tmpd_dev/linux/tmpd_dev.ko |
| |
| This kernel module appears to be a small redirector that sends requests from |
| /dev/tpm over to the Unix domain socket that the emulator will actually listen |
| to. You can verify that it was properly installed with... |
| |
| $ lsmod | grep tpmd_dev |
| |
| And remove it with... |
| |
| $ rmmod tpmd_dev |
| |
| But you don't want to remove it right now. Instead, continue on by starting |
| up the emulator. First, make a directory for the emulator to stash its |
| working state. The default location for the tpm emulator state clashes with |
| trousers, so you'll want to pick a new location. I used... |
| |
| $ mkdir ~/local/var/tpm/ |
| |
| Then, start up the daemon... |
| |
| $ sudo tpmd -f -d -s ~/local/var/tpm/ |
| |
| The -f argument tells it to run in the foreground, so you can easily stop it |
| with Ctrl-C if you want. The -d argument makes it print extra debugging info. |
| |
| *Note: On Google workstations, root can't access your NFS home directory. If |
| you're not using a Google workstation, or don't have an NFS mounted home |
| directory, this probably doesn't apply to you. |
| |
| Setup TrouSerS |
| -------------- |
| |
| Install TrouSerS if you don't already have it, using... |
| |
| $ sudo apt-get install trousers |
| |
| TrouSerS is an API over raw /dev/tpm access, so that applications can code to a |
| higher level of abstraction. Start it on your host (outside of the chroot) |
| with... |
| |
| $ sudo tcsd -f |
| |
| Now you can try actually poking at your tpm. Trousers comes with a set of |
| tpm utilities in /usr/sbin, though you don't actually need root to run them. |
| Start off with an easy one... |
| |
| $ /usr/sbin/tpm_version |
| TPM Version: 01010000 |
| Manufacturer Info: 4554485a |
| |
| Then... |
| |
| $ /usr/sbin/tpm_getpubek |
| Public Endorsement Key: |
| ... lots of stuff... |
| |
| If that all works, try taking ownership of the TPM... |
| |
| $ /usr/sbin/tpm_takeownership |
| |
| Enter 111111 (six ones) for both the owner and the Storage Root Key (SRK) |
| passwords. Now clear the SRK password... |
| |
| $ /usr/sbin/tmp_changeownerauth -s |
| Enter owner password: |
| Enter new SRK password: |
| Confirm password: |
| |
| Enter 111111 for the owner password, then leave the SRK password blank (just |
| press ENTER.) After this, check to be sure you actually have ownership, try |
| something like... |
| |
| $ /usr/sbin/tpm_setclearable -s |
| Enter owner password: |
| Owner Clear Disabled: false |
| Force Clear Disabled: false |
| |
| The -s means 'status', which will just print whether or not the TPM can be |
| cleared. If you get "Authentication failed", something is bad and you've got |
| to fix it. |
| |
| If it works, then it's time to try in the chroot, read on. |
| |
| The /dev/ tree in chroot is linked to /dev on your host. You should be able |
| to verify that /dev/tpm is the same in both places by running `ls -i /dev/tpm/` |
| in and out of the chroot. It should return the same inode number both times. |
| |
| Now enter your chroot and try tpm_setclearable again. This time though, |
| you're going to have to run the binary that was built for the target, using |
| something like... |
| |
| chroot$ scripts/run_32bit.sh /build/x86-generic/usr/sbin/tpm_setclearable -s |
| |
| The run_32bit.sh shell script just modifies your library path so that the |
| 32 bit libraries come first, so that you can run things that were built for |
| the 32 bit image. |
| |
| The tpm_setclearable command should work exactly the same as it did outside of |
| the chroot. If so, go get a coffee, a smoke, or go for a run around the block. |
| You're getting close. |
| |
| PKCS#11, OpenCryptoki, and You |
| ------------------------------ |
| |
| PKCS#11 defines an API for talking to cryptographic smart cards, or "tokens". |
| These tokens are hardware that can perform cryptographic operations. They are |
| used for things like... |
| |
| * Generating a secure keypair on the hardware, without revealing the |
| private portion of the key. Both the public and private key reside |
| in some form of NVRAM on the token, but the token may only reveal the |
| public key. |
| * Perform on-chip encryption or decryption using the keypair. |
| * Storing arbitrary application data on-chip in public or password |
| protected NVRAM. |
| |
| The API assumes that your machine has one or more slots, which can each |
| contain a token. Not all tokens support all operations, and the API has |
| a way to query the token to find out what it supports. |
| |
| OpenCryptoki is an implementation of the PKCS#11 API specification. It can |
| be used to talk to real hardware tokens, but it also comes with a software |
| based token that uses the TPM to encrypt an on-disk database of the token's |
| NVRAM. This software based token is what the Enterprise Daemon uses to |
| store VPN and 802.1x certificates. |
| |
| Setup OpenCryptoki |
| ------------------ |
| |
| From here on out, we'll be working in the chroot. We have a particular version |
| of openCryptoki in there, and it's sometimes a finicky piece of software to |
| work with. |
| |
| Before you get started, make sure you've built a recent tree, and that it works. |
| It's helpful to know that whatever you've got built in the chroot is sane, so |
| go ahead and build an image and boot it on a device. |
| |
| Then, from inside the chroot, add yourself to the pkcs11 group. Something |
| like... |
| |
| chroot$ sudo /usr/sbin/usermod -a -G pkcs11 $USER |
| |
| ( The pkcs11 group should be made as part of the build. If you don't have it ) |
| ( try exiting the chroot and re-entering. ) |
| |
| Then exit the chroot and come back in, to make sure it took affect. Prove it |
| to yourself with something like... |
| |
| chroot$ groups | grep pkcs11 |
| |
| Now you'll need to create the virtual slot with the TPM based virtual token... |
| |
| chroot$ cd ~/trunk/src/scripts |
| chroot$ sudo ./run32_bit.sh /build/x86-generic/usr/sbin/pkcs_slot -- 0 tpm |
| |
| ( A lot of the commands in this part require the run32_bit.sh script. You ) |
| ( can save yourself some typing by running `./run32_bit.sh bash`, so that ) |
| ( the environment variable changes live for the life of the new bash shell. ) |
| ( When you're done, press Ctrl-D to return back to the previous ) |
| ( environment. ) |
| |
| The pkcs_slot script from OpenCryptoki is written in Bash, you can peek |
| inside if you're curious what it really does. |
| |
| The pkcsslotd program expects to be run from /usr/sbin, but in the chroot |
| it is built into /build/x86-generic/usr/sbin. A symlink will fix that... |
| |
| chroot$ cd /usr/sbin/ |
| chroot$ sudo ln -s /build/x86-generic/usr/sbin/pkcsslotd . |
| |
| Now start pkcsslotd with... |
| |
| chroot$ cd ~/trunk/src/scripts |
| chroot$ sudo run_32bit.sh /usr/sbin/pkcsslotd |
| |
| This should start without issue, and you can move on to some quick tests... |
| |
| chroot$ ./run_32bit.sh /build/x86-generic/usr/sbin/pkcsconf -- -i |
| PKCS#11 Info |
| ... |
| |
| chroot$ ./run_32bit.sh /build/x86-generic/usr/sbin/pkcsconf -- -s |
| Slot #0 Info |
| ... |
| |
| chroot$ ./run_32bit.sh /build/x86-generic/usr/sbin/pkcsconf -- -t |
| Token #0 Info: |
| ... |
| Flags: 0x880045 (RNG|LOGIN_REQUIRED|CLOCK_ON_TOKEN|USER_PIN_TO_BE_CHANGED| |
| SO_PIN_TO_BE_CHANGED) |
| ... |
| |
| Notice the flags associated with the token. The fact that it is missing |
| TOKEN_INITIALIZED means that the token hasn't yet been set up. Also notice |
| USER_PIN_TO_BE_CHANGED and SO_PIN_TO_BE_CHANGED, which mean that our token |
| these PINs (numeric passwords) to be changed. Tpmtoken_init helps with that... |
| |
| chroot$ ./run_32bit.sh /build/x86-generic/usr/bin/tpmtoken_init |
| A new TPM security officer password is needed. The password must be between |
| 6 and 127 characters in length. |
| Enter new password: |
| |
| Type 111111 (six ones) and press enter. When this completes the tokens |
| flags should be different... |
| |
| chroot$ ./run_32bit.sh /build/x86-generic/usr/sbin/pkcsconf -- -t |
| Token #0 Info: |
| ... |
| Flags: 0x44D (RNG|LOGIN_REQUIRED|USER_PIN_INITIALIZED|CLOCK_ON_TOKEN| |
| TOKEN_INITIALIZED) |
| ... |
| |
| Now we have TOKEN_INITIALIZED, and the PINs no longer need to be changed. |
| Now list out all of the object stored on the token... |
| |
| $ ./run_32bit.sh /build/x86-generic/usr/bin/tpmtoken_objects |
| Enter your TPM user password: |
| No objects found |
| |
| And there you go! We haven't put anything on the token yet, so there is |
| nothing to list. You're now ready to unit tests that require a functioning |
| PKCS#11 device, without having to copy them to the netbook, or reboot to |
| clear your TPM. |
| |
| Troubleshooting |
| --------------- |
| |
| Don't forget to remove the SRK password as described above. If you do forget, |
| you'll get a 0x6 error (CKR_FUNCTION_FAILED) when you try to initialize the |
| token. |
| |
| If you're getting 0x2 (CKR_HOST_MEMORY) errors, you probably aren't in the |
| pkcs11 group, or pkcsslotd hasn't started. |
| |
| The openCryptoki website is absolutely awful. It's basically a blank page that |
| looks like it should have some information in it, but doesn't. There is |
| a little documentation in the source though. Start with the FAQ: |
| <http://opencryptoki.git.sourceforge.net/git/gitweb.cgi?p=opencryptoki/ |
| opencryptoki;a=blob_plain;f=FAQ;hb=HEAD>. |
| |
| For more information on the PKCS#11 API see the RSA website <http://www.rsa.com/ |
| rsalabs/node.asp?id=2133>. Specifically, the PKCS#11 Core Specification, which |
| is not as daunting as it looks at first. |
| |
| For a little more nitty gritty, open /build/x86-generic/usr/include/ |
| opencryptoki/pkcs11types.h in your editor. This can be a handy way to map |
| hexadecimal error codes to their mnemonics when things go wrong. |
| |
| If you get sideways and want to start from scratch, here are the things you |
| might want to remove (it's probably a good idea to stop the daemons that might |
| have open file handles before removing this stuff): |
| |
| * Outside of the chroot, tpmd is going to store some state wherever you told |
| it to with the -s option. This document recommended ~/local/var/tpm. |
| * Also outside of the chroot, the TrouSerS daemon tcsd stores some state in |
| /var/lib/tpm/. |
| * Inside the chroot, pkcsslotd stores your token data under |
| /var/lib/opencryptoki/... |
| - The pk_config_data file is a manifest of slots, created by pkcs_slot. |
| - The tpm/ directory contains per-user NVRAM for the TPM backed slot. If |
| you're going to delete this, make sure the entire user directory goes |
| away. The pkcs_slot script won't correctly repopulate the directory if |
| it finds some leftovers from a previous run. |
| |