OLD | NEW |
(Empty) | |
| 1 |
| 2 Testing PKCS11 on a development box |
| 3 =================================== |
| 4 |
| 5 It's quite useful to be able to unit test and debug actual PKCS11 calls on |
| 6 your dev machine. It saves the time of fumbling with the little netbook and |
| 7 makes iteration much faster. |
| 8 |
| 9 Our typical z600's don't have a hardware TPM, but that's actually not a problem. |
| 10 It turns out its much easier to unit test with a software TPM, since they |
| 11 never require hard reboots to clear the TPM. |
| 12 |
| 13 So, if you get to the point where you want to hack on pkcs11 calls on your |
| 14 dev box, this document can help you get a working software TPM. |
| 15 |
| 16 Install "TPM Emulator" |
| 17 ---------------------- |
| 18 |
| 19 TPM Emulator requires cmake, which wasn't installed on my machine. In addition, |
| 20 the version of it that apt-get wanted to install was too old. I downloaded |
| 21 the latest binary tarball from <http://www.cmake.org/cmake/resources/ |
| 22 software.html> and expanded it on my local disk. I ran cmake using an |
| 23 absolute path to the binary. You might want to properly install it in your |
| 24 path somewhere, but I was in a rush. |
| 25 |
| 26 TPM Emulator also requires GMP, from <http://gmplib.org/>. This installed (on |
| 27 the host, outside of the chroot) without a hitch. Just remember to build it |
| 28 on the local disk so you can install it when its done*. |
| 29 |
| 30 Finally, TPM Emulator comes with a kernel module, and needs your kernel |
| 31 headers to compile it. In my case `sudo apt-get install |
| 32 linux-headers-2.6.24-gg804006` did the trick. You are almost definitely |
| 33 running a different version of the kernel. Check it with `uname -a`, find the |
| 34 appropriate headers package, and install it. |
| 35 |
| 36 Once you've got the requirements installed, download the latest tarball from |
| 37 <http://tpm-emulator.berlios.de/>. Build it on your machine, outside of the |
| 38 chroot. Make sure to build it on the local disk, so you can |
| 39 `sudo make install` when its done*. The TPM Emulator page has build |
| 40 instructions. In my case it went like: |
| 41 |
| 42 $ cd ~/local/src/tpm-emulator/ |
| 43 $ mkdir build |
| 44 $ cd build |
| 45 $ ~/local/cmake/bin/cmake ../ |
| 46 $ make install |
| 47 |
| 48 Once you've got that build, insert the kernel module. The module doesn't seem |
| 49 to get installed as part of `make install`, so you need to install it from the |
| 50 build directory... |
| 51 |
| 52 $ cd ~/local/src/tmp-emulator/ |
| 53 $ sudo insmod build/tmpd_dev/linux/tmpd_dev.ko |
| 54 |
| 55 This kernel module appears to be a small redirector that sends requests from |
| 56 /dev/tpm over to the Unix domain socket that the emulator will actually listen |
| 57 to. You can verify that it was properly installed with... |
| 58 |
| 59 $ lsmod | grep tpmd_dev |
| 60 |
| 61 And remove it with... |
| 62 |
| 63 $ rmmod tpmd_dev |
| 64 |
| 65 But you don't want to remove it right now. Instead, continue on by starting |
| 66 up the emulator. First, make a directory for the emulator to stash its |
| 67 working state. The default location for the tpm emulator state clashes with |
| 68 trousers, so you'll want to pick a new location. I used... |
| 69 |
| 70 $ mkdir ~/local/var/tpm/ |
| 71 |
| 72 Then, start up the daemon... |
| 73 |
| 74 $ sudo tpmd -f -d -s ~/local/var/tpm/ |
| 75 |
| 76 The -f argument tells it to run in the foreground, so you can easily stop it |
| 77 with Ctrl-C if you want. The -d argument makes it print extra debugging info. |
| 78 |
| 79 *Note: On Google workstations, root can't access your NFS home directory. If |
| 80 you're not using a Google workstation, this probably doesn't apply to you. |
| 81 |
| 82 Setup TrouSerS |
| 83 -------------- |
| 84 |
| 85 Install TrouSerS if you don't already have it, using... |
| 86 |
| 87 $ sudo apt-get install trousers |
| 88 |
| 89 TrouSerS is an API over raw /dev/tpm access, so that applications can code to a |
| 90 higher level of abstraction. Start it on your host (outside of the chroot) |
| 91 with... |
| 92 |
| 93 $ sudo tcsd -f |
| 94 |
| 95 Now you can try actually poking at your tpm. Trousers comes with a set of |
| 96 tpm utilities in /usr/sbin, though you don't actually need root to run them. |
| 97 Start off with an easy one... |
| 98 |
| 99 $ /usr/sbin/tpm_version |
| 100 TPM Version: 01010000 |
| 101 Manufacturer Info: 4554485a |
| 102 |
| 103 Then... |
| 104 |
| 105 $ /usr/sbin/tpm_getpubek |
| 106 Public Endorsement Key: |
| 107 ... lots of stuff... |
| 108 |
| 109 If that all works, try taking ownership of the TPM... |
| 110 |
| 111 $ /usr/sbin/tpm_takeownership |
| 112 |
| 113 Enter 111111 (six ones) for both the owner and the Storage Root Key (SRK) |
| 114 passwords. Now clear the SRK password... |
| 115 |
| 116 $ /usr/sbin/tmp_changeownerauth -s |
| 117 Enter owner password: |
| 118 Enter new SRK password: |
| 119 Confirm password: |
| 120 |
| 121 Enter 111111 for the owner password, then leave the SRK password blank (just |
| 122 press ENTER.) After this, check to be sure you actually have ownership, try |
| 123 something like... |
| 124 |
| 125 $ /usr/sbin/tpm_setclearable -s |
| 126 Enter owner password: |
| 127 Owner Clear Disabled: false |
| 128 Force Clear Disabled: false |
| 129 |
| 130 The -s means 'status', which will just print whether or not the TPM can be |
| 131 cleared. If you get "Authentication failed", something is bad and you've got |
| 132 to fix it. |
| 133 |
| 134 If it works, then it's time to try in the chroot, read on. |
| 135 |
| 136 The /dev/ tree in chroot is linked to /dev on your host. You should be able |
| 137 to verify that /dev/tpm is the same in both places by running `ls -i /dev/tpm/` |
| 138 in and out of the chroot. It should return the same inode number both times. |
| 139 |
| 140 Now enter your chroot and try tpm_setclearable again. This time though, |
| 141 you're going to have to run the binary that was built for the target, using |
| 142 something like... |
| 143 |
| 144 chroot$ scripts/run_32bit.sh /build/x86-generic/usr/sbin/tpm_setclearable -s |
| 145 |
| 146 The run_32bit.sh shell script just modifies your library path so that the |
| 147 32 bit libraries come first, so that you can run things that were build for |
| 148 the 32 bit image. |
| 149 |
| 150 The tpm_setclearable command should work exactly the same as it did outside of |
| 151 the chroot. If so, go get a coffee, a smoke, or go for a run around the block. |
| 152 You're getting close. |
| 153 |
| 154 PKCS#11, OpenCryptoKi, and You |
| 155 ------------------------------ |
| 156 |
| 157 PKCS#11 defines an API for talking to cryptographic smart cards, or "tokens". |
| 158 These tokens are hardware that can perform cryptographic operations. They are |
| 159 used for things like... |
| 160 |
| 161 * Generating a secure keypair on the hardware, without revealing the |
| 162 private portion of the key. Both the public and private key reside |
| 163 in some form of NVRAM on the token, but the token may only reveal the |
| 164 public key. |
| 165 * Perform on-chip encryption or decryption using the keypair. |
| 166 * Storing arbitrary application data on-chip in public or password |
| 167 protected NVRAM. |
| 168 |
| 169 The API assumes that your machine has one or more slots, which can each |
| 170 contain a token. Not all tokens support all operations, and the API has |
| 171 a way to query the token to find out what it supports. |
| 172 |
| 173 OpenCryptoKi is an implementation of the PKCS#11 API specification. It can |
| 174 be used to talk to real hardware tokens, but it also comes with a software |
| 175 based token that uses the TPM to encrypt an on-disk database of the token's |
| 176 NVRAM. This software based token is what the Enterprise Daemon uses to |
| 177 store VPN and 802.1x certificates. |
| 178 |
| 179 Setup OpenCryptoKi |
| 180 ------------------ |
| 181 |
| 182 From here on out, we'll be working in the chroot. We have a particular version |
| 183 of opencryptoki in there, and it's sometimes a finicky piece of software to |
| 184 work with. |
| 185 |
| 186 Before you get started, make sure you've built a recent tree, and that it works. |
| 187 It's helpful to know that whatever you've got built in the chroot is sane, so |
| 188 go ahead and build an image and boot it on a device. |
| 189 |
| 190 Then, from inside the chroot, add yourself to the pkcs11 group. Something |
| 191 like... |
| 192 |
| 193 chroot$ sudo /usr/sbin/usermod -a -G pkcs11 $USER |
| 194 |
| 195 ( The pkcs11 group should be made as part of the build. If you don't have it ) |
| 196 ( try exiting the chroot and re-entering. ) |
| 197 |
| 198 Then exit the chroot and come back in, to make sure it took affect. Prove it |
| 199 to yourself with something like... |
| 200 |
| 201 chroot$ groups | grep pkcs11 |
| 202 |
| 203 Now you'll need to create the virtual slot with the TPM based virtual token... |
| 204 |
| 205 chroot$ cd ~/trunk/src/scripts |
| 206 chroot$ sudo ./run32_bit.sh /build/x86-generic/usr/sbin/pkcs_slot -- 0 tpm |
| 207 |
| 208 ( A lot of the commands in this part require the run32_bit.sh script. You ) |
| 209 ( can save yourself some typing by running `./run32_bit.sh bash`, so that ) |
| 210 ( the environment variable changes live for the life of the new bash shell. ) |
| 211 ( When you're done, press Ctrl-D to return back to the previous ) |
| 212 ( environment. ) |
| 213 |
| 214 The pkcs_slot script from OpenCryptoKi is written in Bash, you can peek |
| 215 inside if you're curious what it really does. |
| 216 |
| 217 The pkcsslotd program expects to be run from /usr/sbin, but in the chroot |
| 218 it is built into /build/x86-generic/usr/sbin. A symlink will fix that... |
| 219 |
| 220 chroot$ cd /usr/sbin/ |
| 221 chroot$ sudo ln -s /build/x86-generic/usr/sbin/pkcsslotd . |
| 222 |
| 223 Now start pkcsslotd with... |
| 224 |
| 225 chroot$ cd ~/trunk/src/scripts |
| 226 chroot$ sudo run_32bit.sh /usr/sbin/pkcsslotd |
| 227 |
| 228 This should start without issue, and you can move on to some quick tests... |
| 229 |
| 230 chroot$ ./run_32bit.sh /build/x86-generic/usr/sbin/pkcsconf -- -i |
| 231 PKCS#11 Info |
| 232 ... |
| 233 |
| 234 chroot$ ./run_32bit.sh /build/x86-generic/usr/sbin/pkcsconf -- -s |
| 235 Slot #0 Info |
| 236 ... |
| 237 |
| 238 chroot$ ./run_32bit.sh /build/x86-generic/usr/sbin/pkcsconf -- -t |
| 239 Token #0 Info: |
| 240 ... |
| 241 Flags: 0x880045 (RNG|LOGIN_REQUIRED|CLOCK_ON_TOKEN|USER_PIN_TO_BE_CHANGED| |
| 242 SO_PIN_TO_BE_CHANGED) |
| 243 ... |
| 244 |
| 245 Notice the flags associated with the token. The fact that it is missing |
| 246 TOKEN_INITIALIZED means that the token hasn't yet been set up. Also notice |
| 247 USER_PIN_TO_BE_CHANGED and SO_PIN_TO_BE_CHANGED, which mean that our token |
| 248 these PINs (numeric passwords) to be changed. Tpmtoken_init helps with that... |
| 249 |
| 250 chroot$ ./run_32bit.sh /build/x86-generic/usr/bin/tpmtoken_init |
| 251 A new TPM security officer password is needed. The password must be between |
| 252 6 and 127 characters in length. |
| 253 Enter new password: |
| 254 |
| 255 Type 111111 (six ones) and press enter. When this completes the tokens |
| 256 flags should be different... |
| 257 |
| 258 chroot$ ./run_32bit.sh /build/x86-generic/usr/sbin/pkcsconf -- -t |
| 259 Token #0 Info: |
| 260 ... |
| 261 Flags: 0x44D (RNG|LOGIN_REQUIRED|USER_PIN_INITIALIZED|CLOCK_ON_TOKEN| |
| 262 TOKEN_INITIALIZED) |
| 263 ... |
| 264 |
| 265 Now we have TOKEN_INITIALIZED, and the PINs no longer need to be changed. |
| 266 Now list out all of the object stored on the token... |
| 267 |
| 268 $ ./run_32bit.sh /build/x86-generic/usr/bin/tpmtoken_objects |
| 269 Enter your TPM user password: |
| 270 No objects found |
| 271 |
| 272 And there you go! We haven't put anything on the token yet, so there is |
| 273 nothing to list. You're now ready to unit tests that require a functioning |
| 274 PKCS#11 device, without having to copy them to the netbook, or reboot to |
| 275 clear your TPM. |
| 276 |
| 277 Troubleshooting |
| 278 --------------- |
| 279 |
| 280 Don't forget to remove the SRK password as described above. If you do forget, |
| 281 you'll get a 0x6 error (CKR_FUNCTION_FAILED) when you try to initialize the |
| 282 token. |
| 283 |
| 284 If you're getting 0x2 (CKR_HOST_MEMORY) errors, you probably aren't in the |
| 285 pkcs11 group, or pkcsslotd hasn't started. |
| 286 |
| 287 The openCryptoki website is absolutely awful. It's basically a blank page that |
| 288 looks like it should have some information in it, but doesn't. There is |
| 289 a little documentation in the source though. Start with the FAQ: |
| 290 <http://opencryptoki.git.sourceforge.net/git/gitweb.cgi?p=opencryptoki/ |
| 291 opencryptoki;a=blob_plain;f=FAQ;hb=HEAD>. |
| 292 |
| 293 For more information on the PKCS#11 API see the RSA website <http://www.rsa.com/ |
| 294 rsalabs/node.asp?id=2133>. Specifically, the PKCS#11 Core Specification, which |
| 295 is not as daunting as it looks at first. |
| 296 |
| 297 For a little more nitty gritty, open /build/x86-generic/usr/include/ |
| 298 opencryptoki/pkcs11types.h in your editor. This can be a handy way to map |
| 299 hexadecimal error codes to their mnemonics when things go wrong. |
| 300 |
| 301 If you get sideways and want to start from scratch, here are the things you |
| 302 might want to remove (it's probably a good idea to stop the daemons that might |
| 303 have open file handles before removing this stuff): |
| 304 |
| 305 * Outside of the chroot, tpmd is going to store some state wherever you told |
| 306 it to with the -s option. This document recommended ~/local/var/tpm. |
| 307 * Also outside of the chroot, the TrouSerS daemon tcsd stores some state in |
| 308 /var/lib/tpm/. |
| 309 * Inside the chroot, pkcsslotd stores your token data under |
| 310 /var/lib/opencryptoki/... |
| 311 - The pk_config_data file is a manifest of slots, created by pkcs_slot. |
| 312 - The tpm/ directory contains per-user NVRAM for the TPM backed slot. If |
| 313 you're going to delete this, make sure the entire user directory goes |
| 314 away. The pkcs_slot script won't correctly repopulate the directory if |
| 315 it finds some leftovers from a previous run. |
| 316 |
OLD | NEW |