The following picture is taken from Wikipedia [1]:
We can read more about the picture in [1]. We should just say that TPM is a hardware chip on the computer’s motherboard and is capable of communicating with the software tools installed on the system. The TPM has the following features:
a. Binding a Key: The TPM can create cryptographic keys and encrypt/decrypt them. This protects the keys from being disclosed, since the TPM is the only one who can also decrypt the keys. The TPM has a Storage Root Key (SRK) that is embedded within the TPM hardware and only the TPM knows about it. This effectively enables only the TPM to be able to encrypt/decrypt the keys, since it’s only the TPM that knows the key, which is never disclosed to any other component.
b. Sealing a Key: The TPM can also seal a key, which means that the key can only be decrypted under the same conditions as it was encrypted.
Enabling TPM in the BIOS#
Before doing anything, we should first enable the TPM in BIOS.
Enabling TPM in the Kernel#
First thing to do when trying to configure TPM is to configure a kernel. On Gentoo Linux we need to configure our existing kernel to support the TPM. In order to check whether the kernel supports TPM by default, we can execute the command below:
[plain] # cat /usr/src/linux/.config | grep TPM # CONFIG_TCG_TPM is not set [/plain]
From the output we can see that the TPM is disabled and the current kernel doesn’t support it. Let’s enable the TPM in the kernel now. To do that, we can first cd into the /usr/src/linux/ directory, then execute the make menuconfig to enter the interactive kernel configuration menu. Afterwards we need to select Device Drivers – Character devices – TPM Hardware Support and select all of the options listed below:
[plain] * TPM Interface Specification 1.2 Interface <M> National Semiconductor TPM Interface <M> Atmel TPM Interface * Infineon Technologies TPM Interface [/plain]
All the commands we need to run are listed below:
[bash] # cd /usr/src/linux # make menuconfig ; configure to use the TPM as module and exit the make menuconfig configuration menu # make && make modules && make modules_install [/bash]
The last command in the above output will actually compile and install the new kernel. If we changed some of the option as built-in, we need to copy the new kernel into the /boot partition like command below:
[bash] # cp arch/x86_64/boot/bzImage /boot/kernel [/bash]
But if we installed the TPM as modules only, those are automatically loaded into the current kernel. To check whether the module is enabled, we can execute the command as we did before. The command is listed below:
[plain] # cat /usr/src/linux/.config | grep TPM CONFIG_TCG_TPM=m [/plain]
We can see that the TPM is compiled into the kernel as a module, which is very good. In order to check which modules were enabled we can also execute the command below:
[bash] # modprobe -l | grep tpm kernel/drivers/char/tpm/tpm.ko kernel/drivers/char/tpm/tpm_bios.ko kernel/drivers/char/tpm/tpm_tis.ko kernel/drivers/char/tpm/tpm_nsc.ko kernel/drivers/char/tpm/tpm_atmel.ko kernel/drivers/char/tpm/tpm_infineon.ko [/bash]
There are the following modules enabled: tpm, tpm_bios, tpm_tis, tpm_nsc, tpm_atmel and tpm_infineon. We don’t need all of the modules, but just specific ones based on our hardware. We’ve enabled all the modules, because they don’t actually get loaded when the Linux is booting, so they don’t slow down the booting process. The modules are just there in case we need them.
In our case we’ll use the generic module tpm_tis and we don’t need the other ones. To load the selected module we can execute the command below:
[bash] # modprobe tpm_tis [/bash]
When loading the tpm_tis module we can receive an error saying something like:
[plain] # modprobe tpm_tis WARNING: Error inserting tpm (/lib/modules/3.2.12-gentoo/kernel/drivers/char/tpm/tpm.ko): Unknown symbol in module, or unknown parameter (see dmesg) FATAL: Error inserting tpm_tis (/lib/modules/3.2.12-gentoo/kernel/drivers/char/tpm/tpm_tis.ko): Unknown symbol in module, or unknown parameter (see dmesg) [/plain]
Upon viewing the dmesg the detailed error will reveal the information below:
[plain] [92605.067263] tpm_bios: Unknown symbol securityfs_create_dir (err 0) [92605.067277] tpm_bios: Unknown symbol securityfs_remove (err 0) [92605.067288] tpm_bios: Unknown symbol securityfs_create_file (err 0) [/plain]
This can happen if we’ve enabled the TPM in the kernel as modules, but then didn’t actually copy the new kernel over the /boot partition and restarted the system. This happens because the CONFIG_SECURITYFS=y option was set to true, but it was set to false when we last booted our system. To check whether this option is set to true (as it should be), issue the below command:
[bash] # cat /usr/src/linux/.config | grep CONFIG_SECURITY CONFIG_SECURITY=y [/bash]
Various options are listed when executing the above command, but we’re only presenting the option that interests us, the CONFIG_SECURITY option. We can see that the option is set to true. If the error is still appearing when trying to load the module (with modprobe), then we should copy the newly built kernel over to the /boot partition and restart the system. Afterwards we should load the modules without any errors. This can be seen below:
[bash] # modprobe tpm # modprobe tpm_bios # modprobe tpm_tis force=1 interrupts=0 [/bash]
We’ve loaded the tpm and tpm_bios module with the default parameters, but we’ve changed the parameters when loading the tpm_tis module. The whole information about a module can be seen if we execute the modinfo command with the appropriate module name. An example of printing the details about the tpm_tis module can be seen below:
[bash] # modinfo tpm_tis filename: /lib/modules/3.2.12-gentoo/kernel/drivers/char/tpm/tpm_tis.ko license: GPL version: 2.0 description: TPM Driver author: Leendert van Doorn (leendert@watson.ibm.com) srcversion: 8E086F255337EF6F307939E alias: acpi*::* alias: pnp:d* alias: acpi*:ICO0102:* alias: pnp:dICO0102* alias: acpi*:NSC1200:* alias: pnp:dNSC1200* alias: acpi*:BCM0102:* alias: pnp:dBCM0102* alias: acpi*:BCM0101:* alias: pnp:dBCM0101* alias: acpi*:IFX0102:* alias: pnp:dIFX0102* alias: acpi*:ATM1200:* alias: pnp:dATM1200* alias: acpi*:PNP0C31:* alias: pnp:dPNP0C31* depends: tpm intree: Y vermagic: 3.2.12-gentoo SMP mod_unload parm: itpm:Force iTPM workarounds (found on some Lenovo laptops) (bool) parm: interrupts:Enable interrupts (bool) parm: hid:Set additional specific HID for this driver to probe (string) parm: force:Force device probe rather than using ACPI entry (bool) [/bash]
We can see various information that is available about that specific module, from filename (which is very useful when looking for the exact path of the module on disk), author, license, and version, to all the parameters the module can accept as input when loading the module with modprobe. The optional parameters are: itpm, interrupts, hid and force. We’ve used the interrupts parameter that enables the interrupts and force that forces the device to probe rather than use ACPI.
After the module is loaded we can check the dmesg output, where we can check that the TPM was successfully enabled. If the output looks like the following then everything works as expected and the TPM was successfully loaded.
[plain] # dmesg | tail [ 682.144337] tpm_tis tpm_tis: 1.2 TPM (device-id 0xB, rev-id 16) [ 684.229180] tpm_tis tpm_tis: Adjusting TPM timeout parameters [/plain]
There should also be the appropriate /dev/ entries, which indicate that the TPM is enabled in BIOS:
[bash] # ls -l /dev/tpm* lrwxrwxrwx 1 root root 4 Sep 13 18:42 /dev/tpm -> tpm0 crw-rw—- 1 tss tss 10, 224 Sep 13 18:42 /dev/tpm0 [/bash]
All the tools we’re ever gonna need when working with TPM are the trousers package that provides an open-source TCG software stack (TSS) v1.1 implementation and tpm-tools package that provides the trousers support tools for the Trusted Platform Modules (TPM). To install both of the packages we can issue the following command on the Gentoo Linux distribution:
[bash] # emerge app-crypt/trousers app-crypt/tpm-tools [/bash]
When installed, the trousers package provides a daemon that is used for TPM communication. First we need to check whether the daemon is running with the command:
[bash] # /etc/init.d/tcsd status * status: stopped [/bash]
We can see that the tcsd daemon is stopped, which is why we need to start it. We can start the tcsd daemon with the start argument passed to the appropriate script in the /etc/init.d/ directory:
[bash] # /etc/init.d/tcsd start * Starting TrouSerS’ TCS daemon (tcsd) … [ ok ] [/bash]
The trousers daemon (tcsd) was successfully started. To check on which port the daemon is listening we can use the netstat command as below:
[bash] # netstat -landtp | grep tcsd tcp 0 0 127.0.0.1:30003 0.0.0.0:* LISTEN 4040/tcsd [/bash]
The daemon is listening on port 4040. Since the tcsd is up and running, the check whether TPM is accessible should also succeed, but let’s try to access TPM anyway. To check whether TPM is accessible we can run the tpm_version command:
[bash] # tpm_version TPM 1.2 Version Info: Chip Version: 1.2.1.2 Spec Level: 2 Errata Revision: 0 TPM Vendor ID: IFX TPM Version: 01010000 Manufacturer Info: 49465800 [/bash]
Conclusion#
We’ve seen what TPM is and how to enable it in BIOS and kernel. We need to remember that TPM is an actual chip on the motherboard that we can directly access. It also holds a private cryptographic key that is used to encrypt/decrypt the data, and since that key is never disclosed the data encryption/decryption is not vulnerable to any kind of attack.
In the next tutorial we’ll take a look at how to initialize and use the TPM hardware chip.
Sources#
[1] Trusted Platform Module