How to use a TPM with Linux
By webmaster – Security – Permalink
The goal of the article is to offer a simple tutorial to use your onboard TPM to secure your system. The TPM can offer security for a trusted boot and create a chain of trust for over applications.
The Hardware
There are already many versions of TPM standard. The first versions were not all compatible (from Atmel, STM, Infineon…), therefore since the 1.2 version of the standard it seems we have a consensus.
So, we will see the procedure to use a 1.2 TPM.
I have for example a DELL Optiplex 755 which provides a ST Microelectronics TPM conform with version 1.2. This conformance is important since the Linux kernel does not provide a specific implementation for all chips.
You can see what TPMs are supported with your kernel version with the following command :
$ ls -la /lib/modules/`uname -r`/kernel/drivers/char/tpm
drwxr-xr-x 2 root root 4096 2008-06-24 10:33 .
drwxr-xr-x 9 root root 4096 2008-06-24 10:33 ..
-rw-r
r1 root root 9012 2008-06-18 20:13 tpm_atmel.ko-rw-r
r1 root root 10960 2008-06-18 20:13 tpm_bios.ko-rw-r
r1 root root 13440 2008-06-18 20:13 tpm_infineon.ko-rw-r
r1 root root 20392 2008-06-18 20:13 tpm.ko-rw-r
r1 root root 10712 2008-06-18 20:13 tpm_nsc.ko-rw-r
r1 root root 17432 2008-06-18 20:13 tpm_tis.ko
The tpm_tis module is the generic one to use fully 1.2 compatible TPMs. We will use this one.
The BIOS
Before doing anything, you must enable the TPM in the BIOS of your motherboard. If you need to reset the TPM BIOS, this usually requires a full power off and back on of the computer.
Linux kernel
We use two generic modules tpm_bios and tpm and the specific one tpm_tis.
First load the generic modules :
$ sudo modprobe tpm_bios
$ sudo modprobe tpm
And then the tpm_tis module with specific parameters. In fact, we user the force option to probe rather than using the ACPI entry and the interrupts option to desactivate the IRQ.
$ sudo modprobe tpm_tis force=1 interrupts=0
$ dmesg
...
[xxx.yyy] tpm_tis tpm_tis: 1.2 TPM (device-id 0x4A10, rev-id 78)
If you have something like this, all works fine !
If your TPM does not seem to be detected go to the last section Kernel development corner
.
TPM management tools
There are many softwares to manage your TPM, the more efficients I think are TrouSerS andTrusted Computing for the Java(tm) Platform.
In this tutorial, we will use TrouSerS . It provides an open-source TCG Software Stack and many TPM tools.
So, we will no see how to take ownership and initialize your TPM. We will use the TPM tools provided with TrouSerS, you can refer to your local manpages of to this documentation.
Prepare the tools
Tools installation :
$ sudo aptitude install tpm-tools trousers
Trousers is daemon which centralize all the communication with the TPM. All communication are base on Local or Remote Procedure Call (RPC). You can restrict its usage to local programs. First of all, check if it is running :
$ sudo /etc/init.d/tcsd start
Check if the TPM is accessible :
$ sudo tpm_version
TPM Version: 01010000
Manufacturer Info: 53544d20
Initialize the TPM
So the first step is to take ownership. This operation will prompt for owner and SRK passwords which are very important and must not be lost.
$ sudo tpm_takeownership
Enter owner password: xxxxxx
Confirm password: xxxxxx
Enter SRK password: yyyyyyyy
Confirm password: yyyyyyyy
Ownership can only be realized once, any other attempt will fail.
The operation may take awhile, the TPM is generating an initializing some internal cryptographic values. The owner password is for adminstration and other sensitive tasks. TheSRK is the Storage Root Key which will be required whenever you load a key into the TPM.
If you have the following error :
Tspi_TPM_GetPubEndorsementKey failed: 0x00000023 - layer=tpm, code=0023 (35), No EK
This is because your TPM does not have an Endorsement Key. Then, launch the following command which will take awhile :
$ sudo tpm_createek
Now the TPM has an owner, we can get the Public Endorsement Key. The Endorsement Key is typically a 2,048-bit RSA public and private key pair, which is created randomly on the chip at manufacture time and cannot be changed. The private key never leaves the chip, while the public key is used for attestation and for encryption of sensitive data sent to the chip.
To get the public key, your owner password will be required :
$sudo tpm_getpubek
Tspi_TPM_GetPubEndorsementKey failed: 0x00000008 - layer=tpm, code=0008 (8),
The TPM target command has been disabled
Enter owner password:
Public Endorsement Key:
Version: 01010000
Usage: 0x0002 (Unknown)
Flags: 0x00000000 (!VOLATILE, !MIGRATABLE, !REDIRECTION)
AuthUsage: 0x00 (Never)
Algorithm: 0x00000020 (Unknown)
Encryption Scheme: 0x00000012 (Unknown)
Signature Scheme: 0x00000010 (Unknown)
Public Key:
a71def6a f09b39cb e0e55779 b1e6dfe5 26ca2278 b6fce7cf f1c242c5 545694d8
1a5804ad 5a3b1d5c c18c3d93 fda2e201 78a86e4e c93e4bb7 e1851eab ca98cbe5
81c06522 1357777c e0e55779 1bac9e9c 8208f203 f1477705 0317fe2b db233d4d
a71def6a f09b39cb e0e55779 b1e6dfe5 26ca2278 b6fce7cf f1c242c5 545694d8
[...]
TrustedGrub
Introduction
TrustedGRUB is an extension of the standard GRUB bootloader. It has been modified to detect and support the TPM functionalities. The main feature of TrustedGRUB is to measure arbitrary files during the boot process and extend the Platform Configuration Registers (PCR).
PCR are registers inside the TPM memory which are updated at each boot.
The PCR are used as follow :
- PCR 0 to 3 for the BIOS, ROMS…
- PCR 4 contains MBR information and stage1
- PCR 8 contains bootloader information stage2 part1
- PCR 9 contains bootloader information stage2 part2
- PCR 12 contains all commandline arguments from menu.lst and those entered in the shell
- PCR 13 contains all files checked via the checkfile-routine
- PCR 14 contains all files which are actually loaded (e.g., Linux kernel, initrd, modules…)
- PCR 15 to 23 are not used
You can see your currents PCR values with the following command :
$ sudo cat /sys/class/misc/tpm0/device/pcrs
PCR-00: 9C 22 FD 7F A5 88 83 75 13 74 CD DD 12 EA 7B 40 F6 AD F5 F7
PCR-01: A8 9F B8 F8 8C AA 95 90 E6 12 9B 63 3B 14 4A 68 51 44 90 D5
PCR-02: A8 9F B8 F8 8C AA 95 90 E6 12 9B 63 3B 14 4A 68 51 44 90 D5
PCR-03: A8 9F B8 F8 8C AA 95 90 E6 12 9B 63 3B 14 4A 68 51 44 90 D5
PCR-04: 44 85 2F BD 5D 44 F9 5B 5E D3 97 16 DF 8E 3C 6E BE 63 A1 20
PCR-05: 19 0A 15 23 AF AC 1D C2 6D 48 AA 3D AE 50 FF 89 AE 79 F2 98
PCR-06: A8 9F B8 F8 8C AA 95 90 E6 12 9B 63 3B 14 4A 68 51 44 90 D5
PCR-07: A8 9F B8 F8 8C AA 95 90 E6 12 9B 63 3B 14 4A 68 51 44 90 D5
PCR-08: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
PCR-09: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
PCR-10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
PCR-11: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
PCR-12: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
PCR-13: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
PCR-14: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
PCR-15: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...
PCR up to 8 are not extended without any compliant boot loader.
Installation
So, you can download the latest version of TrustedGrub at the following address.
The procedure is the following :
$ tar -xzvf TrustedGRUB-1.1.3.tgz
$ cd TrustedGRUB-1.1.3/
Read the file README.tGRUB, you need some specific tools to compile it :
$ sudo aptitude install aclocale automake autoconf gcc
Then start compiling :
$ ./build_tgruib.sh
- Deflating TrustedGRUB
- Configuring TrustedGRUB
- Compiling TrustedGRUB
Then, before installing anything copy your actual configuration and prepare a liveCD 😉
$ sudo mv /boot/grub /boot/grub_old
Remove you actual Grub version :
$ sudo dpkg -r grub
And then install the new one :
$ cd TrustedGRUB-1.1.3/
$ sudo make install
And copy the files for the boot process :
$ sudo mkdir /boot/grub
$ sudo cp ../default /boot/grub/
$ sudo cp stage1/stage1 /boot/grub
$ sudo cp stage2/stage2 /boot/grub
Copy your old menu list :
$ sudo cp /boot/grub_old/menu.lst /boot/grub
And finally install Grub :
$ sudo grub
root (hdX,Y)
setup (hdX)
Where X is the disk number and Y the partition number (generally X=0 and Y=0).
You can now restart with a new TrustedGRUB !!
Chain of trust and integrity checking
After restarting the system we can list the PCR and see how they are updated. But the TPM is only a passive component, the security must be ensured by the software at each step. For this reason, new versions of TrustedGRUB come with to additional functionalities :
- the checkfile option
- the pcr_verify utility.
The checkfile allows to specify in the /boot/grub/menu.lst file, additional files or programs to check at startup. Grub will extend the PCR-13 with a SHA1 of these files.
The first thing to do is to indicate to grub to verify additional files, and where found them (disk and path) :
title TrustedGRUB Test
root (hd0,0)
kernel /boot/vmlinuz-2.6.xx ro quiet splash
initrd /boot/initrd.img-2.6.xx
checkfile (hd?,?)/somewhere/check.file
quiet
Then, create the file /somewhere/check.file, with the following content :
fedb1cff009e115f7f5f7b4533667a787798832d (hd0,1)/test1.file
485214eab2de87284de9d4e323e428bf60e0aa77 (hd0,1)/grub-0.92.tar.bz2
a6e171e989849dd44735a513c4270a0837c09174 (hd0,1)/test2.file
You must respect the following constraints :
- The check file MUST NOT be larger than 8096 Bytes.
- The first component is a 40 byte alphanumeric value, created with sha1sum.
- The second component has to be the driver followed by the absolute path of the file.
- Each line must end with an end-line character.
If you use a wrong syntax your system will not boot !!
TSS Stack
The TrouSerS software suite provides an open-source TCG Software Stack. It is licensed under the Common Public License (CPL).
TrouSers provides the following services :
- RSA key pair generation
- RSA encryption and decryption using PKCS v1.5 and OAEP padding
- RSA sign/verify
- Extend data into the TPM's PCRs and log these events
- Seal data to arbitrary PCRs
- Random Number Generation
- RSA key storage
To install it, proceed as the following :
$ sudo aptitude install trousers
The TSS stack is designed to be used locally or remotely. If you want to allow remote commands you must update the configuration file located in /etc/tcsd.conf :
$ sudo more /etc/tcsd.conf
...
# Option: remote_ops
# Values: TCS operation names, separated by commas (no whitespace)
# Description: A list of TCS commands which will be allowed to be executed
# on this machine's TCSD by TSP's on non-local hosts (over the internet).
# By default, access to all operations is denied.
#
# possible values: seal - encrypt data bound to PCR values
# unseal - decrypt data bound to PCR values
# registerkey - store keys in system persistent storage Disk write access!
# unregisterkey - remove keys from system persistent storage Disk write access!
# loadkey - load a key into the TPM
# createkey - create a key using the TPM
# sign - encrypt data using a private key
# random - generate random numbers
# getcapability - query the TCS/TPM for its capabilities
# unbind - decrypt data
# quote - request a signed blob containing all PCR values
# readpubek - access the TPM's Public EndorsementKey
# getregisteredkeybypublicinfo - Search system persistent storage for a public key
# getpubkey - Retrieve a loaded key's public data from inside the TPM
# selftest - execute selftest and test results ordinals
#
remote_ops = <UPDATE HERE>
All these functionalities can be accessed locally with the tpm_tools but for a more convenient usage, it exists a graphical user interface : ''TPM Keyring''.
To compile this software will be need additional packages :
autotools-dev
libltdl3-dev
libtool
automake
autoconf
swig
qt3-devel
openssl-devel
gtk2-dev
python-dev
python-gtk2-dev
python-all-dev
Then run :
$ cvs -d:pserver:anonymous@trousers.cvs.sourceforge.net:/cvsroot/trousers co applications/tpm_keyring2
$ cd applications/tpm_keyring2/
To compile tpm_keyring on Ubuntu you must edit the ''Makefile' file and replace :
PYTHON_INCLUDES=-I/usr/include/python
with
PYTHON_INCLUDES=-I/usr/include/python2.5
or
PYTHON_INCLUDES=-I/usr/include/python2.4
depending on the version you use.
Then :
$ make
You can now run tpm_keyring :
$ ./tpm_keyring
For more information please refer to the following tutorial.
Kernel development corner
Will be updated soon.
By default, the Linux kernel gets in the ACPI tables the information about the supported TPMavailable on a platform. Even if the TPM device can be found in the ACPI tables, the driver will not find the device if its identifier is not referenced. Most of the TPMs are compatible with the standard tpm_tis module driver but the kernel does not reference all new hardware components. For many of them, the support concists in adding the device HID in the module source.
For example, the Linux kernel version 2.6.25.9 has the following HID :
in file drivers/char/tpm/tpm_tis.c
[...]
static struct pnp_device_id tpm_pnp_tbl __devinitdata = {
{"PNP0C31", 0}, /* TPM */
{"ATM1200", 0}, /* Atmel */
{"IFX0102", 0}, /* Infineon */
{"BCM0101", 0}, /* Broadcom */
{"NSC1200", 0}, /* National */
/* Add new here */
{"", 0}, /* User Specified */
{"", 0} /* Terminator */
};
[...]
To get all information about your TPM device, you can use a tool iasl, provided by The ACPI Component Architecture Project. This tool is a compiler which allows you yo disassemble the binary ACPI table and dump them in a readable text format.
You can download it here : UNIX Format Source Code and Build Environment.
To compile iasl :
$ tar -xzvf acpica-unix-20080609.tar.gz
$ cd acpica-unix-20080609/compiler
$ make
First get a local copy of your ACPI tables :
$ sudo cp /proc/acpi/dsdt .
$ sudo chmod a+r dsdt
To get all informations from the ACPI tables run the following command to disassemble :
acpica-unix-20080609/compiler/iasl -d dsdt
Intel ACPI Component Architecture
AML Disassembler version 20080609 Jun 13 2008
Copyright (C) 2000 - 2008 Intel Corporation
Supports ACPI Specification Revision 3.0a
Loading Acpi table from file dsdt
Acpi table DSDT successfully installed and loaded
Pass 1 parse of DSDT
Pass 2 parse of DSDT
Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)
....................................................................................
Parsing completed
Disassembly completed, written to "dsdt.dsl"
You now have a text readable version of your ACPI tables in the file dsdt.dsl.
Search the word TPM in the file, you will have a section starting with something like :
Device (TPM)
{
Name (_HID, EisaId ("BCM0102"))
Name (_CID, EisaId ("PNP0C31"))
Method (_STA, 0, NotSerialized)
{
SX10 ()
SX30 (0x0E)
SX11 ()
Store (SX42 (), Local0)
SX12 ()
Return (Local0)
}
[...]
The line containing your device HID is the following :
Name (_HID, EisaId ("BCM0102"))
Add the value BCM0102 in the pnp_device_id structure of the tpm_tis module to support yourTPM device. (See this post for an example Broadcom TPM with DELL Latitude D630).
And recompile the module to test !!