How to mitigate ROCA TPM vulnerability?

ROCA vulnerability was discovered (October 2017) in a software library, RSALib, provided by Infineon Technologies. That library is also used in TPM modules. When this vulnerability is present, a pair of prime numbers used for generating RSA keys is chosen from a small subset of all available prime numbers. This results in a great loss of entropy. Details and exact numbers can be found here.

UPDATE 2021-10-20: provided new link for TPM firmware updates (old one was no longer working), added info about patch for openssl-1.1.0 being applied upstream.

UPDATE 2021-11-18: updated second link referring to the TPM firmware updates (it was not fixed in the UPDATE 2021-10-20).

Discovering whether TPM is vulnerable

All vulnerable keys have the same structure. This structure is visible in the public part of the key, so only the public key is required to check for ROCA. Note that when prime numbers are generated randomly there is still a chance that non-vulnerable generator will produce a key with the same structure. This chance is marginally small, compared to the whole space of available numbers, but there is a possibility of a false positive result. For the version of detection tool we will use it is 2^-154 - consider yourself very lucky if you manage to get a false positive.

Generating RSA key pairs with TPM

TPM2

RSA keys can be generated with tpm2-tools. SLB 9665 used in TPM module doesn’t support 512-bit RSA, so either 1024 or 2048-bit keys must be used. Because of that, it is impossible to factorize the private part in reasonable time for testing purposes, but that time (around 3 months of CPU time according to the paper mentioned earlier) is very low when it comes to the security of keys and, moreover, data and identities protected by them. Even worse, this time scales linearly with the number of cores.

Context is used for key generation, so it must be generated first:

1
2
tpm2_createprimary -g 'sha1' -G 'rsa1024:null:aes128cfb' -o tpm.ctx
tpm2_create -C tpm.ctx -Grsa1024 -u key.pub -r key.priv

Only the public key is actually required by vulnerability check. It is a good idea to generate more than one pair, probably using different key sizes - chances for false positives are extremely low, but not zero.

TPM has a limited amount of the internal RAM and runs out of memory after 3 operations with error:

1
ERROR: Tss2_Sys_CreatePrimary(0x902) - tpm:warn(2.0): out of memory for object contexts

In this case either rebooting or flushing open handles manually helps. Only handles-transient need to be flushed:

1
2
3
4
5
6
7
$ tpm2_getcap -c handles-transient
- 0x80000000
- 0x80000001
- 0x80000002
$ tpm2_flushcontext -c 0x80000000
$ tpm2_flushcontext -c 0x80000001
$ tpm2_flushcontext -c 0x80000002

Extracting keys hashes

File key.pub is a binary file with a TPM-specific header. It is not supported by the tool for checking for ROCA vulnerability, so the key needs to be extracted and saved in one of the supported formats, e.g. hex coded number. This can be done with the following script:

1
2
3
4
5
6
7
8
9
#!/bin/bash

rm -f keys.txt

for file in *.pub
do
    dd if=${file} bs=1 skip=24 | hexdump -v -e '/1 "%02x"' >> keys.txt
    echo "" >> keys.txt
done

The header is 22 bytes long, followed by the size of the key (2 bytes) and the key itself. The key is the last field in the file, so it isn’t necessary to know its size - it is needed only for keys in memory.

Testing for ROCA vulnerability

A tool for checking for ROCA TPM vulnerability can be found here. The easiest way is to install it with pip:

1
pip install roca-detect

All parsed keys can be checked using just one command:

1
roca-detect keys.txt

More use cases can be found on the main page of this tool, including tests for saved SSH hosts keys.

This operation should take no more than a couple of seconds, as it only checks if the key was generated from insecure prime numbers, without finding the exact numbers used. It does not generate private keys.

Results

This is output from test run on 2 different modules, with both 1024 and 2048-bit keys generated on each of them:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
2019-03-25 18:31:17 [11915] WARNING Fingerprint found in modulus keys.txt idx 0
{"type": "mod-hex", "fname": "keys.txt", "idx": 0, "aux": null,
  "n": "0x94b79a35a5d47040df1503670080a7714ae1ee751aeb32071b3db388b3bf80b11f661c4b8819ebd1c716239c9ec5a202b08a2aa3c17ad6cd17075ba49fcd005d8b8fa50c29433db35c1421727472deddd77bced7e6438db4d447008b11cdb018139bfef2e06c4b4a3e672543a7e9333040fd881815e14b1f1338e90180fd0865",
  "marked": true, "time_years": 0.16104529886799998, "price_aws_c4": 70.5861544938444}
(...)
2019-03-25 18:31:17 [11915] INFO ### SUMMARY ####################
2019-03-25 18:31:17 [11915] INFO Records tested: 8
2019-03-25 18:31:17 [11915] INFO .. PEM certs: . . . 0
2019-03-25 18:31:17 [11915] INFO .. DER certs: . . . 0
2019-03-25 18:31:17 [11915] INFO .. RSA key files: . 0
2019-03-25 18:31:17 [11915] INFO .. PGP master keys: 0
2019-03-25 18:31:17 [11915] INFO .. PGP total keys:  0
2019-03-25 18:31:17 [11915] INFO .. SSH keys:  . . . 0
2019-03-25 18:31:17 [11915] INFO .. APK keys:  . . . 0
2019-03-25 18:31:17 [11915] INFO .. JSON keys: . . . 0
2019-03-25 18:31:17 [11915] INFO .. LDIFF certs: . . 0
2019-03-25 18:31:17 [11915] INFO .. JKS certs: . . . 0
2019-03-25 18:31:17 [11915] INFO .. PKCS7: . . . . . 0
2019-03-25 18:31:17 [11915] INFO Fingerprinted keys found: 4
2019-03-25 18:31:17 [11915] INFO WARNING: Potential vulnerability
2019-03-25 18:31:17 [11915] INFO ################################

It shows that ROCA vulnerability is present on this TPM module model. TPM firmware update will be required.

Note that ROCA is connected only with RSA, it doesn’t affect any other security functions, as long as they don’t use RSALib.

Updating TPM firmware

Tools for updating Infineon TPM firmware can be easily found, unfortunately, most of them are either UEFI or Windows applications. A Linux port of them can be found here. It requires openssl-1.0 (both developer files and runtime library), but it can be updated to 1.1.0 version using this patch. EDIT: Patch has already been committed to main branch.

First, check if TPMFactoryUpd was built successfully and TPM is detected properly:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ ./TPMFactoryUpd -info
  **********************************************************************
  *    Infineon Technologies AG   TPMFactoryUpd   Ver 01.01.2459.00    *
  **********************************************************************

       TPM information:
       ----------------
       Firmware valid                    :    Yes
       TPM family                        :    2.0
       TPM firmware version              :    5.61.2785.0
       TPM platformAuth                  :    Empty Buffer
       Remaining updates                 :    64

Remember the current firmware version number, it will be needed later. Also, note what is the value of TPM platformAuth - it must be Empty Buffer in order to perform an update. To do this, build and flash coreboot with TPM disabled in the config menu, or use an older version of BIOS - none of the v4.8.0.* versions have TPM support enabled. SeaBIOS doesn’t need any modifications, it will not initialize TPM unless coreboot does. BIOS from other vendors might include an option to turn TPM off - keep in mind that doing so will probably mess up things like a Secure Boot or HDD encryption.

TPM firmwares are available with some of the UEFI and Windows images, like these. Only 9665FW update package_1.5/Firmware/TPM20_<old_version>_to_TPM20_5.63.3144.0.BIN file is required. Extract this file to the same directory as the TPMFactoryUpd and run:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ ./TPMFactoryUpd -update tpm20-emptyplatformauth -firmware TPM20_<old_version>_to_TPM20_5.63.3144.0.BIN
  **********************************************************************
  *    Infineon Technologies AG   TPMFactoryUpd   Ver 01.01.2459.00    *
  **********************************************************************

       TPM update information:
       -----------------------
       Firmware valid                    :    Yes
       TPM family                        :    2.0
       TPM firmware version              :    5.61.2785.0
       TPM platformAuth                  :    Empty Buffer
       Remaining updates                 :    64
       New firmware valid for TPM        :    Yes
       TPM family after update           :    2.0
       TPM firmware version after update :    5.63.3144.0

       Preparation steps:
       TPM2.0 policy session created to authorize the update.

    DO NOT TURN OFF OR SHUT DOWN THE SYSTEM DURING THE UPDATE PROCESS!

       Updating the TPM firmware ...
       Completion: 100 %
       TPM Firmware Update completed successfully.

This can take 3-5 minutes, depending on the firmware update size. After it completes, TPM is not useful until the next reboot:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ ./TPMFactoryUpd -info
  **********************************************************************
  *    Infineon Technologies AG   TPMFactoryUpd   Ver 01.01.2459.00    *
  **********************************************************************

       TPM information:
       ----------------
       Firmware valid                    :    Yes
       TPM family                        :    2.0
       TPM firmware version              :    5.63.3144.0
       TPM platformAuth                  :    N/A - System restart required
       Remaining updates                 :    N/A - System restart required

Reboot platform immediately. Using TPM functions in this state isn’t safe. After successful reboot and flashing original coreboot firmware the result should be:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ ./TPMFactoryUpd -info
  **********************************************************************
  *    Infineon Technologies AG   TPMFactoryUpd   Ver 01.01.2459.00    *
  **********************************************************************

       TPM information:
       ----------------
       Firmware valid                    :    Yes
       TPM family                        :    2.0
       TPM firmware version              :    5.63.3144.0
       TPM platformAuth                  :    Not Empty Buffer
       Remaining updates                 :    63

Updating TPM firmware - automatic version detection

Assuming that a whole Firmware directory was extracted to the directory containing TPMFactoryUpd from the update package, one can use a single command to do the update. Appropriate file is chosen automatically, depending on the old version. The command is:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ ./TPMFactoryUpd -update config-file -config Firmware/TPM20_latest.cfg
  **********************************************************************
  *    Infineon Technologies AG   TPMFactoryUpd   Ver 01.01.2459.00    *
  **********************************************************************

       TPM update information:
       -----------------------
       Firmware valid                    :    Yes
       TPM family                        :    2.0
       TPM firmware version              :    5.51.2098.0
       TPM platformAuth                  :    Empty Buffer
       Remaining updates                 :    64
       New firmware valid for TPM        :    Yes
       TPM family after update           :    2.0
       TPM firmware version after update :    5.63.3144.0

       Selected firmware image:
       TPM20_5.51.2098.0_to_TPM20_5.63.3144.0.BIN

       Preparation steps:
       TPM2.0 policy session created to authorize the update.

    DO NOT TURN OFF OR SHUT DOWN THE SYSTEM DURING THE UPDATE PROCESS!

       Updating the TPM firmware ...
       Completion: 100 %
       TPM Firmware Update completed successfully.

Remember to use BIOS with TPM disabled, and re-flash newer BIOS firmware afterwards.

Summary

Repeating all steps from generating TPM context to using roca-detect shows that the vulnerability is no longer present:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
2019-03-26 18:40:42 [4325] INFO ### SUMMARY ####################
2019-03-26 18:40:42 [4325] INFO Records tested: 8
2019-03-26 18:40:42 [4325] INFO .. PEM certs: . . . 0
2019-03-26 18:40:42 [4325] INFO .. DER certs: . . . 0
2019-03-26 18:40:42 [4325] INFO .. RSA key files: . 0
2019-03-26 18:40:42 [4325] INFO .. PGP master keys: 0
2019-03-26 18:40:42 [4325] INFO .. PGP total keys:  0
2019-03-26 18:40:42 [4325] INFO .. SSH keys:  . . . 0
2019-03-26 18:40:42 [4325] INFO .. APK keys:  . . . 0
2019-03-26 18:40:42 [4325] INFO .. JSON keys: . . . 0
2019-03-26 18:40:42 [4325] INFO .. LDIFF certs: . . 0
2019-03-26 18:40:42 [4325] INFO .. JKS certs: . . . 0
2019-03-26 18:40:42 [4325] INFO .. PKCS7: . . . . . 0
2019-03-26 18:40:42 [4325] INFO No fingerprinted keys found (OK)
2019-03-26 18:40:42 [4325] INFO ################################

We will check every TPM module we sell and, if necessary, update the firmware before sending them to the customers. If you ordered such module earlier or you are not sure if it is vulnerable, feel free to test them for yourself.

If you think we can help in improving the security of your firmware or you are looking for someone who can boot your product by leveraging advanced features of used hardware platform, feel free to book a call with us or drop us email to contact<at>3mdeb<dot>com. If you are interested in similar content feel free to sign up for our newsletter


Krystian Hebel
Firmware Engineer interested mostly in things deliberately omitted from documentation. Thinks C is high-level language, can write something in Verilog but doesn't know how to read it yet.