IBM TPM 2.0 TSS API

Ken Goldman

IBM Research

kgoldman@us.ibm.com


June 29, 2017




1. Introduction 4

2. Features 5

3. API 6

3.1. TSS_Execute() 6

3.2. TSS_Create() 6

3.3. TSS_Delete() 7

3.4. Optional Customization 8

3.4.1. Property Example 8

3.4.2. Properties 8

3.4.3. TSS_SetProperty() 11

3.5. Extra Parameter 12

3.6. Other APIs and Headers 12

4. Application Notes 14

4.1. TPM Simulator 14

4.2. Parameter Encryption 14

4.3. Session Salt 14

4.4. Session Bind 14

4.5. NV 15

4.5.1. Rationale 15

4.5.2. NV Preprovisioning 16

4.6. TPM2_LoadExternal 16

4.7. Connecting to Resource Managers 16

4.8. Endorsement Key (EK Certificates) 17

4.8.1. Nuvoton 17

4.8.2. St Micro 17

4.8.3. Infineon 18

4.8.4. NationZ 19

4.8.5. Intel 19

4.8.5.1. Intel EK Certificate Download 19

4.9. Command Line Utilities 20

5. Example 21

6. Build 22

6.1. Directories 22

6.2. Linux 22

6.3. Windows 23

6.3.1. Windows Tbsi 24

6.3.2. Windows Visual Studio 25

6.3.3. Windows gcc 25

6.4. AIX 25

6.5. Minimal TSS Library Builds 26

6.5.1. TPM_TSS_NOFILE 26

6.5.2. TPM_TSS_NOCRYPTO 26

7. Fedora 27

7.1. Local Install 27

7.2. Alternative Local Install 27

7.3. Repository Install 28

7.4. Install Test 28

7.5. Source rpms 28

8. Status 30

8.1. Utilities 30

8.2. Bugs 30

8.3. Untested 30

9. Theading 31



  1. Introduction


The IBM TSS is designed for:



  1. Features



The TSS handles the following, completely hidden from the caller:



and almost hidden from the caller:





  1. API


The API consists of the following calls:

    1. TSS_Execute()


#include <tss2/tss.h>


TPM_RC TSS_Execute(TSS_CONTEXT *tssContext,

RESPONSE_PARAMETERS *out,

COMMAND_PARAMETERS *in,

EXTRA_PARAMETERS *extra,

TPM_CC commandCode,

...);


This is the primary TSS function.


tssContext: Opaque object

out: The standard TPM2 Part 3 response parameter

in: The standard TPM2 Part 3 command parameter

extra: Some commands (only two so far) require extra parameter s.

commandCode: The standard TPM2 Part 2 command code.


. . . : A list of session 3-tuples , of the form

TPMI_SH_AUTH_SESSION sessionHandle,

const char *password,

unsigned int sessionAttributes

The list is terminated with (TPM_RH_NULL, NULL, 0)


    1. TSS_Create()


#include <tss2/tss.h>


TPM_RC TSS_Create(TSS_CONTEXT **tssContext);


This creates the TSS_CONTEXT used in the TSS_Execute() function. It is initialized with the default configuration, which can be then changed using 3.4.3 TSS_SetProperty().


Returns an error if the context cannot be allocated, or if the properties cannot be initialized, typically due to an invalid environment variable.


See 3.3 TSS_Delete().


It does not immediately open a connection, so that the connection properties can be changed from the default first.


    1. TSS_Delete()


#include <tss2/tss.h>


TPM_RC TSS_Delete(TSS_CONTEXT *tssContext);


The deletes the opaque context created using 3.2 TSS_Create().


It closes an open connection.


Returns an error if the connection close fails.


    1. Optional Customization


The TSS is designed to work by default with no configuration.


The current default connects to the Microsoft format socket simulation. This will eventually change to connect to the resource manager.


There are three ways to customize the configuration:


  1. At compile time, with a compiler flag

  2. At program start, using an environment variable

  3. During run time, using the 3.4.3 TSS_SetProperty() function.


The environment variables and TSS_SetProperty property use the same names. The makefile flag uses the name with _DEFAULT appended.


The environment variable overrides the compiler flag, and the TSS_SetProperty() function overrides both the compiler flag and the environment variable.


      1. Property Example


To change the default TPM interface to the TPM device driver:



-DTPM_INTERFACE_TYPE_DEFAULT="\"dev\""



> setenv TPM_INTERFACE_TYPE dev



rc = TSS_SetProperty(tssContext, TPM_INTERFACE_TYPE, "dev");


      1. Properties


(Remember that the makefile compiler flag requires _DEFAULT to be added, and that the quotes must be escaped.).


The property and legal values are:


TPM_TRACE_LEVEL

default - 0

0 - no tracing

1 - trace errors

2 - trace errors and execution flow


TPM_DATA_DIR

default - current directory

set the directory where the TSS can store persistent data


TPM_INTERFACE_TYPE

default - socsim

socsim - the socket simulator

see

TPM_SERVER_NAME

TPM_SERVER_TYPE

TPM_COMMAND_PORT

TPM_PLATFORM_PORT

dev - TPM device driver

see

TPM_DEVICE

TPM_SERVER_NAME

default - localhost

set the socket server name (full host name or dotted decimal)

TPM_SERVER_TYPE

default - mssim

mssim - send packets in the Microsoft simulator format (header and footer)

raw - send packets in the raw TPM specification Part 3 format


TPM_COMMAND_PORT

default - 2321

set the socket port for TPM commands


TPM_PLATFORM_PORT

default - 2322

set the socket port for TPM simulator platform commands


TPM_DEVICE

Unix/Linux default - /dev/tpm0 (single user)

Windows default - Windows 7,8,10 Tbsi

For Unix, sets the TPM device name

/dev/tpmrm0 is the multi-user kernel resource manager

Once the kernel resource manager is upstreamed, this

may become the default.

For Windows, not currently used, only Tbsi supported

TPM_ENCRYPT_SESSIONS

default 1

1 - Session state is saved encrypted

0 - Session state is saved in plaintext


Since session state can potentially hold secrets, it should normally be encrypted. When the process terminates, the ephemeral encryption key is lost.


See 4.9 Command Line Utilities for the special case of using the command line utilities. That section is not applicable when using the TSS library in programs.


      1. TSS_SetProperty()


#include <tss2/tss.h>


TPM_RC TSS_SetProperty(TSS_CONTEXT *tssContext,

int property,

const char *value);



The TSS_SetProperty() function overrides the defaults and environment variables programmatically.

If the property is related to the connection, an open connection is closed before the property is processed.


NOTE: The close occurs even if the new value is the same as the old value. This can be used to close a connection without deleting the context.


Question: Is it good to mandate this behavior? It offers functionality and makes the implementation easier, but perhaps it's too clever?


NOTE: The value parameter is always a string. For simplicity, the 'value' pointer is stored. The input should be a constant string.


NOTE: For the property TPM_TRACE_LEVEL, tssContext is ignored. The trace level is per process, not per context.







    1. Extra Parameter


The extra parameter is a catch-all for any parameters that TSS_Execute() requires beyond the normal TPM command and response parameters.


TPM2_StartAuthSession needs the bind password so that it can calculate the session key.


    1. Other APIs and Headers


Headers are now in the …/utils/tss2 directory. This move (from …/utils) permits source to use this construct, compatible with an eventual header install in /usr/include/tss2:


#include <tss2/tss.h>


The utility / demo applications cheat a bit, in that they call into TSS utility functions. These are less likely to be stable than the official API above.












  1. Application Notes


Several areas have non-obvious usage. They are described here.


    1. TPM Simulator


A typical cause of a hang when sending the first command to the TPM simulator is that it has not received a simulated "powered up." Send this command:


> powerup


The platform firmware initializes a hardware TPM. The TPM simulator requires this command:


> startup


    1. Parameter Encryption


The caller does NOT perform parameter encryption. Simply set the session attribute to either or both of TPMA_SESSION_ENCRYPT or TPMA_SESSION_DECRYPT.


    1. Session Salt


To salt, the caller should set tpmKey (the handle of a loaded decrypt key) in TPM2_StartAuthSession. The key must be an RSA 2048-bit key or EC NIST P256 key with sign clear and decrypt set.


The caller must supply the extra parameter as a StartAuthSession_Extra structure.


The caller does NOT supply the HMAC salt. The encryptedSalt parameter is ignored, as the TSS generates the salt.


    1. Session Bind


To bind, the caller should set bind (the bind entity handle) in TPM2_StartAuthSession. The caller must supply the extra parameter as a StartAuthSession_Extra structure and set the bindPassword member to the bind handle password.


    1. NV


For applications that do not share an NV index and don't use global locks or transient locks that change after a reboot, the following details are unnecessary. Just issue the TPM2_NV_DefineSpace and everything works, including HMAC sessions.


For applications that do not satisfy the above criteria, the application must issue TPM2_NV_ReadPublic and validate that the public area is as expected, including the locks.

      1. Rationale


Why? For authorization, the TSS includes the Name (a hash of the public NV metadata) in the HMAC calculation. This ensures that the NV index has not been replaced with a different version with untrusted metadata.


Normally, the TSS tracks the Name, even when the application changes the written or lock attributes. However, if the attributes (and therefore the Name) change outside the application, the TSS is unable to track the change. In those cases, the application must read the public data and validate it.


Why doesn't the TSS automatically issue the TPM2_NV_ReadPublic? If it did that, it would encourage the application developer to blindly trust the index. The application is expected to examine the TPM2_NV_ReadPublic return (e.g., the policy, the attributes) and decide whether the index is trusted. The TSS cannot enforce this, but it does at least encourage it.


The index Name can change as the metadata changes. These changes include the "written" bit and the read and write locks. The TSS automatically tracks the changes performed on a single index by the application. It does not track:


  1. Changes "out of band", by a different application, including an attacker.


This will surface as an HMAC failure. The application should reissue TPM2_NV_ReadPublic and decide if the index is still trusted.


  1. Changes to transient lock status due to a reboot.


If the application is aware of the reboot, it can reissue TPM2_NV_ReadPublic and re-evaluate the return. Otherwise, it can wait for the potential HMAC failure and handle it as above.


  1. Locks due to a global lock, because it's hard and because global lock is expected to be used at provisioning, if ever.


This case will probably never occur in practice. If it does, handle the HMAC failure as above.


      1. NV Preprovisioning


This is the case where some other application has used TPM2_NV_DefineSpace to preprovision an index. As an alternative to the application evaluating the TPM2_NV_ReadPublic response, the NV metadata and Name can be preprovisioned when the application is installed. Two files are required:


[nnnnnnnn] is the hex value of the NV index.


  1. h[nnnnnnnn].bin - The Name, a binary hash of the public data

  2. nvp[nnnnnnnn].bin - The marshaled TPMS_NV_Public


    1. TPM2_LoadExternal


This command is unique, in that it has an optional parameter, TPM2B_SENSITIVE inPrivate. The caller should use the size as a flag: 0 for not present, and non-zero for present.


Rationale:


The TPM uses the inPrivate.size zero to indicate that the parameter is not present, and uses the correct marshaled size to indicate that the parameter is present. This TSS uses that design pattern, but, as with other TPM2B's that wrap structures, it does not require the caller to marshal the structure and determine the correct size.


    1. Connecting to Resource Managers


An issue arises when using the TSS utilities (not the TSS itself) on a platform with a resource manager. Windows currently has a resource manager (called TBS) and all OSes will eventually have one.


A resource manager flushes all resources (objects like keys, and sessions) when a connection closes. Since the utilities are standalone processes, the connection closes after each invocation. Thus, for example, a utility can load a key, but, when the "load" command terminates, the resource manager will flush the key.


This is not an issue for a complete application using the TSS, because the TSS will keep the connection open through multiple TPM commands. For prototyping using the utilities, the solution is to simulate this persistent connection behavior.


The "tpm_proxy" program connects as a socket server on one side and a TPM device driver on the other. Once the proxy starts, the resource manager sees one persistent connection, as desired. The utilities use the socket interface to the proxy.


The proxy (for both TPM 1.2 and TPM 2.0) is part of the tarball at


https://sourceforge.net/projects/ibmswtpm/files/?source=navbar


It is not well tested for TPM 2.0. I expect that the TPM_Startup call must be commented out, and that the TSS must run in "raw" mode.


    1. Endorsement Key (EK Certificates)


The TSS includes several TPM vendor EK root certificates for convenience.


There is no reason for a user to trust these certificates. Obtain production certificates directly from the TPM vendor.


These URLs are provided for convenience. Observe that some URLs are http. I encourage all readers to ask the TPM vendors to offer these certificates over a secured web page, since they form the root of trust for TPM authenticity.


Utilities such as "createek" that take a -root argument require a list of EK root certificates in a file. The utilities include a sample file …/utils/certificates/rootcerts.txt. The file MUST be edited, since the file names must have a complete path to your install directory.


Certificates must be in PEM format. To convert from DER format (.cer, .crt) to PEM using openssl:


> openssl x509 -in cert.cer -inform DER -out cert.pem


      1. Nuvoton


https://www.nuvoton.com/security/NTC-TPM-EK-Cert/Nuvoton%20TPM%20Root%20CA%202110.cer


https://www.nuvoton.com/security/NTC-TPM-EK-Cert/Nuvoton%20TPM%20Root%20CA%201110.cer


      1. St Micro


GlobalSign Trusted Computing CA


http://secure.globalsign.com/cacert/gstpmroot.crt


ST TPM Root certificate


http://secure.globalsign.com/cacert/stmtpmekroot.crt


ST Intermediate CA 01


http://secure.globalsign.com/cacert/stmtpmekint01.crt


ST Intermediate CA 02


http://secure.globalsign.com/cacert/stmtpmekint02.crt


ST Intermediate CA 03


http://secure.globalsign.com/cacert/stmtpmekint03.crt


ST Intermediate CA 04


http://secure.globalsign.com/cacert/stmtpmekint04.crt


ST Intermediate CA 05


http://secure.globalsign.com/cacert/stmtpmekint05.crt


GlobalSign Trusted Platform Module ECC


Root CA


http://secure.globalsign.com/cacert/tpmeccroot.crt


STM TPM ECC Root CA 01


http://secure.globalsign.com/stmtpmeccroot01.crt


STM TPM ECC Intermediate CA 01


http://secure.globalsign.com/stmtpmeccint01.crt


      1. Infineon


https://www.infineon.com/cms/en/product/promopages/optiga_tpm_certificates


      1. NationZ


Root


https://pki.nationz.com.cn/EkRootCA/EkRootCA.crt


Intermediate certificates


https://pki.nationz.com.cn/EkMfrCA001/EkMfrCA001.crt

https://pki.nationz.com.cn/EkMfrCA002/EkMfrCA002.crt

https://pki.nationz.com.cn/EkMfrCA003/EkMfrCA003.crt

      1. Intel


PTT EK Root Certificate


https://upgrades.intel.com/content/CRL/ekcert/EKRootPublicKey.cer


PTT EK Intermediate Certificate

http://upgrades.intel.com/content/CRL/ekcert/SPTHEPIDPROD_EK_Platform_Public_Key.cer

        1. Intel EK Certificate Download


As of June, 2017, the Intel PTT does not come provisioned with EK certificates. They must be downloaded using this procedure.



    1. Command Line Utilities


See also section 4.7 Connecting to Resource Managers.


As stated in section 3.4.2 Properties, the default is to build the TSS library to encrypt session state with an ephemeral encryption key that is lost when the application exits.


This behavior would preclude using the command line utilities with sessions, since the encryption key would change. There are two facilities to remedy this.


  1. For stand-alone debugging, save session state in plaintext. For example, use an environment variable:


> setenv TPM_ENCRYPT_SESSIONS 0


or the equivalent compile time flag


-DTPM_ENCRYPT_SESSIONS_DEFAULT="\"0\""


  1. For using the command line utilities securely, either stand-alone or in scripts, a fixed encryption key can be specified.


In the script:

TPM_SESSION_ENCKEY=`./getrandom -by 16 -ns`

On the command line:

> setenv TPM_SESSION_ENCKEY `./getrandom -by 16 -ns`


  1. Example

Each standalone utility serves as an example for a single command.


The signapp.c source shows how several commands can be chained together to form an application. It does the following:


  1. Build

The builds for Linux and Windows create the TSS shared object / dll and about 110 command line programs. The command line programs can be used in a script for rapid prototyping or as sample usage code.


The build files clear TPM_ENCRYPT_SESSIONS, which is useful for prototyping and regression testing. This should be removed for production applications.

    1. Directories


The TSS ships with these directories:


…/utils TSS and utility / demo applications

…/utils/regtests TSS regression tests

…/utils/policies TSS regression test policies and miscellaneous files

…/demo TSS demo web pages

…/tpmutils TSS Visual Studio files


To extract the tarball


> cd …

> tar xvf ibmtssnnn.tar .


    1. Linux


Install OpenSSL 1.0.x or 1.1.x.


> cd …/utils

> make


Note: Linux builds must have TPM_POSIX defined.


After building, run the regression test against a running simulator. -h gives help. The Linux version takes about 1 minute.


> ./reg.sh -a


The regression test can run against a software TPM at /dev/tpm0. It will skip the power up sequence. However, it uses the environment variable TPM_INTERFACE_TYPE as the determination. If the default TPM_INTERFACE_TYPE was changed at compile time, the regression test will try the power up sequence unless the environment variable is also set.


I would not expect the regression test to run against a hardware TPM, since the platform firmware will have set the platform authorization. There are likely to be other errors due to protected or unsupported TPM features.


Use the regression test for TSS verification, not as a TPM test tool.


The TPM device driver normally does not permit non-root access. Either


> chmod 777 /dev/tpm0


or run as root or sudo.


    1. Windows


Install OpenSSL. The usual place to get OpenSSL for Windows is http://slproweb.com/products/Win32OpenSSL.html. There is no need to build / compile from source. Just run the downloaded .exe.


Install OpenSSL 1.0.x, not 1.1.x, which is a major API departure from previous versions. The port to 1.1.x has not yet been tested on Windows.


Install Win32 OpenSSL, not the "Light" versions, which I believe do not contain the development files.


If you chose not to install OpenSSL in the recommended location, C:\Program Files\OpenSSL, you must fix the build paths. (In other words, use the recommended location.)


This directory should be added to the Path environment variable if it's not already there:


c:\Program Files\OpenSSL\bin


Note: Windows builds must have TPM_WINDOWS defined.


Build with Visual Studio using the solution …/tpmutils/tpmutils.sln


After building, run the regression test against a running simulator. The Windows version takes about 15 minutes.


The Windows script assumes that typical command line tools such as touch and diff are installed. A typical download location is


http://gnuwin32.sourceforge.net/packages.html


See CoreUtils and DiffUtils.


> reg.bat


The regression test script defaults to the executables being in the same directory as the script, …/tpm2/utils. This is correct for the gcc build, but not for the Visual Studio build. To point to those executables, set this environment variable. Do not omit the trailing slash.


> set TPM_EXE_PATH=../tpmutils/Debug/


      1. Windows Tbsi


These instructions have been lightly tested.


Users that use only the socket interface may not want to install Tbsi (Windows TPM Base Services). Undefine TPM_WINDOWS_TBSI to remove that dependency.


Note: To undefined the macro in Visual Studio:

  1. View - Other Windows - Property Manager

  2. Expand one of the projects

  3. Expand Debug (or Release if doing a release build)

  4. Double click CommonProperties

  5. Expand Common Properties, then C/C++, then select Preprocessor

  6. Next to Preprocessor Definitions, click the value, then the down arrow, then <Edit>

  7. Remove the macro TPM_WINDOWS_TBSI

  8. OK, OK


To build in Tbsi:




NOTE: For Windows 7, the alternate macro TPM_WINDOWS_TBSI_WIN7 uses the TPM 1.2 Tbsi API. I use it for light testing, but it is probably useless for a TPM 2.0.


Note: The TPM_WINDOWS_TBSI_WIN8 macro also supports Windows 10.



Note: For Windows 7, use c:/progra~1/Micros~2/Windows/v7.1/lib/Tbs.lib


      1. Windows Visual Studio


VS solution and project files are supplied. The Visual Studio 2013 Solution is …/tpmutils/tpmutils.sln.


It is currently configured to compile in the Windows (TPM_WINDOWS) TBSI (TPM_WINDOWS_TBSI) for Windows 8 (TPM_WINDOWS_TBSI_WIN8). It links with Tbs.lib.


The default is to connect to the socket simulator using the Microsoft simulator packet format. To change the default from a SW TPM to a HW TPM, add the preprocessor definition:


TPM_INTERFACE_TYPE_DEFAULT="dev"


      1. Windows gcc


A mingw (Minimalist GNU for Windows) makefile.mak is included. mingw from http://www.mingw.org/ must be installed.


winerror.h may have to be installed in C:\Program Files\MinGW\include


If the mingw install does not come with C:\Program Files\MinGW\include\tbs.h, a lightly tested file is included in the utils directory. Copy to C:\Program Files\MinGW\include.


Uncomment as indicated in makefile.mak to use the TBSI, either Windows 8 or Windows 7. Build using:


> cd …/utils

> make -f makefile.mak


    1. AIX


Use gnu make (gmake), not make.


> cd …/utils

> gmake -f makefile.aix


After building, run the regression test against a running Microsoft simulator. -h gives help. Since the TPM simulator does not run on AIX yet, set the TPM_SERVER_NAME environment variable.


> reg.sh -a


    1. Minimal TSS Library Builds


There are several compile time macros that permit building a subset of the TSS library. Features are lost, but the tradeoff may be important in some environments.


Since the regression test does not function against minimal builds, these variations are very lightly tested. Please report bugs.

      1. TPM_TSS_NOFILE


Defining this macro builds a TSS library that does not use files for temporary and persistent state. All state is stored in the TSS context and is lost when the context is deleted.


Drawbacks:



      1. TPM_TSS_NOCRYPTO


Defining this macro builds a TSS library that does not depend on a crypto library.


Drawbacks:



  1. Fedora

This section is only relevant to a Fedora rpm install. It is a work in progress, and may not be 100% correct yet.


The …/utils directory holds a sample makefile, makefile.sample that can be modified for a user application.


Prerequisite:


# yum install rpm-build

    1. Local Install


Download the rpms:


TBD


  1. Install binaries:



# rpm -ivh tss2-nnn-1.el6.x86_64.rpm


  1. Install development headers:



# rpm -ivh tss2-devel-nnn-1.el6.x86_64.rpm


  1. Install debug source and support


# rpm -ivh tss2-debuginfo-nnn-1.el6.x86_64.rpm


    1. Alternative Local Install



Erase an old version as needed:


# yum erase tss2-devel-nnn-1.el6.x86_64

# yum erase tss2-nnn-1.el6.x86_64

# yum erase tss2-debuginfo-nnn-1.el6.x86_64


Install (new method)


# dnf install ./tss2-nnn-1.el6.x86_64.rpm

# dnf install ./tss2-devel-nnn-1.el6.x86_64.rpm

# dnf install ./tss2-debuginfo-nnn-1.el6.x86_64.rpm


Install (old method)


# yum install ./tss2-nnn-1.el6.x86_64.rpm

# yum install ./tss2-devel-nnn-1.el6.x86_64.rpm

# yum install ./tss2-debuginfo-nnn-1.el6.x86_64.rpm


    1. Repository Install


Once the packages have been upstreamed, use this process.


# dnf install tss


    1. Install Test


This assumes that the SW TPM has been installed, see this link:


https://sourceforge.net/projects/ibmtpm20tss/?source=navbar


It also assumes that the regression test has been installed. See Section 7.5.


In reg.sh, change the utility prefix variable to tss.


PREFIX=tss


Run the regression test:


> cd ~/rpmbuild/BUILD/tss2-nnn/utils

> ./reg.sh


    1. Source rpms


Install source (as non-root user)


> rpm -ivh tss2-nnn-1.el6.src.rpm


The src rpm has a tarball and spec file. To build:


> cd ~/rpmbuild

> rpmbuild -bp SPECS/tss2.spec

> cd BUILD/tss2-nnn/utils

> make -f makefile.fedora



  1. Status

    1. Utilities


The utilities serve several purposes:



The bash regression test script itself is sample code for how to use the utilities and the TPM to perform multi-step tasks.




NOTE: The utility command line arguments are not stable. They change occasionally to improve consistency among utilities or to add features


The utilities currently do not permit all TPM command options. Let me know what needs enhancement.


    1. Bugs



Please report bugs.


    1. Untested


These may "just work" but they have not been tested yet.

Users are welcome to suggest ECC tests and prioritize the below list.




  1. Theading


The TSS is not thread safe.


There are many issues with making a TSS thread safe, because the TPM is inherently single threaded. For example:



I think the best we can do is provide a common "TSS lock semaphore" mechanism, so that threads can coordinate access to the TSS using a common API.

Page 31