A TPM for Everyone

Written in February 2009

Introduction

In the past, I've talked about the Trusted Platform Module (TPM) and Trusted Computing in the context of Mac OS X.

"Trusted" Computing is usually a contentious topic and the actual utility of a TPM is often overshadowed by a never-ending litany of "what-if" scenarios that have been brought up over time. The Mac OS X specific gist of this is that although the early x86-based Macintosh computers had onboard TPMs, Apple stopped including TPMs in Macintoshes roughly around the time the Mac Pro was introduced. In contrast, it is quite common to find TPMs in modern day non-Apple computers. There are several interesting and useful things one can do with a TPM on any operating system. It is rather disappointing that a modern Macintosh is devoid of this device.

The Next Best Thing to a TPM

Suppose you have a Macintosh without a TPM and you really do want to experiment with Trusted Computing or features of the TPM in general. Your needs could be development-related or they could be purely academic. Well, you could do the next best thing to having a real TPM: you can use a software TPM emulator. One such open-source emulator has been around for some time and it is straightforward to make it run on Mac OS X.

The TPM emulator is implemented as a daemon that encapsulates most of the functionality of a physical TPM. Out of the box, the TPM emulator will need to be accessed on Mac OS X through an intermediate library—the equivalent of the TPM Device Driver Library (TDDL). It would be nice if all existing TPM-related software used the TDDL interface, but often that's not the case. Instead, software that uses the TPM might want to directly access the TPM device. The Mac OS X TPM device driver I wrote in 2006 for the Infineon TPM chip provides a /dev/tpm device node, which is then used by all the other TPM tools and libraries I ported to Mac OS X. Therefore, it would be really useful if, in addition to the TPM emulator daemon, we had something that provides a /dev/tpm that behaves like the "real thing".

That something would be a Mac OS X kernel extension. It would publish a /dev/tpm device node just like the "real" TPM device driver. However, instead of communicating with the TPM hardware (which does not exist), this kernel extension would communicate with the TPM emulator daemon running in user space. I'm releasing the source code for such a kernel extension—let us call it the TPM Emulator Device Bridge Kernel Extension. Let us see how to set everything up so that we have a /dev/tpm that's functional enough to work seamlessly with TPM-based software.

Setting Up a Software TPM

First, we check out the source code for the TPM emulator from its subversion tree. We will assume that our working directory is /work/tpm/.

$ cd /work/tpm/ $ svn checkout svn://svn.berlios.de/tpm-emulator/trunk tpm-emulator ... $ cd tpm-emulator

Next, download the TPM emulator patch from the Download section of this page. You can apply the patch and compile the emulator as follows.

$ pwd /work/tpm/tpm-emulator $ patch -p0 < /path/to/tpm-emulator-0.5-macosx.patch patching file tpm/tpm_deprecated.c patching file tpmd/tpm_emulator_config.h patching file tpmd/tpmd.c patching file tddl/tddl.c patching file tddl/Makefile patching file Makefile $ make ...

Now download and compile the TPM Device Bridge kernel extension.

$ cd /work/tpm/ $ tar -xzvf /path/to/tpm_bridge.tar.gz $ cd tpm_bridge $ xcodebuild -target tpm_bridge -configuration Release ... ** BUILD SUCCEEDED ** $

We can now load the newly compiled kernel extension. Mac OS X has specific requirements on the ownership and permissions of kernel extension bundles.

$ pwd /work/tpm/tpm_bridge $ cp -pR build/Release/tpm_bridge.kext /tmp/ $ sudo chown -R root:wheel /tmp/tpm_bridge.kext $ sudo kextload -v /tmp/tpm_bridge.kext kextload: extension /tmp/tpm_bridge.kext appears to be loadable kextload: loading extension /tmp/tpm_bridge.kext kextload: sending 1 personality to the kernel kextload: /tmp/tpm_bridge.kext loaded successfully kextload: extension /tmp/tpm_bridge.kext has no personalities $ ls -las /dev/tpm 0 crw-rw-rw- 1 root wheel 19, 0 Feb 23 02:06 /dev/tpm

Once the kernel extension is loaded, we see that a /dev/tpm node becomes available. By default, the kernel extension allows read/write access to everybody for experimental convenience—depending on your needs, you might want to change this in the source. At this point, the device will not behave like a "real" TPM device because we still need to run the TPM emulator daemon, which the device would communicate with.

The kernel extension uses a Unix domain socket to communicate with the emulator daemon. By default, the path to this socket is /tmp/tpm/tpmd_socket:0. Moreover, the daemon needs a location to store the TPM's persistent state. By default, the daemon would store it in the /tmp/tpm/ directory in a file whose name begins with tpm_emulator-1.2. Let us create a /tmp/tpm/ directory and start the daemon. Please refer to the TPM emulator documentation to understand which command-line arguments to use. Initially, we will run the daemon in its "clear" startup mode.

The /tmp location for both TPM persistent data and the Unix domain socket is makeshift. In particular, remember that /tmp will not be persistent across a reboot. In a production setup, you would use more appropriate locations. For example, you could use the per user Documents folder for storing TPM persistent data and the per user temporary folder (the DARWIN_USER_TEMP_DIR configuration parameter) for the socket.

The socket path must be changed both in the kernel extension source and in the emulator source.

$ mkdir /tmp/tpm/ $ cd /work/tpm/tpm-emulator/tpmd $ ./tpmd -d -f clear ... ../tpm/tpm_startup.c:44: Info: TPM_Startup(1) tpmd.c:376: Debug: waiting for connections... ...

At this point, TPM-based software should be able to talk to /dev/tpm just as if the machine had a physical TPM. Please refer to "Trusted Computing for Mac OS X" for more information on TPM-related software you can experiment with. The following is an example of what you should see if you run the tpm_demo program from the osxbook-libtpm package.

$ cd /path/to/osxbook-libtpm-2.0c $ ./tpm_demo TPM version 1.1.0.0 24 PCR registers are available PCR-00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... PCR-23: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 10 Key slots are available slots = 10, num = 0 No keys are loaded $

Note that this setup should also work on a PowerPC Macintosh.

Download