TCG TPM2 r1p59 Part3 Commands Code Pub
TCG TPM2 r1p59 Part3 Commands Code Pub
Part 3: Commands
Family “2.0”
Level 00 Revision 01.59
November 8, 2019
Published
Contact: [email protected]
TCG Published
Copyright © TCG 2006-2020
TCG
Trusted Platform Module Library Part 3: Commands
CONTENTS
1 Scope .................................................................................................................................................... 1
2 Terms and Definitions ........................................................................................................................... 1
3 Symbols and abbreviated terms ............................................................................................................ 1
4 Notation ................................................................................................................................................. 2
4.1 Introduction ..................................................................................................................................... 2
4.2 Table Decorations ........................................................................................................................... 2
4.3 Handle and Parameter Demarcation .............................................................................................. 3
4.4 AuthorizationSize and ParameterSize ............................................................................................ 3
4.5 Return Code Alias ........................................................................................................................... 4
5 Command Processing ........................................................................................................................... 4
5.1 Introduction ..................................................................................................................................... 4
5.2 Command Header Validation .......................................................................................................... 4
5.3 Mode Checks .................................................................................................................................. 5
5.4 Handle Area Validation ................................................................................................................... 5
5.5 Session Area Validation .................................................................................................................. 6
5.6 Authorization Checks ...................................................................................................................... 7
5.7 Parameter Decryption ..................................................................................................................... 9
5.8 Parameter Unmarshaling ................................................................................................................ 9
5.9 Command Post Processing .......................................................................................................... 11
6 Response Values ................................................................................................................................ 12
6.1 Tag ................................................................................................................................................ 12
6.2 Response Codes .......................................................................................................................... 12
7 Implementation Dependent ................................................................................................................. 15
8 Detailed Actions Assumptions ............................................................................................................. 16
8.1 Introduction ................................................................................................................................... 16
8.2 Pre-processing .............................................................................................................................. 16
8.3 Post Processing ............................................................................................................................ 16
9 Start-up ................................................................................................................................................ 17
9.1 Introduction ................................................................................................................................... 17
9.2 _TPM_Init...................................................................................................................................... 17
9.3 TPM2_Startup ............................................................................................................................... 19
9.4 TPM2_Shutdown .......................................................................................................................... 27
10 Testing ................................................................................................................................................. 31
10.1 Introduction ................................................................................................................................... 31
10.2 TPM2_SelfTest ............................................................................................................................. 32
10.3 TPM2_IncrementalSelfTest .......................................................................................................... 35
10.4 TPM2_GetTestResult ................................................................................................................... 38
11 Session Commands ............................................................................................................................ 41
11.1 TPM2_StartAuthSession .............................................................................................................. 41
11.2 TPM2_PolicyRestart ..................................................................................................................... 47
12 Object Commands ............................................................................................................................... 50
12.1 TPM2_Create................................................................................................................................ 50
Tables
Table 1 — Command Modifiers and Decoration ........................................................................................... 2
Table 2 — Separators ................................................................................................................................... 3
Table 3 — Unmarshaling Errors ................................................................................................................. 10
Table 4 — Command-Independent Response Codes ................................................................................ 13
Table 5 — TPM2_Startup Command .......................................................................................................... 22
Table 6 — TPM2_Startup Response .......................................................................................................... 22
Table 7 — TPM2_Shutdown Command ..................................................................................................... 28
Table 8 — TPM2_Shutdown Response ...................................................................................................... 28
Table 9 — TPM2_SelfTest Command ........................................................................................................ 33
Table 10 — TPM2_SelfTest Response ...................................................................................................... 33
Table 11 — TPM2_IncrementalSelfTest Command ................................................................................... 36
Table 12 — TPM2_IncrementalSelfTest Response ................................................................................... 36
Table 13 — TPM2_GetTestResult Command ............................................................................................ 39
Table 14 — TPM2_GetTestResult Response............................................................................................. 39
Table 15 — TPM2_StartAuthSession Command ....................................................................................... 43
Table 16 — TPM2_StartAuthSession Response ........................................................................................ 43
Table 17 — TPM2_PolicyRestart Command .............................................................................................. 48
Table 18 — TPM2_PolicyRestart Response .............................................................................................. 48
Table 19 — TPM2_Create Command ........................................................................................................ 53
Table 20 — TPM2_Create Response ......................................................................................................... 53
Table 21 — TPM2_Load Command ........................................................................................................... 57
Table 22 — TPM2_Load Response ............................................................................................................ 57
Table 23 — TPM2_LoadExternal Command .............................................................................................. 62
Table 24 — TPM2_LoadExternal Response .............................................................................................. 62
Table 25 — TPM2_ReadPublic Command ................................................................................................. 66
Table 26 — TPM2_ReadPublic Response ................................................................................................. 66
Table 27 — TPM2_ActivateCredential Command ...................................................................................... 69
Table 28 — TPM2_ActivateCredential Response ...................................................................................... 69
Table 29 — TPM2_MakeCredential Command .......................................................................................... 73
Table 30 — TPM2_MakeCredential Response .......................................................................................... 73
Table 31 — TPM2_Unseal Command ........................................................................................................ 76
Table 32 — TPM2_Unseal Response ........................................................................................................ 76
Table 33 — TPM2_ObjectChangeAuth Command ..................................................................................... 79
Table 34 — TPM2_ObjectChangeAuth Response ..................................................................................... 79
Table 35 — TPM2_CreateLoaded Command ............................................................................................ 82
Table 36 — TPM2_CreateLoaded Response ............................................................................................. 82
Table 37 — TPM2_Duplicate Command .................................................................................................... 87
1 Scope
This TPM 2.0 Part 3 of the Trusted Platform Module Library specification contains the definitions of the
TPM commands. These commands make use of the constants, flags, structures, and union definitions
defined in TPM 2.0 Part 2.
The detailed description of the operation of the commands is written in the C language with extensive
comments. The behavior of the C code in this TPM 2.0 Part 3 is normative but does not fully describe the
behavior of a TPM. The combination of this TPM 2.0 Part 3 and TPM 2.0 Part 4 is sufficient to fully
describe the required behavior of a TPM.
The code in parts 3 and 4 is written to define the behavior of a compliant TPM. In some cases (e.g.,
firmware update), it is not possible to provide a compliant implementation. In those cases, any
implementation provided by the vendor that meets the general description of the function provided in TPM
2.0 Part 3 would be compliant.
The code in parts 3 and 4 is not written to meet any particular level of conformance nor does this
specification require that a TPM meet any particular level of conformance.
For the purposes of this document, the terms and definitions given in TPM 2.0 Part 1 apply.
For the purposes of this document, the symbols and abbreviated terms given in TPM 2.0 Part 1 apply.
4 Notation
4.1 Introduction
For the purposes of this document, the notation given in TPM 2.0 Part 1 applies.
Command and response tables use various decorations to indicate the fields of the command and the
allowed types. These decorations are described in this clause.
The symbols and terms in the Notation column of Table 1 are used in the tables for the command
schematics. These values indicate various qualifiers for the parameters or descriptions with which they
are associated.
@ A Name decoration – When this symbol precedes a handle parameter in the “Name” column, it
indicates that an authorization session is required for use of the entity associated with the handle.
If a handle does not have this symbol, then an authorization session is not allowed.
+PP A Description modifier – This modifier may follow TPM_RH_PLATFORM in the “Description”
column to indicate that Physical Presence is required when platformAuth/platformPolicy is
provided.
+{PP} A Description modifier – This modifier may follow TPM_RH_PLATFORM to indicate that Physical
Presence may be required when platformAuth/platformPolicy is provided. The commands with this
notation may be in the setList or clearList of TPM2_PP_Commands().
{NV} A Description modifier – This modifier may follow the commandCode in the “Description” column
to indicate that the command may result in an update of NV memory and be subject to rate
throttling by the TPM. If the command code does not have this notation, then a write to NV
memory does not occur as part of the command actions.
NOTE Any command that uses authorization may cause a write to NV if there is an authorization
failure. A TPM may use the occasion of command execution to update the NV copy of clock.
{F} A Description modifier – This modifier indicates that the “flushed” attribute will be SET in the
TPMA_CC for the command. The modifier may follow the commandCode in the “Description”
column to indicate that any transient handle context used by the command will be flushed from the
TPM when the command completes. This may be combined with the {NV} modifier but not with the
{E} modifier.
EXAMPLE 1 {NV F}
EXAMPLE 2 TPM2_SequenceComplete() will flush the context associated with the sequenceHandle.
{E} A Description modifier – This modifier indicates that the “extensive” attribute will be SET in the
TPMA_CC for the command. This modifier may follow the commandCode in the “Description”
column to indicate that the command may flush many objects and re-enumeration of the loaded
context likely will be required. This may be combined with the {NV} modifier but not with the {F}
modifier.
EXAMPLE 1 {NV E}
EXAMPLE 2 TPM2_Clear() will flush all contexts associated with the Storage hierarchy and the
Endorsement hierarchy.
Notation Meaning
Auth Index: A Description modifier – When a handle has a “@” decoration, the “Description” column will
contain an “Auth Index:” entry for the handle. This entry indicates the number of the authorization
session. The authorization sessions associated with handles will occur in the session area in the
order of the handles with the “@” modifier. Sessions used only for encryption/decryption or only for
audit will follow the handles used for authorization.
Auth Role: A Description modifier – This will be in the “Description” column of a handle with the “@”
decoration. It may have a value of USER, ADMIN or DUP.
If the handle has the Auth Role of USER and the handle is an Object, the type of authorization is
determined by the setting of userWithAuth in the Object's attributes. If the handle is
TPM_RH_OWNER, TPM_RH_ENDORSEMENT, or TPM_RH_PLATFORM, operation is as if
userWithAuth is SET. If the handle references an NV Index, then the allowed authorizations are
determined by the settings of the attributes of the NV Index as described in TPM 2.0 Part 2,
"TPMA_NV (NV Index Attributes)."
If the Auth Role is ADMIN and the handle is an Object, the type of authorization is determined by
the setting of adminWithPolicy in the Object's attributes. If the handle is TPM_RH_OWNER,
TPM_RH_ENDORSEMENT, or TPM_RH_PLATFORM, operation is as if adminWithPolicy is SET.
If the handle is an NV index, operation is as if adminWithPolicy is SET (see 5.6 e)2)).
If the DUP role is selected, authorization may only be with a policy session (DUP role only applies
to Objects).
When either ADMIN or DUP role is selected, a policy command that selects the command being
authorized is required to be part of the policy.
EXAMPLE TPM2_Certify requires the ADMIN role for the first handle (objectHandle). The policy
authorization for objectHandle is required to contain
TPM2_PolicyCommandCode(commandCode == TPM_CC_Certify). This sets the state of the
policy so that it can be used for ADMIN role authorization in TPM2_Certify().
The demarcations between the header, handle, and parameter parts are indicated by:
Table 2 — Separators
Separator Meaning
the values immediately following are in the handle area
Authorization sessions are not shown in the command or response schematics. When the tag of a
command or response is TPM_ST_SESSIONS, then a 32-bit value will be present in the
command/response buffer to indicate the size of the authorization field or the parameter field. This value
shall immediately follow the handle area (which may contain no handles). For a command, this value
(authorizationSize) indicates the size of the Authorization Area and shall have a value of 9 or more. For a
response, this value (parameterSize) indicates the size of the parameter area and may have a value of
zero.
If the authorizationSize field is present in the command, parameterSize will be present in the response,
but only if the responseCode is TPM_RC_SUCCESS.
When authorization is required to use the TPM entity associated with a handle, then at least one session
will be present. To indicate this, the command tag Description field contains TPM_ST_SESSIONS.
Addional sessions for audit, encrypt, and decrypt may be present.
When the command tag Description field contains TPM_ST_NO_SESSIONS, then no sessions are
allowed and the authorizationSize field is not present.
When a command allows use of sessions when not required, the command tag Description field will
indicate the types of sessions that may be used with the command.
For the RC_FMT1 return codes that may add a parameter, handle, or session number, the prefix
TPM_RCS_ is an alias for TPM_RC_.
TPM_RC_n is added, where n is the parameter, handle, or session number. In addition, TPM_RC_H is
added for handle, TPM_RC_P for parameter, and TPM_RC_S for session errors.
EXAMPLE 2 TPM2_HMAC_Start with parameters that result in TPM_ALG_NULL as the hash algorithm will
returns TPM_RC_VALUE plus the parameter number. Since hashAlg is the second parameter,
This code results:
5 Command Processing
5.1 Introduction
This clause defines the command validations that are required of any implementation and the response
code returned if the indicated check fails. Unless stated otherwise, the order of the checks is not
normative and different TPM may give different responses when a command has multiple errors.
In the description below, some statements that describe a check may be followed by a response code in
parentheses. This is the normative response code should the indicated check fail. A normative response
code may also be included in the statement.
Before a TPM may begin the actions associated with a command, a set of command format and
consistency checks shall be performed. These checks are listed below and should be performed in the
indicated order.
The TPM shall successfully unmarshal a TPMI_ST_COMMAND_TAG and verify that it is either
TPM_ST_SESSIONS or TPM_ST_NO_SESSIONS (TPM_RC_BAD_TAG).
The TPM shall successfully unmarshal a UINT32 as the commandSize. If the TPM has an interface
buffer that is loaded by some hardware process, the number of octets in the input buffer for the
command reported by the hardware process shall exactly match the value in commandSize
(TPM_RC_COMMAND_SIZE).
NOTE A TPM may have direct access to system memory and unmarshal directly from that memory.
The TPM shall successfully unmarshal a TPM_CC and verify that the command is implemented
(TPM_RC_COMMAND_CODE).
NOTE 1 In Failure mode, the TPM has no cryptographic capability and processing of sessions is not
supported.
NOTE 2 The TPM may enter Failure mode during _TPM_Init processing, before TPM2_Startup(). Since
the platform firmware cannot know that the TPM is in Failure mode without accessing it, and
since the first command is required to be TPM2_Startup(), the expected sequence will be that
platform firmware (the CRTM) will issue TPM2_Startup() and receive TPM_ RC_FAILURE
indicating that the TPM is in Failure mode.
There may be failures where a TPM cannot record that it received TPM2_Startup(). In those
cases, a TPM in failure mode may process TPM2_GetTestResult(), TPM2_GetCapability(), or
the field upgrade commands. As a side effect, that TPM may process TPM2_GetTestResult(),
TPM2_GetCapability() or the field upgrade commands before TPM2_Startup().
This is a corner case exception to the rule that TPM2_Startup() must be the first command.
The mode checks may be performed before or after the command header validation.
After successfully unmarshaling and validating the command header, the TPM shall perform the following
checks on the handles and sessions. These checks may be performed in any order.
NOTE 1 A TPM is required to perform the handle area validation before the authorization checks because an
authorization cannot be performed unless the authorization values and attributes for the referenced
entity are known by the TPM. For them to be k nown, the referenced entity must be in the TPM and
accessible.
The TPM shall successfully unmarshal the number of handles required by the command and validate
that the value of the handle is consistent with the command syntax. If not, the TPM shall return
TPM_RC_VALUE.
NOTE 2 The TPM may unmarshal a handle and validate that it references an entity on the TPM before
unmarshaling a subsequent handle.
NOTE 3 If the submitted command contains fewer handles than required by the syntax of the command,
the TPM may continue to read into the next area and attempt to interpret the data as a handle.
For all handles in the handle area of the command, the TPM will validate that the referenced entity is
present in the TPM.
1) If the handle references a transient object, the handle shall reference a loaded object
(TPM_RC_REFERENCE_H0 + N where N is the number of the handle in the command).
NOTE 4 If the hierarchy for a transient object is disabled, then the transient objects will be flushed
so this check will fail.
NOTE 5 The reference implementation keeps an internal attribute, passed do wn from a primary
key to its descendents, indicating the object's hierarchy.
iv) if the TPM implementation moves a persistent object to RAM for command processing then
sufficient RAM space is available (TPM_RC_OBJECT_MEMORY).
3) If the handle references an NV Index, then
i) an Index exists that corresponds to the handle (TPM_RC_HANDLE); and
ii) the hierarchy associated with the existing NV Index is not disabled (TPM_RC_HANDLE).
iii) If the command requires write access to the index data then TPMA_NV_WRITELOCKED is
not SET (TPM_RC_NV_LOCKED)
iv) If the command requires read access to the index data then TPMA_NV_READLOCKED is
not SET (TPM_RC_NV_LOCKED)
4) If the handle references a session, then the session context shall be present in TPM memory
(TPM_RC_REFERENCE_H0 + N).
5) If the handle references a primary seed for a hierarchy (TPM_RH_ENDORSEMENT,
TPM_RH_OWNER, or TPM_RH_PLATFORM) then the enable for the hierarchy is SET
(TPM_RC_HIERARCHY).
6) If the handle references a PCR, then the value is within the range of PCR supported by the TPM
(TPM_RC_VALUE)
If the tag is TPM_ST_SESSIONS and the command requires TPM_ST_NO_SESSIONS, the TPM will
return TPM_RC_AUTH_CONTEXT.
If the tag is TPM_ST_NO_SESSIONS and the command requires TPM_ST_SESSIONS, the TPM will
return TPM_RC_AUTH_MISSING.
If the tag is TPM_ST_SESSIONS, the TPM will attempt to unmarshal an authorizationSize and return
TPM_RC_AUTHSIZE if the value is not within an acceptable range.
1) The minimum value is (sizeof(TPM_HANDLE) + sizeof(UINT16) + sizeof(TPMA_SESSION) +
sizeof(UINT16)).
The TPM will unmarshal the authorization sessions and perform the following validations:
1) If the session handle is not a handle for an HMAC session, a handle for a policy session, or,
TPM_RS_PW then the TPM shall return TPM_RC_HANDLE.
2) If the session is not loaded, the TPM will return the warning TPM_RC_REFERENCE_S0 + N
where N is the number of the session. The first session is session zero, N = 0.
NOTE 2 If the HMAC and policy session contexts use the same memory, the type of the context
must match the type of the handle.
3) If the maximum allowed number of sessions have been unmarshaled and fewer octets than
indicated in authorizationSize were unmarshaled (that is, authorizationSize is too large), the TPM
shall return TPM_RC_AUTHSIZE.
4) The consistency of the authorization session attributes is checked.
i) Only one session is allowed for:
(a) session auditing (TPM_RC_ATTRIBUTES) – this session may be used for encrypt or
decrypt but may not be a session that is also used for authorization;
(b) decrypting a command parameter (TPM_RC_ATTRIBUTES) – this may be any of the
authorization sessions, or the audit session, or a session may be added for the single
purpose of decrypting a command parameter, as long as the total number of sessions
does not exceed three; and
(c) encrypting a response parameter (TPM_RC_ATTRIBUTES) – this may be any of the
authorization sessions, or the audit session if present, ora session may be added for the
single purpose of encrypting a response parameter, as long as the total number of
sessions does not exceed three.
NOTE 3 A session used for decrypting a command parameter may also be used for
encrypting a response parameter.
ii) If a session is not being used for authorization, at least one of decrypt, encrypt, or audit must
be SET. (TPM_RC_ATTRIBUTES).
5) An authorization session is present for each of the handles with the “@” decoration
(TPM_RC_AUTH_MISSING).
After unmarshaling and validating the handles and the consistency of the authorization sessions, the
authorizations shall be checked. Authorization checks only apply to handles if the handle in the command
schematic has the “@” decoration. Authorization checks must be performed in this order.
The public and sensitive portions of the object shall be present on the TPM
(TPM_RC_AUTH_UNAVAILABLE).
If the associated handle is TPM_RH_PLATFORM, and the command requires confirmation with
physical presence, then physical presence is asserted (TPM_RC_PP).
If the object or NV Index is subject to DA protection, and the authorization is with an HMAC or
password, then the TPM is not in lockout (TPM_RC_LOCKOUT).
Family “2.0” TCG Published Page 7
Level 00 Revision 01.59 Copyright © TCG 2006-2020 November 8, 2019
Part 3: Commands Trusted Platform Module Library
NOTE 1 An object is subject to DA protection if its noDA attribute is CLEAR. An NV Index is subject to
DA protection if its TPMA_NV_NO_DA attribute is CLEAR.
NOTE 2 An HMAC or password is required in a policy session when the policy contains
TPM2_PolicyAuthValue() or TPM2_PolicyPassword().
If the command requires a handle to have DUP role authorization, then the associated authorization
session is a policy session (TPM_RC_AUTH_TYPE).
If the command requires a handle to have ADMIN role authorization:
1) If the entity being authorized is an object and its adminWithPolicy attribute is SET, or a hierarchy,
then the authorization session is a policy session (TPM_RC_AUTH_TYPE).
2) If the entity being authorized is an NV Index, then the associated authorization session is a policy
session.
NOTE 4 The only commands that are currently defined that require use of ADMIN role authorization
are commands that operate on objects and NV Indices.
NOTE 5 There is no check for a hierarchy, because a hierarchy operates as if use rWithAuth is SET.
NOTE 6 A policy session may require proof of knowledge of the authValue of the object being
authorized.
If the authorization uses a password, then the password matches the authValue associated with the
handle (TPM_RC_AUTH_FAIL or TPM_RC_BAD_AUTH).
If the TPM returns an error other than TPM_RC_AUTH_FAIL then the TPM shall not alter any TPM state.
If the TPM return TPM_RC_AUTH_FAIL, then the TPM shall not alter any TPM state other than
lockoutCount.
NOTE 7 The TPM may decrease failedTries regardless of any other processing performed by the TPM. That
is, the TPM may exit Lockout mode, regardless of the return code.
If an authorization session has the TPMA_SESSION.decrypt attribute SET, and the command does not
allow a command parameter to be encrypted, then the TPM will return TPM_RC_ATTRIBUTES.
Otherwise, the TPM will decrypt the parameter using the values associated with the session before
parsing parameters.
Introduction
The detailed actions for each command assume that the input parameters of the command have been
unmarshaled into a command-specific structure with the structure defined by the command schematic.
Additionally, a response-specific output structure is assumed which will receive the values produced by
the detailed actions.
NOTE An implementation is not required to process parameters in this manner or to separate the
parameter parsing from the command actions. This method was chosen for the specification so that
the normative behavior described by the detailed actions would be clear and une ncumbered.
Unmarshaling is the process of processing the parameters in the input buffer and preparing the
parameters for use by the command-specific action code. No data movement need take place but it is
required that the TPM validate that the parameters meet the requirements of the expected data type as
defined in TPM 2.0 Part 2.
Unmarshaling Errors
When an error is encountered while unmarshaling a command parameter, an error response code is
returned and no command processing occurs. A table defining a data type may have response codes
embedded in the table to indicate the error returned when the input value does not match the parameters
of the table.
NOTE In the reference implementation, a parameter number is added to the response code so that the
offending parameter can be isolated. This is optional.
In many cases, the table contains no specific response code value and the return code will be determined
as defined in Table 3.
In some commands, a parameter may not be used because of various options of that command.
However, the unmarshaling code is required to validate that all parameters have values that are allowed
by the TPM 2.0 Part 2 definition of the parameter type even if that parameter is not used in the command
actions.
When the code that implements the detailed actions of the command completes, it returns a response
code. If that code is not TPM_RC_SUCCESS, the post processing code will not update any session or
audit data and will return a 10-octet response packet.
If the command completes successfully, the tag of the command determines if any authorization sessions
will be in the response. If so, the TPM will encrypt the first parameter of the response if indicated by the
authorization attributes. The TPM will then generate a new nonce value for each session and, if
appropriate, generate an HMAC.
If authorization HMAC computations are performed on the response, the HMAC keys used in the
response will be the same as the HMAC keys used in processing the HMAC in the command.
NOTE 1 This primarily affects authorizations associated with a first write to an NV Index using a bound
session. The computation of the HMAC in the response is performed as if the Name o f the Index did
not change as a consequence of the command actions. The session binding to the NV Index will not
persist to any subsequent command.
NOTE 2 The authorization attributes were validated during the session area validation to ensure that only
one session was used for parameter encryption of the response and that the command allowed
encryption in the response.
NOTE 3 No session nonce value is used for a password authorization but the session data is present.
Additionally, if the command is being audited by Command Audit, the audit digest is updated with the
cpHash of the command and rpHash of the response.
6 Response Values
6.1 Tag
When a command completes successfully, the tag parameter in the response shall have the same value
as the tag parameter in the command (TPM_ST_SESSIONS or TPM_ST_NO_SESSIONS). When a
command fails (the responseCode is not TPM_RC_SUCCESS), then the tag parameter in the response
shall be TPM_ST_NO_SESSIONS.
A special case exists when the command tag parameter is not an allowed value (TPM_ST_SESSIONS or
TPM_ST_NO_SESSIONS). For this case, it is assumed that the system software is attempting to send a
command formatted for a TPM 1.2 but the TPM is not capable of executing TPM 1.2 commands. So that
the TPM 1.2 compatible software will have a recognizable response, the TPM sets tag to
TPM_ST_RSP_COMMAND, responseSize to 00 00 00 0A16 and responseCode to TPM_RC_BAD_TAG.
This is the same response as the TPM 1.2 fatal error for TPM_BADTAG.
The normal response for any command is TPM_RC_SUCCESS. Any other value indicates that the
command did not complete and the state of the TPM is unchanged. An exception to this general rule is
that the logic associated with dictionary attack protection is allowed to be modified when an authorization
failure occurs.
Commands have response codes that are specific to that command, and those response codes are
enumerated in the detailed actions of each command. The codes associated with the unmarshaling of
parameters are documented Table 3. Another set of response code values are not command specific and
indicate a problem that is not specific to the command. That is, if the indicated problem is remedied, the
same command could be resubmitted and may complete normally.
The response codes that are not command specific are listed and described in
Table 4.
The reference code for the command actions may have code that generates specific response codes
associated with a specific check but the listing of responses may not have that response code listed.
7 Implementation Dependent
The actions code for each command makes assumptions about the behavior of various sub-systems.
There are many possible implementations of the subsystems that would achieve equivalent results. The
actions code is not written to anticipate all possible implementations of the sub-systems. Therefore, it is
the responsibility of the implementer to ensure that the necessary changes are made to the actions code
when the sub-system behavior changes.
8.1 Introduction
The C code in the Detailed Actions for each command is written with a set of assumptions about the
processing performed before the action code is called and the processing that will be done after the
action code completes.
8.2 Pre-processing
Before calling the command actions code, the following actions have occurred.
• Verification that the handles in the handle area reference entities that are resident on the TPM.
• NOTE If a handle is in the parameter portion of the command, the associated entity does not
have to be loaded, but the handle is required to be the correct type.
• If use of a handle requires authorization, the Password, HMAC, or Policy session associated with the
handle has been verified.
• If a command parameter was encrypted using parameter encryption, it was decrypted before being
unmarshaled.
• If the command uses handles or parameters, the calling stack contains a pointer to a data structure
(in) that holds the unmarshaled values for the handles and command parameters. If the response has
handles or parameters, the calling stack contains a pointer to a data structure (out) to hold the
handles and response parameters generated by the command.
• All parameters of the in structure have been validated and meet the requirements of the parameter
type as defined in TPM 2.0 Part 2.
• Space set aside for the out structure is sufficient to hold the largest out structure that could be
produced by the command
9 Start-up
9.1 Introduction
This clause contains the commands used to manage the startup and restart state of a TPM.
9.2 _TPM_Init
General Description
NOTE 1 If the TPM performs self-tests after receiving _TPM_Init() and the TPM enters Failure mode before
receiving TPM2_Startup() or TPM2_FieldUpgradeData(), then the TPM may be able to accept
TPM2_GetTestResult() or TPM2_GetCapability().
The means of signaling _TPM_Init shall be defined in the platform-specific specifications that define the
physical interface to the TPM. The platform shall send this indication whenever the platform starts its boot
process and only when the platform starts its boot process.
There shall be no software method of generating this indication that does not also reset the platform and
begin execution of the CRTM.
NOTE 2 In the reference implementation, this signal causes an internal flag ( s_initialized) to be CLEAR.
While this flag is CLEAR, the TPM will only accept the next expected command described above.
Detailed Actions
1 #include "Tpm.h"
2 #include "_TPM_Init_fp.h"
3 // This function is used to process a _TPM_Init indication.
4 LIB_EXPORT void
5 _TPM_Init(
6 void
7 )
8 {
9 g_powerWasLost = g_powerWasLost | _plat__WasPowerLost();
10
11 #if SIMULATION && DEBUG
12 // If power was lost and this was a simulation, put canary in RAM used by NV
13 // so that uninitialized memory can be detected more easily
14 if(g_powerWasLost)
15 {
16 memset(&gc, 0xbb, sizeof(gc));
17 memset(&gr, 0xbb, sizeof(gr));
18 memset(&gp, 0xbb, sizeof(gp));
19 memset(&go, 0xbb, sizeof(go));
20 }
21 #endif
22
23 #if SIMULATION
24 // Clear the flag that forces failure on self-test
25 g_forceFailureMode = FALSE;
26 #endif
27
28 // Disable the tick processing
29 _plat__ACT_EnableTicks(FALSE);
30
31 // Set initialization state
32 TPMInit();
33
34 // Set g_DRTMHandle as unassigned
35 g_DRTMHandle = TPM_RH_UNASSIGNED;
36
37 // No H-CRTM, yet.
38 g_DrtmPreStartup = FALSE;
39
40 // Initialize the NvEnvironment.
41 g_nvOk = NvPowerOn();
42
43 // Initialize cryptographic functions
44 g_inFailureMode = (CryptInit() == FALSE);
45 if(!g_inFailureMode)
46 {
47 // Load the persistent data
48 NvReadPersistent();
49
50 // Load the orderly data (clock and DRBG state).
51 // If this is not done here, things break
52 NvRead(&go, NV_ORDERLY_DATA, sizeof(go));
53
54 // Start clock. Need to do this after NV has been restored.
55 TimePowerOn();
56 }
57 return;
58 }
9.3 TPM2_Startup
General Description
TPM2_Startup() is always preceded by _TPM_Init, which is the physical indication that TPM initialization
is necessary because of a system-wide reset. TPM2_Startup() is only valid after _TPM_Init. Additional
TPM2_Startup() commands are not allowed after it has completed successfully. If a TPM requires
TPM2_Startup() and another command is received, or if the TPM receives TPM2_Startup() when it is not
required, the TPM shall return TPM_RC_INITIALIZE.
NOTE 1 See 9.2.1 for other command options for a TPM supporting field upgrade mode.
NOTE 2 _TPM_Hash_Start, _TPM_Hash_Data, and _TPM_Hash_End are not commands and a platform -
specific specification may allow these indications between _TPM_Init and TPM2_Startup().
If in Failure mode, the TPM shall accept TPM2_GetTestResult() and TPM2_GetCapability() even if
TPM2_Startup() is not completed successfully or processed at all.
A platform-specific specification may restrict the localities at which TPM2_Startup() may be received.
A Shutdown/Startup sequence determines the way in which the TPM will operate in response to
TPM2_Startup(). The three sequences are:
1) TPM Reset – This is a Startup(CLEAR) preceded by either Shutdown(CLEAR) or no
TPM2_Shutdown(). On TPM Reset, all variables go back to their default initialization state.
NOTE 3 Only those values that are specified as having a default initialization state are changed by TPM
Reset. Persistent values that have no default initialization state are not changed by this
command. Values such as seeds have no default initialization state and only change due to
specific commands.
2) TPM Restart – This is a Startup(CLEAR) preceded by Shutdown(STATE). This preserves much of the
previous state of the TPM except that PCR and the controls associated with the Platform hierarchy
are all returned to their default initialization state;
3) TPM Resume – This is a Startup(STATE) preceded by Shutdown(STATE). This preserves the
previous state of the TPM including the static Root of Trust for Measurement (S-RTM) PCR and the
platform controls other than the phEnable.
If a TPM receives Startup(STATE) and that was not preceded by Shutdown(STATE), the TPM shall return
TPM_RC_VALUE.
If, during TPM Restart or TPM Resume, the TPM fails to restore the state saved at the last
Shutdown(STATE), the TPM shall enter Failure Mode and return TPM_RC_FAILURE.
On any TPM2_Startup(),
• phEnable shall be SET;
• all transient contexts (objects, sessions, and sequences) shall be flushed from TPM memory;
On TPM Reset:
• platformAuth and platformPolicy shall be set to the Empty Buffer,
• For each NV Index with TPMA_NV_WRITEDEFINE CLEAR or TPMA_NV_WRITTEN CLEAR,
TPMA_NV_WRITELOCKED shall be CLEAR,
• For each NV Index with TPMA_NV_ORDERLY SET, TPMA_NV_WRITTEN shall be CLEAR unless
the type is TPM_NT_COUNTER,
• On a disorderly reset, advance the orderly counters,
• For each NV Index with TPMA_NV_CLEAR_STCLEAR SET, TPMA_NV_WRITTEN shall be CLEAR,
• tracking data for saved session contexts shall be set to its initial value,
• the object context sequence number is reset to zero,
• a new context encryption key shall be generated,
• TPMS_CLOCK_INFO.restartCount shall be reset to zero,
• TPMS_CLOCK_INFO.resetCount shall be incremented,
• the PCR Update Counter shall be clear to zero,
NOTE 5 Because the PCR update counter may be incremented when a P CR is reset, the PCR resets
performed as part of this command can result in the PCR update counter being non -zero at the
end of this command.
NOTE 6 PCR may be initialized any time between _TPM_Init and the end of TPM2_Startup(). PCR that
are preserved by TPM Resume will need to be restored during TPM2_Startup().
NOTE 7 See "Initializing PCR" in TPM 2.0 Part 1 for a description of the default initial conditions for a
PCR.
On TPM Restart:
• TPMS_CLOCK_INFO.restartCount shall be incremented,
• phEnableNV, shEnable and ehEnable shall be SET,
• platformAuth and platformPolicy shall be set to the Empty Buffer,
• For each NV index with TPMA_NV_WRITEDEFINE CLEAR or TPMA_NV_WRITTEN CLEAR,
TPMA_NV_WRITELOCKED shall be CLEAR,
• For each NV index with TPMA_NV_CLEAR_STCLEAR SET, TPMA_NV_WRITTEN shall be CLEAR,
and
• PCR in all banks are reset to their default initial conditions.
• If an H-CRTM Event Sequence is active, extend the PCR designated by the platform-specific
specification.
• For each ACT the timeout is reset to zero, the signaled attribute is set to CLEAR (if preserveSignaled
is CLEAR), and the authPolicy is set to the Empty Buffer and its hashAlg is set to TPM_ALG_NULL.
On TPM Resume:
• the H-CRTM startup method is the same for this TPM2_Startup() as for the previous TPM2_Startup();
(TPM_RC_LOCALITY)
• TPMS_CLOCK_INFO.restartCount shall be incremented; and
• PCR that are specified in a platform-specific specification to be preserved on TPM Resume are
restored to their saved state and other PCR are set to their initial value as determined by a platform-
specific specification. For constraints, see TPM 2.0 Part 1, H-CRTM before TPM2_Startup() and
TPM2_Startup without H-CRTM.
• The ACT timeout, the ACT signaled attribute and the ACT specific authPolicy values are preserved.
Other TPM state may change as required to meet the needs of the implementation.
If the startupType is TPM_SU_STATE and the TPM requires TPM_SU_CLEAR, then the TPM shall return
TPM_RC_VALUE.
NOTE 8 The TPM will require TPM_SU_CLEAR when no shutdown was performed or after
Shutdown(CLEAR).
NOTE 9 If startupType is neither TPM_SU_STATE nor TPM_SU_CLEAR, then the unmarshaling code returns
TPM_RC_VALUE.
Detailed Actions
1 #include "Tpm.h"
2 #include "Startup_fp.h"
3 #if CC_Startup // Conditional expansion of this file
4 TPM_RC
5 TPM2_Startup(
6 Startup_In *in // IN: input parameter list
7 )
8 {
9 STARTUP_TYPE startup;
10 BYTE locality = _plat__LocalityGet();
11 BOOL OK = TRUE;
12 //
13 // The command needs NV update.
14 RETURN_IF_NV_IS_NOT_AVAILABLE;
15
16 // Get the flags for the current startup locality and the H-CRTM.
17 // Rather than generalizing the locality setting, this code takes advantage
18 // of the fact that the PC Client specification only allows Startup()
19 // from locality 0 and 3. To generalize this probably would require a
20 // redo of the NV space and since this is a feature that is hardly ever used
21 // outside of the PC Client, this code just support the PC Client needs.
22
23 // Input Validation
24 // Check that the locality is a supported value
25 if(locality != 0 && locality != 3)
26 return TPM_RC_LOCALITY;
27 // If there was a H-CRTM, then treat the locality as being 3
28 // regardless of what the Startup() was. This is done to preserve the
29 // H-CRTM PCR so that they don't get overwritten with the normal
30 // PCR startup initialization. This basically means that g_StartupLocality3
31 // and g_DrtmPreStartup can't both be SET at the same time.
32 if(g_DrtmPreStartup)
33 locality = 0;
34 g_StartupLocality3 = (locality == 3);
35
36 #if USE_DA_USED
37 // If there was no orderly shutdown, then their might have been a write to
38 // failedTries that didn't get recorded but only if g_daUsed was SET in the
39 // shutdown state
40 g_daUsed = (gp.orderlyState == SU_DA_USED_VALUE);
41 if(g_daUsed)
42 gp.orderlyState = SU_NONE_VALUE;
43 #endif
44
45 g_prevOrderlyState = gp.orderlyState;
46
47 // If there was a proper shutdown, then the startup modifiers are in the
48 // orderlyState. Turn them off in the copy.
49 if(IS_ORDERLY(g_prevOrderlyState))
50 g_prevOrderlyState &= ~(PRE_STARTUP_FLAG | STARTUP_LOCALITY_3);
51 // If this is a Resume,
52 if(in->startupType == TPM_SU_STATE)
53 {
54 // then there must have been a prior TPM2_ShutdownState(STATE)
55 if(g_prevOrderlyState != TPM_SU_STATE)
56 return TPM_RCS_VALUE + RC_Startup_startupType;
57 // and the part of NV used for state save must have been recovered
58 // correctly.
59 // NOTE: if this fails, then the caller will need to do Startup(CLEAR). The
60 // code for Startup(Clear) cannot fail if the NV can't be read correctly
61 // because that would prevent the TPM from ever getting unstuck.
62 if(g_nvOk == FALSE)
63 return TPM_RC_NV_UNINITIALIZED;
64 // For Resume, the H-CRTM has to be the same as the previous boot
65 if(g_DrtmPreStartup != ((gp.orderlyState & PRE_STARTUP_FLAG) != 0))
66 return TPM_RCS_VALUE + RC_Startup_startupType;
67 if(g_StartupLocality3 != ((gp.orderlyState & STARTUP_LOCALITY_3) != 0))
68 return TPM_RC_LOCALITY;
69 }
70 // Clean up the gp state
71 gp.orderlyState = g_prevOrderlyState;
72
73 // Internal Date Update
74 if((gp.orderlyState == TPM_SU_STATE) && (g_nvOk == TRUE))
75 {
76 // Always read the data that is only cleared on a Reset because this is not
77 // a reset
78 NvRead(&gr, NV_STATE_RESET_DATA, sizeof(gr));
79 if(in->startupType == TPM_SU_STATE)
80 {
81 // If this is a startup STATE (a Resume) need to read the data
82 // that is cleared on a startup CLEAR because this is not a Reset
83 // or Restart.
84 NvRead(&gc, NV_STATE_CLEAR_DATA, sizeof(gc));
85 startup = SU_RESUME;
86 }
87 else
88 startup = SU_RESTART;
89 }
90 else
91 // Will do a TPM reset if Shutdown(CLEAR) and Startup(CLEAR) or no shutdown
92 // or there was a failure reading the NV data.
93 startup = SU_RESET;
94 // Startup for cryptographic library. Don't do this until after the orderly
95 // state has been read in from NV.
96 OK = OK && CryptStartup(startup);
97
98 // When the cryptographic library has been started, indicate that a TPM2_Startup
99 // command has been received.
100 OK = OK && TPMRegisterStartup();
101
102 // Read the platform unique value that is used as VENDOR_PERMANENT
103 // authorization value
104 g_platformUniqueDetails.t.size
105 = (UINT16)_plat__GetUnique(1, sizeof(g_platformUniqueDetails.t.buffer),
106 g_platformUniqueDetails.t.buffer);
107
108 // Start up subsystems
109 // Start set the safe flag
110 OK = OK && TimeStartup(startup);
111
112 // Start dictionary attack subsystem
113 OK = OK && DAStartup(startup);
114
115 // Enable hierarchies
116 OK = OK && HierarchyStartup(startup);
117
118 // Restore/Initialize PCR
119 OK = OK && PCRStartup(startup, locality);
120
121 // Restore/Initialize command audit information
122 OK = OK && CommandAuditStartup(startup);
123
124 // Restore the ACT
125 OK = OK && ActStartup(startup);
126
127 //// The following code was moved from Time.c where it made no sense
128 if(OK)
129 {
130 switch(startup)
131 {
132 case SU_RESUME:
133 // Resume sequence
134 gr.restartCount++;
135 break;
136 case SU_RESTART:
137 // Hibernate sequence
138 gr.clearCount++;
139 gr.restartCount++;
140 break;
141 default:
142 // Reset object context ID to 0
143 gr.objectContextID = 0;
144 // Reset clearCount to 0
145 gr.clearCount = 0;
146
147 // Reset sequence
148 // Increase resetCount
149 gp.resetCount++;
150
151 // Write resetCount to NV
152 NV_SYNC_PERSISTENT(resetCount);
153
154 gp.totalResetCount++;
155 // We do not expect the total reset counter overflow during the life
156 // time of TPM. if it ever happens, TPM will be put to failure mode
157 // and there is no way to recover it.
158 // The reason that there is no recovery is that we don't increment
159 // the NV totalResetCount when incrementing would make it 0. When the
160 // TPM starts up again, the old value of totalResetCount will be read
161 // and we will get right back to here with the increment failing.
162 if(gp.totalResetCount == 0)
163 FAIL(FATAL_ERROR_INTERNAL);
164
165 // Write total reset counter to NV
166 NV_SYNC_PERSISTENT(totalResetCount);
167
168 // Reset restartCount
169 gr.restartCount = 0;
170
171 break;
172 }
173 }
174 // Initialize session table
175 OK = OK && SessionStartup(startup);
176
177 // Initialize object table
178 OK = OK && ObjectStartup();
179
180 // Initialize index/evict data. This function clears read/write locks
181 // in NV index
182 OK = OK && NvEntityStartup(startup);
183
184 // Initialize the orderly shut down flag for this cycle to SU_NONE_VALUE.
185 gp.orderlyState = SU_NONE_VALUE;
186
187 OK = OK && NV_SYNC_PERSISTENT(orderlyState);
188
189 // This can be reset after the first completion of a TPM2_Startup() after
190 // a power loss. It can probably be reset earlier but this is an OK place.
191 if(OK)
192 g_powerWasLost = FALSE;
193
194 return (OK) ? TPM_RC_SUCCESS : TPM_RC_FAILURE;
195 }
196 #endif // CC_Startup
9.4 TPM2_Shutdown
General Description
This command is used to prepare the TPM for a power cycle. The shutdownType parameter indicates
how the subsequent TPM2_Startup() will be processed.
For a shutdownType of any type, the volatile portion of Clock is saved to NV memory and the orderly
shutdown indication is SET. NV Indexes with the TPMA_NV_ORDERLY attribute will be updated.
For a shutdownType of TPM_SU_STATE, the following additional items are saved:
• tracking information for saved session contexts;
• the session context counter;
• PCR that are designated as being preserved by TPM2_Shutdown(TPM_SU_STATE);
• the PCR Update Counter;
• flags associated with supporting the TPMA_NV_WRITESTCLEAR and TPMA_NV_READSTCLEAR
attributes;
• the counter value and authPolicy for each ACT; and
NOTE If a counter has not been updated since the las t TPM2_Startup(), then the saved value will be one
half of the current counter value.
Detailed Actions
1 #include "Tpm.h"
2 #include "Shutdown_fp.h"
3 #if CC_Shutdown // Conditional expansion of this file
4 TPM_RC
5 TPM2_Shutdown(
6 Shutdown_In *in // IN: input parameter list
7 )
8 {
9 // The command needs NV update. Check if NV is available.
10 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
11 // this point
12 RETURN_IF_NV_IS_NOT_AVAILABLE;
13
14 // Input Validation
15
16 // If PCR bank has been reconfigured, a CLEAR state save is required
17 if(g_pcrReConfig && in->shutdownType == TPM_SU_STATE)
18 return TPM_RCS_TYPE + RC_Shutdown_shutdownType;
19
20 // Internal Data Update
21
22 gp.orderlyState = in->shutdownType;
23
24 // PCR private date state save
25 PCRStateSave(in->shutdownType);
26
27 // Save the ACT state
28 ActShutdown(in->shutdownType);
29
30 // Save RAM backed NV index data
31 NvUpdateIndexOrderlyData();
32
33 #if ACCUMULATE_SELF_HEAL_TIMER
34 // Save the current time value
35 go.time = g_time;
36 #endif
37
38 // Save all orderly data
39 NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go);
40
41 if(in->shutdownType == TPM_SU_STATE)
42 {
43 // Save STATE_RESET and STATE_CLEAR data
44 NvWrite(NV_STATE_CLEAR_DATA, sizeof(STATE_CLEAR_DATA), &gc);
45 NvWrite(NV_STATE_RESET_DATA, sizeof(STATE_RESET_DATA), &gr);
46
47 // Save the startup flags for resume
48 if(g_DrtmPreStartup)
49 gp.orderlyState = TPM_SU_STATE | PRE_STARTUP_FLAG;
50 else if(g_StartupLocality3)
51 gp.orderlyState = TPM_SU_STATE | STARTUP_LOCALITY_3;
52 }
53 // only two shutdown options.
54 else if(in->shutdownType != TPM_SU_CLEAR)
55 return TPM_RCS_VALUE + RC_Shutdown_shutdownType;
56
57 NV_SYNC_PERSISTENT(orderlyState);
58
59 return TPM_RC_SUCCESS;
60 }
61 #endif // CC_Shutdown
10 Testing
10.1 Introduction
Compliance to standards for hardware security modules may require that the TPM test its functions
before the results that depend on those functions may be returned. The TPM may perform operations
using testable functions before those functions have been tested as long as the TPM returns no value
that depends on the correctness of the testable function.
EXAMPLE TPM2_PCR_Extend() may be executed before the hash algorithms have been tested. However, until
the hash algorithms have been tested, the contents of a PCR may not be used in any command if
that command may result in a value being returned to the TPM user. This means that
TPM2_PCR_Read() or TPM2_PolicyPCR() could not complete until the hashes have been checked
but other TPM2_PCR_Extend() commands may be executed even though the operation uses
previous PCR values.
If a command is received that requires return of a value that depends on untested functions, the TPM
shall test the required functions before completing the command.
Once the TPM has received TPM2_SelfTest() and before completion of all tests, the TPM is required to
return TPM_RC_TESTING for any command that uses a function that requires a test.
If a self-test fails at any time, the TPM will enter Failure mode. While in Failure mode, the TPM will return
TPM_RC_FAILURE for any command other than TPM2_GetTestResult() and TPM2_GetCapability(). The
TPM will remain in Failure mode until the next _TPM_Init.
10.2 TPM2_SelfTest
General Description
This command causes the TPM to perform a test of its capabilities. If the fullTest is YES, the TPM will test
all functions. If fullTest = NO, the TPM will only test those functions that have not previously been tested.
If any tests are required, the TPM shall either
• return TPM_RC_TESTING and begin self-test of the required functions, or
NOTE 1 If fullTest is NO, and all functions have been tested, the TPM shall return TPM_RC_SUCCESS.
• perform the tests and return the test result when complete. On failure, the TPM shall return
TPM_RC_FAILURE.
If the TPM uses option a), the TPM shall return TPM_RC_TESTING for any command that requires use
of a testable function, even if the functions required for completion of the command have already been
tested.
NOTE 2 This command may cause the TPM to continue processing after it has returned the response. So
that software can be notified of the completion of the te sting, the interface may include controls that
would allow the TPM to generate an interrupt when the “background” processing is complete. This
would be in addition to the interrupt that may be available for signaling normal command completion.
It is not necessary that there be two interrupts, but the interface should provide a way to indicate the
nature of the interrupt (normal command or deferred command).
NOTE 3 The PC Client platform specific TPM, in response to fullTest YES, will not return
TPM_RC_TESTING. It will block until all tests are complete.
Detailed Actions
1 #include "Tpm.h"
2 #include "SelfTest_fp.h"
3 #if CC_SelfTest // Conditional expansion of this file
4 TPM_RC
5 TPM2_SelfTest(
6 SelfTest_In *in // IN: input parameter list
7 )
8 {
9 // Command Output
10
11 // Call self test function in crypt module
12 return CryptSelfTest(in->fullTest);
13 }
14 #endif // CC_SelfTest
10.3 TPM2_IncrementalSelfTest
General Description
This command causes the TPM to perform a test of the selected algorithms.
NOTE 1 The toTest list indicates the algorithms that software would like the TPM to test in anticipation of
future use. This allows tests to be done so that a future commands will not be delayed due to
testing.
The implementation may treat algorithms on the toTest list as either 'test each completely' or 'test
this combination.'
EXAMPLE If the toTest list includes AES and CTR mode, it may be interpreted as a request to test only AES in
CTR mode. Alternatively, it may be interpreted as a request to test AES in all modes and CTR mode
for all symmetric algorithms.
If toTest contains an algorithm that has already been tested, it will not be tested again.
NOTE 2 The only way to force retesting of an algorithm is with TPM2_SelfTest( fullTest = YES).
The TPM will return in toDoList a list of algorithms that are yet to be tested. This list is not the list of
algorithms that are scheduled to be tested but the algorithms/functions that have not been tested. Only
the algorithms on the toTest list are scheduled to be tested by this command.
NOTE 3 An algorithm remains on the toDoList while any part of it remains untested.
EXAMPLE A symmetric algorithm remains untested until it is tested with all its modes.
Making toTest an empty list allows the determination of the algorithms that remain untested without
triggering any testing.
If toTest is not an empty list, the TPM shall return TPM_RC_SUCCESS for this command and then return
TPM_RC_TESTING for any subsequent command (including TPM2_IncrementalSelfTest()) until the
requested testing is complete.
NOTE 4 If toDoList is empty, then no additional tests are required and TPM_RC_TESTING will not be
returned in subsequent commands and no additional delay will occur in a command due to testing.
NOTE 5 If none of the algorithms listed in toTest is in the toDoList, then no tests will be performed.
NOTE 6 The TPM cannot return TPM_RC_TESTING for the first call to this command even when testing is
not complete, because response parameters can only returned with the TPM_RC_SUCCESS return
code.
If all the parameters in this command are valid, the TPM returns TPM_RC_SUCCESS and the toDoList
(which may be empty).
NOTE 7 An implementation may perform all requested tests before returning TPM_RC_SUCCESS, or it may
return TPM_RC_SUCCESS for this command and then return TPM_RC_TESTING for all
subsequence commands (including TPM2_IncrementatSelfTest()) until the requested tests are
complete.
Detailed Actions
1 #include "Tpm.h"
2 #include "IncrementalSelfTest_fp.h"
3 #if CC_IncrementalSelfTest // Conditional expansion of this file
4 TPM_RC
5 TPM2_IncrementalSelfTest(
6 IncrementalSelfTest_In *in, // IN: input parameter list
7 IncrementalSelfTest_Out *out // OUT: output parameter list
8 )
9 {
10 TPM_RC result;
11 // Command Output
12
13 // Call incremental self test function in crypt module. If this function
14 // returns TPM_RC_VALUE, it means that an algorithm on the 'toTest' list is
15 // not implemented.
16 result = CryptIncrementalSelfTest(&in->toTest, &out->toDoList);
17 if(result == TPM_RC_VALUE)
18 return TPM_RCS_VALUE + RC_IncrementalSelfTest_toTest;
19 return result;
20 }
21 #endif // CC_IncrementalSelfTest
10.4 TPM2_GetTestResult
General Description
This command returns manufacturer-specific information regarding the results of a self-test and an
indication of the test status.
If TPM2_SelfTest() has not been executed and a testable function has not been tested, testResult will be
TPM_RC_NEEDS_TEST. If TPM2_SelfTest() has been received and the tests are not complete,
testResult will be TPM_RC_TESTING.
If testing of all functions is complete without functional failures, testResult will be TPM_RC_SUCCESS. If
any test failed, testResult will be TPM_RC_FAILURE.
This command will operate when the TPM is in Failure mode so that software can determine the test
status of the TPM and so that diagnostic information can be obtained for use in failure analysis. If the
TPM is in Failure mode, then tag is required to be TPM_ST_NO_SESSIONS or the TPM shall return
TPM_RC_FAILURE.
NOTE The reference implementation may return a 32-bit value s_failFunction. This simply gives a unique
value to each of the possible places where a failure could occur. It is not intended to provide a
pointer to the function. __func__ is a pointer to a character string but the failure mode code can only
return 32-bit values. It is expected that the manufacturer can disambiguate this value if a customer’s
TPM goes into failure mode.
Detailed Actions
1 #include "Tpm.h"
2 #include "GetTestResult_fp.h"
3 #if CC_GetTestResult // Conditional expansion of this file
In the reference implementation, this function is only reachable if the TPM is not in failure mode meaning
that all tests that have been run have completed successfully. There is not test data and the test result is
TPM_RC_SUCCESS.
4 TPM_RC
5 TPM2_GetTestResult(
6 GetTestResult_Out *out // OUT: output parameter list
7 )
8 {
9 // Command Output
10
11 // Call incremental self test function in crypt module
12 out->testResult = CryptGetTestResult(&out->outData);
13
14 return TPM_RC_SUCCESS;
15 }
16 #endif // CC_GetTestResult
11 Session Commands
11.1 TPM2_StartAuthSession
General Description
This command is used to start an authorization session using alternative methods of establishing the
session key (sessionKey). The session key is then used to derive values used for authorization and for
encrypting parameters.
This command allows injection of a secret into the TPM using either asymmetric or symmetric encryption.
The type of tpmKey determines how the value in encryptedSalt is encrypted. The decrypted secret value
is used to compute the sessionKey.
The label value of “SECRET” (see “Terms and Definitions” in TPM 2.0 Part 1) is used in the recovery of
the secret value.
The TPM generates the sessionKey from the recovered secret value.
No authorization is required for tpmKey or bind.
NOTE 2 The justification for using tpmKey without providing authorization is that the result of using the key is
not available to the caller, except indirectly through the sessionKey. This does not represent a point
of attack on the value of the key. If the caller attempts to use the session without knowing the
sessionKey value, it is an authorization failure that will trigger the dictionary attack logic.
The entity referenced with the bind parameter contributes an authorization value to the sessionKey
generation process.
If both tpmKey and bind are TPM_RH_NULL, then sessionKey is set to the Empty Buffer. If tpmKey is not
TPM_RH_NULL, then encryptedSalt is used in the computation of sessionKey. If bind is not
TPM_RH_NULL, the authValue of bind is used in the sessionKey computation.
If symmetric specifies a block cipher, then TPM_ALG_CFB is the only allowed value for the mode field in
the symmetric parameter (TPM_RC_MODE).
This command starts an authorization session and returns the session handle along with an initial
nonceTPM in the response.
If the TPM does not have a free slot for an authorization session, it shall return
TPM_RC_SESSION_HANDLES.
If the TPM implements a “gap” scheme for assigning contextID values, then the TPM shall return
TPM_RC_CONTEXT_GAP if creating the session would prevent recycling of old saved contexts (See
“Context Management” in TPM 2.0 Part 1).
If tpmKey is not TPM_ALG_NULL then encryptedSalt shall be a TPM2B_ENCRYPTED_SECRET of the
proper type for tpmKey. The TPM shall return TPM_RC_HANDLE if the sensitive portion of tpmKey is not
loaded. The TPM shall return TPM_RC_VALUE if:
tpmKey references an RSA key and
1) the size of encryptedSalt is not the same as the size of the public modulus of tpmKey,
2) encryptedSalt has a value that is greater than the public modulus of tpmKey,
3) encryptedSalt is not a properly encoded OAEP value, or
4) the decrypted salt value is larger than the size of the digest produced by the nameAlg of tpmKey;
or
NOTE 3 The asymScheme of the key object is ignored in this case and TPM_ALG_OAEP is used, even if
asymScheme is set to TPM_ALG_NULL.
NOTE 4 When ECC is used, the point multiply process produces a value (Z) that is used in a KDF to
produce the final secret value. The size of the secret value is an input parameter to the KDF
and the result will be set to be the size of the digest produced by the nameAlg of tpmKey.
The TPM shall return TPM_RC_KEY if tpmkey does not reference an asymmetric key. The TPM shall
return TPM_RC_VALUE if the scheme of the key is not TPM_ALG_OAEP or TPM_ALG_NULL. The TPM
shall return TPM_RC_ATTRIBUTES if tpmKey does not have the decrypt attribute SET.
If bind references a transient object, then the TPM shall return TPM_RC_HANDLE if the sensitive portion
of the object is not loaded.
For all session types, this command will cause initialization of the sessionKey and may establish binding
between the session and an object (the bind object). If sessionType is TPM_SE_POLICY or
TPM_SE_TRIAL, the additional session initialization is:
• set policySession→policyDigest to a Zero Digest (the digest size for policySession→policyDigest is
the size of the digest produced by authHash);
• authorization may be given at any locality;
• authorization may apply to any command code;
• authorization may apply to any command parameters or handles;
• the authorization has no time limit;
• an authValue is not needed when the authorization is used;
• the session is not bound;
• the session is not an audit session; and
• the time at which the policy session was created is recorded.
Additionally, if sessionType is TPM_SE_TRIAL, the session will not be usable for authorization but can be
used to compute the authPolicy for an object.
NOTE 5 Although this command changes the session allocation information in the TPM, it does not invalidate
a saved context. That is, TPM2_Shutdown() is not required after this command in order to re -
establish the orderly state of the TPM. This is because the created context will occupy an available
slot in the TPM and sessions in the TPM do not survive any TPM2_Startup(). However, if a created
session is context saved, the orderly state does change.
The TPM shall return TPM_RC_SIZE if nonceCaller is less than 16 octets or is greater than the size of
the digest produced by authHash.
Detailed Actions
1 #include "Tpm.h"
2 #include "StartAuthSession_fp.h"
3 #if CC_StartAuthSession // Conditional expansion of this file
4 TPM_RC
5 TPM2_StartAuthSession(
6 StartAuthSession_In *in, // IN: input parameter buffer
7 StartAuthSession_Out *out // OUT: output parameter buffer
8 )
9 {
10 TPM_RC result = TPM_RC_SUCCESS;
11 OBJECT *tpmKey; // TPM key for decrypt salt
12 TPM2B_DATA salt;
13
14 // Input Validation
15
16 // Check input nonce size. IT should be at least 16 bytes but not larger
17 // than the digest size of session hash.
18 if(in->nonceCaller.t.size < 16
19 || in->nonceCaller.t.size > CryptHashGetDigestSize(in->authHash))
20 return TPM_RCS_SIZE + RC_StartAuthSession_nonceCaller;
21
22 // If an decrypt key is passed in, check its validation
23 if(in->tpmKey != TPM_RH_NULL)
24 {
25 // Get pointer to loaded decrypt key
26 tpmKey = HandleToObject(in->tpmKey);
27
28 // key must be asymmetric with its sensitive area loaded. Since this
29 // command does not require authorization, the presence of the sensitive
30 // area was not already checked as it is with most other commands that
31 // use the sensitive are so check it here
32 if(!CryptIsAsymAlgorithm(tpmKey->publicArea.type))
33 return TPM_RCS_KEY + RC_StartAuthSession_tpmKey;
34 // secret size cannot be 0
35 if(in->encryptedSalt.t.size == 0)
36 return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt;
37 // Decrypting salt requires accessing the private portion of a key.
38 // Therefore, tmpKey can not be a key with only public portion loaded
39 if(tpmKey->attributes.publicOnly)
40 return TPM_RCS_HANDLE + RC_StartAuthSession_tpmKey;
41 // HMAC session input handle check.
42 // tpmKey should be a decryption key
43 if(!IS_ATTRIBUTE(tpmKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
44 return TPM_RCS_ATTRIBUTES + RC_StartAuthSession_tpmKey;
45 // Secret Decryption. A TPM_RC_VALUE, TPM_RC_KEY or Unmarshal errors
46 // may be returned at this point
47 result = CryptSecretDecrypt(tpmKey, &in->nonceCaller, SECRET_KEY,
48 &in->encryptedSalt, &salt);
49 if(result != TPM_RC_SUCCESS)
50 return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt;
51 }
52 else
53 {
54 // secret size must be 0
55 if(in->encryptedSalt.t.size != 0)
56 return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt;
57 salt.t.size = 0;
58 }
59 switch(HandleGetType(in->bind))
60 {
61 case TPM_HT_TRANSIENT:
62 {
63 OBJECT *object = HandleToObject(in->bind);
64 // If the bind handle references a transient object, make sure that we
65 // can get to the authorization value. Also, make sure that the object
66 // has a proper Name (nameAlg != TPM_ALG_NULL). If it doesn't, then
67 // it might be possible to bind to an object where the authValue is
68 // known. This does not create a real issue in that, if you know the
69 // authorization value, you can actually bind to the object. However,
70 // there is a potential
71 if(object->attributes.publicOnly == SET)
72 return TPM_RCS_HANDLE + RC_StartAuthSession_bind;
73 break;
74 }
75 case TPM_HT_NV_INDEX:
76 // a PIN index can't be a bind object
77 {
78 NV_INDEX *nvIndex = NvGetIndexInfo(in->bind, NULL);
79 if(IsNvPinPassIndex(nvIndex->publicArea.attributes)
80 || IsNvPinFailIndex(nvIndex->publicArea.attributes))
81 return TPM_RCS_HANDLE + RC_StartAuthSession_bind;
82 break;
83 }
84 default:
85 break;
86 }
87 // If 'symmetric' is a symmetric block cipher (not TPM_ALG_NULL or TPM_ALG_XOR)
88 // then the mode must be CFB.
89 if(in->symmetric.algorithm != TPM_ALG_NULL
90 && in->symmetric.algorithm != TPM_ALG_XOR
91 && in->symmetric.mode.sym != TPM_ALG_CFB)
92 return TPM_RCS_MODE + RC_StartAuthSession_symmetric;
93
94 // Internal Data Update and command output
95
96 // Create internal session structure. TPM_RC_CONTEXT_GAP, TPM_RC_NO_HANDLES
97 // or TPM_RC_SESSION_MEMORY errors may be returned at this point.
98 //
99 // The detailed actions for creating the session context are not shown here
100 // as the details are implementation dependent
101 // SessionCreate sets the output handle and nonceTPM
102 result = SessionCreate(in->sessionType, in->authHash, &in->nonceCaller,
103 &in->symmetric, in->bind, &salt, &out->sessionHandle,
104 &out->nonceTPM);
11.2 TPM2_PolicyRestart
General Description
This command allows a policy authorization session to be returned to its initial state. This command is
used after the TPM returns TPM_RC_PCR_CHANGED. That response code indicates that a policy will
fail because the PCR have changed after TPM2_PolicyPCR() was executed. Restarting the session
allows the authorizations to be replayed because the session restarts with the same nonceTPM. If the
PCR are valid for the policy, the policy may then succeed.
This command does not reset the policy ID or the policy start time.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyRestart_fp.h"
3 #if CC_PolicyRestart // Conditional expansion of this file
4 TPM_RC
5 TPM2_PolicyRestart(
6 PolicyRestart_In *in // IN: input parameter list
7 )
8 {
9 // Initialize policy session data
10 SessionResetPolicyData(SessionGet(in->sessionHandle));
11
12 return TPM_RC_SUCCESS;
13 }
14 #endif // CC_PolicyRestart
12 Object Commands
12.1 TPM2_Create
General Description
This command is used to create an object that can be loaded into a TPM using TPM2_Load(). If the
command completes successfully, the TPM will create the new object and return the object’s creation
data (creationData), its public area (outPublic), and its encrypted sensitive area (outPrivate). Preservation
of the returned data is the responsibility of the caller. The object will need to be loaded (TPM2_Load())
before it may be used. The only difference between the inPublic TPMT_PUBLIC template and the
outPublic TPMT_PUBLIC object is in the unique field.
NOTE 1 This command may require temporary use of a transient resource, even though the object does not
remain loaded after the command. See Part 1 Transient Resources.
TPM2B_PUBLIC template (inPublic) contains all of the fields necessary to define the properties of the
new object. The setting for these fields is defined in “Public Area Template” in Part 1 of this specification
and in “TPMA_OBJECT” in Part 2 of this specification. The size of the unique field shall not be checked
for consistency with the other object parameters.
NOTE 2 For interoperability, the unique field should not be set to a value that is larger than allowed by object
parameters, so that the unmarshaling will not fail. A size of zero is recommended. After
unmarshaling, the TPM does not use the input unique field. It is, however, used in
TPM2_CreatePrimary() and TPM2_CreateLoaded.
EXAMPLE 1 A TPM_ALG_RSA object with a keyBits of 2048 in the object’s parameters should have a unique
field that is no larger than 256 bytes.
The parentHandle parameter shall reference a loaded decryption key that has both the public and
sensitive area loaded.
When defining the object, the caller provides a template structure for the object in a TPM2B_PUBLIC
structure (inPublic), an initial value for the object’s authValue (inSensitive.userAuth), and, if the object is a
symmetric object, an optional initial data value (inSensitive.data). The TPM shall validate the consistency
of the attributes of inPublic according to the Creation rules in “TPMA_OBJECT” in TPM 2.0 Part 2.
The inSensitive parameter may be encrypted using parameter encryption.
The methods in this clause are used by both TPM2_Create() and TPM2_CreatePrimary(). When a value
is indicated as being TPM-generated, the value is filled in by bits from the RNG if the command is
TPM2_Create() and with values from KDFa() if the command is TPM2_CreatePrimary(). The parameters
of each creation value are specified in TPM 2.0 Part 1.
The sensitiveDataOrigin attribute of inPublic shall be SET if inSensitive.data is an Empty Buffer and
CLEAR if inSensitive.data is not an Empty Buffer or the TPM shall return TPM_RC_ATTRIBUTES.
If the Object is a not a keyedHash object, and the sign and encrypt attributes are CLEAR, the TPM shall
return TPM_RC_ATTRIBUTES.
The TPM will create new data for the sensitive area and compute a TPMT_PUBLIC.unique from the
sensitive area based on the object type:
For a symmetric key:
1) If inSensitive.sensitive.data is the Empty Buffer, a TPM-generated key value is placed in the new
object’s TPMT_SENSITIVE.sensitive.sym. The size of the key will be determined by
inPublic.publicArea.parameters.
Page 50 TCG Published Family “2.0”
November 8, 2019 Copyright © TCG 2006-2020 Level 00 Revision 01.59
Trusted Platform Module Library Part 3: Commands
2) If inSensitive.sensitive.data is not the Empty Buffer, the TPM will validate that the size of
inSensitive.data is no larger than the key size indicated in the inPublic template (TPM_RC_SIZE)
and copy the inSensitive.data to TPMT_SENSITIVE.sensitive.sym of the new object.
3) A TPM-generated obfuscation value is placed in TPMT_SENSITIVE.sensitive.seedValue. The
size of the obfuscation value is the size of the digest produced by the nameAlg in inPublic. This
value prevents the public unique value from leaking information about the sensitive area.
4) The TPMT_PUBLIC.unique.sym value for the new object is then generated, as shown in equation
(1) below, by hashing the key and obfuscation values in the TPMT_SENSITIVE with the nameAlg
of the object.
unique ≔ HnameAlg(sensitive.seedValue.buffer || sensitive.any.buffer) (1)
If the Object is an asymmetric key:
1) If inSensitive.sensitive.data is not the Empty Buffer, then the TPM shall return TPM_RC_VALUE.
2) A TPM-generated private key value is created with the size determined by the parameters of
inPublic.publicArea.parameters.
3) If the key is a Storage Key, a TPM-generated TPMT_SENSITIVE.seedValue value is created;
otherwise, TPMT_SENSITIVE.seedValue.size is set to zero.
NOTE 3 An Object that is not a storage key has no child Objects to encrypt, so it does not need a
symmetric key.
4) The public unique value is computed from the private key according to the methods of the key
type.
5) If the key is an ECC key and the scheme required by the curveID is not the same as scheme in
the public area of the template, then the TPM shall return TPM_RC_SCHEME.
6) If the key is an ECC key and the KDF required by the curveID is not the same as kdf in the pubic
area of the template, then the TPM shall return TPM_RC_KDF.
NOTE 4 There is currently no command in which the caller may specify the KDF to be used with an
ECC decryption key. Since there is no use for this capability, the reference implementation
requires that the kdf in the template be set to TPM_ALG_NULL or TPM_RC_KDF is
returned.
NOTE 5 Revisions 134 and earlier reference code did not check the error case of
sensitiveDataOrigin SET and an Empty Buffer. Thus, some TPM implementations may also
not have included this error check.
2) If sign and decrypt are both CLEAR, or if sign and decrypt are both SET and the scheme in the
public area of the template is not TPM_ALG_NULL, the TPM shall return TPM_RC_SCHEME.
NOTE 6 Revisions 138 and earlier did not enforce this error case.
4) If inSensitive.sensitive.data is an Empty Buffer, a TPM-generated key value that is the size of the
digest produced by the nameAlg in inPublic is placed in TPMT_SENSITIVE.sensitive.bits.
5) A TPM-generated obfuscation value that is the size of the digest produced by the nameAlg of
inPublic is placed in TPMT_SENSITIVE.seedValue.
6) The TPMT_PUBLIC.unique.keyedHash value for the new object is then generated, as shown in
equation (1) above, by hashing the key and obfuscation values in the TPMT_SENSITIVE with the
nameAlg of the object.
For TPM2_Load(), the TPM will apply normal symmetric protections to the created TPMT_SENSITIVE to
create outPublic.
NOTE 8 The encryption key is derived from the symmetric seed in the sensitive area of the parent.
In addition to outPublic and outPrivate, the TPM will build a TPMS_CREATION_DATA structure for the
object. TPMS_CREATION_DATA.outsideInfo is set to outsideInfo. This structure is returned in
creationData. Additionally, the digest of this structure is returned in creationHash, and, finally, a
TPMT_TK_CREATION is created so that the association between the creation data and the object may
be validated by TPM2_CertifyCreation().
If the object being created is a Storage Key and fixedParent is SET in the attributes of inPublic, then the
symmetric algorithms and parameters of inPublic are required to match those of the parent. The
algorithms that must match are inPublic.nameAlg, and the values in inPublic.parameters that select the
symmetric scheme. If inPublic.nameAlg does not match, the TPM shall return TPM_RC_HASH.If the
symmetric scheme of the key does not match, the parent, the TPM shall return TPM_RC_SYMMETRIC.
The TPM shall not use different response code to differentiate between mismatches of the components of
inPublic.parameters. However, after this verification, when using the scheme to encrypt child objects, the
TPM ignores the symmetric mode and uses TPM_ALG_CFB.
NOTE 10 Prior to revision 01.34, the parent asymmetric algorithms were also checked for fixedParent storage
keys.
Detailed Actions
1 #include "Tpm.h"
2 #include "Object_spt_fp.h"
3 #include "Create_fp.h"
4 #if CC_Create // Conditional expansion of this file
5 TPM_RC
6 TPM2_Create(
7 Create_In *in, // IN: input parameter list
8 Create_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result = TPM_RC_SUCCESS;
12 OBJECT *parentObject;
13 OBJECT *newObject;
14 TPMT_PUBLIC *publicArea;
15
16 // Input Validation
17 parentObject = HandleToObject(in->parentHandle);
18 pAssert(parentObject != NULL);
19
20 // Does parent have the proper attributes?
21 if(!ObjectIsParent(parentObject))
22 return TPM_RCS_TYPE + RC_Create_parentHandle;
23
24 // Get a slot for the creation
25 newObject = FindEmptyObjectSlot(NULL);
26 if(newObject == NULL)
27 return TPM_RC_OBJECT_MEMORY;
28 // If the TPM2B_PUBLIC was passed as a structure, marshal it into is canonical
29 // form for processing
30
31 // to save typing.
32 publicArea = &newObject->publicArea;
33
34 // Copy the input structure to the allocated structure
35 *publicArea = in->inPublic.publicArea;
36
37 // Check attributes in input public area. CreateChecks() checks the things that
38 // are unique to creation and then validates the attributes and values that are
39 // common to create and load.
40 result = CreateChecks(parentObject, publicArea,
41 in->inSensitive.sensitive.data.t.size);
42 if(result != TPM_RC_SUCCESS)
43 return RcSafeAddToResult(result, RC_Create_inPublic);
44 // Clean up the authValue if necessary
45 if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg))
46 return TPM_RCS_SIZE + RC_Create_inSensitive;
47
48 // Command Output
49 // Create the object using the default TPM random-number generator
50 result = CryptCreateObject(newObject, &in->inSensitive.sensitive, NULL);
51 if(result != TPM_RC_SUCCESS)
52 return result;
53 // Fill in creation data
54 FillInCreationData(in->parentHandle, publicArea->nameAlg,
55 &in->creationPCR, &in->outsideInfo,
56 &out->creationData, &out->creationHash);
57
58 // Compute creation ticket
59 TicketComputeCreation(EntityGetHierarchy(in->parentHandle), &newObject->name,
60 &out->creationHash, &out->creationTicket);
61
62 // Prepare output private data from sensitive
63 SensitiveToPrivate(&newObject->sensitive, &newObject->name, parentObject,
64 publicArea->nameAlg,
65 &out->outPrivate);
66
67 // Finish by copying the remaining return values
68 out->outPublic.publicArea = newObject->publicArea;
69
70 return TPM_RC_SUCCESS;
71 }
72 #endif // CC_Create
12.2 TPM2_Load
General Description
This command is used to load objects into the TPM. This command is used when both a TPM2B_PUBLIC
and TPM2B_PRIVATE are to be loaded. If only a TPM2B_PUBLIC is to be loaded, the
TPM2_LoadExternal command is used.
NOTE 1 Loading an object is not the same as restoring a saved object context.
The object’s TPMA_OBJECT attributes will be checked according to the rules defined in
“TPMA_OBJECT” in TPM 2.0 Part 2 of this specification. If the Object is a not a keyedHash object, and
the sign and encrypt attributes are CLEAR, the TPM shall return TPM_RC_ATTRIBUTES.
Objects loaded using this command will have a Name. The Name is the concatenation of nameAlg and
the digest of the public area using the nameAlg.
NOTE 3 Checking the integrity before the data is used prevents attacks on the sensitive area by fuzzing the
data and looking at the differences in the response codes.
The command returns a handle for the loaded object and the Name that the TPM computed for
inPublic.public (that is, the digest of the TPMT_PUBLIC structure in inPublic).
NOTE 4 The TPM-computed Name is provided as a convenience to the caller for those cases where the
caller does not implement the hash algorithms specified in the nameAlg of the object.
NOTE 5 The returned handle is associated with the object until the object is flushed (TPM2_FlushContext) or
until the next TPM2_Startup.
For all objects, the size of the key in the sensitive area shall be consistent with the key size indicated in
the public area or the TPM shall return TPM_RC_KEY_SIZE.
Before use, a loaded object shall be checked to validate that the public and sensitive portions are
properly linked, cryptographically. Use of an object includes use in any policy command. If the parts of the
object are not properly linked, the TPM shall return TPM_RC_BINDING. If a weak symmetric key is in the
sensitive portion, the TPM shall return TPM_RC_KEY.
EXAMPLE 1 For a symmetric object, the unique value in the public area shall be the digest of the sensitive key
and the obfuscation value.
EXAMPLE 2 For a two-prime RSA key, the remainder when dividing the public modulus by the private key shall
be zero and it shall be possible to form a private exponent from the two prime factors of the public
modulus.
EXAMPLE 3 For an ECC key, the public point shall be f(x) where x is the private key.
Detailed Actions
1 #include "Tpm.h"
2 #include "Load_fp.h"
3 #if CC_Load // Conditional expansion of this file
4 #include "Object_spt_fp.h"
5 TPM_RC
6 TPM2_Load(
7 Load_In *in, // IN: input parameter list
8 Load_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result = TPM_RC_SUCCESS;
12 TPMT_SENSITIVE sensitive;
13 OBJECT *parentObject;
14 OBJECT *newObject;
15
16 // Input Validation
17 // Don't get invested in loading if there is no place to put it.
18 newObject = FindEmptyObjectSlot(&out->objectHandle);
19 if(newObject == NULL)
20 return TPM_RC_OBJECT_MEMORY;
21
22 if(in->inPrivate.t.size == 0)
23 return TPM_RCS_SIZE + RC_Load_inPrivate;
24
25 parentObject = HandleToObject(in->parentHandle);
26 pAssert(parentObject != NULL);
27 // Is the object that is being used as the parent actually a parent.
28 if(!ObjectIsParent(parentObject))
29 return TPM_RCS_TYPE + RC_Load_parentHandle;
30
31 // Compute the name of object. If there isn't one, it is because the nameAlg is
32 // not valid.
33 PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name);
34 if(out->name.t.size == 0)
35 return TPM_RCS_HASH + RC_Load_inPublic;
36
37 // Retrieve sensitive data.
38 result = PrivateToSensitive(&in->inPrivate.b, &out->name.b, parentObject,
39 in->inPublic.publicArea.nameAlg,
40 &sensitive);
41 if(result != TPM_RC_SUCCESS)
42 return RcSafeAddToResult(result, RC_Load_inPrivate);
43
44 // Internal Data Update
45 // Load and validate object
46 result = ObjectLoad(newObject, parentObject,
47 &in->inPublic.publicArea, &sensitive,
48 RC_Load_inPublic, RC_Load_inPrivate,
49 &out->name);
50 if(result == TPM_RC_SUCCESS)
51 {
52 // Set the common OBJECT attributes for a loaded object.
53 ObjectSetLoadedAttributes(newObject, in->parentHandle);
54 }
55 return result;
56
57 }
58 #endif // CC_Load
12.3 TPM2_LoadExternal
General Description
This command is used to load an object that is not a Protected Object into the TPM. The command allows
loading of a public area or both a public and sensitive area.
NOTE 1 Typical use for loading a public area is to allow the TPM to validate an asymmetric signature.
Typical use for loading both a public and sensitive area is to allow the TPM to be used as a crypto
accelerator.
Load of a public external object area allows the object to be associated with a hierarchy so that the
correct algorithms may be used when creating tickets. The hierarchy parameter provides this association.
If the public and sensitive portions of the object are loaded, hierarchy is required to be TPM_RH_NULL.
NOTE 2 If both the public and private portions of an object are loaded, the object is not allowed to appear to
be part of a hierarchy.
The object’s TPMA_OBJECT attributes will be checked according to the rules defined in
“TPMA_OBJECT” in TPM 2.0 Part 2. In particular, fixedTPM, fixedParent, and restricted shall be CLEAR
if inPrivate is not the Empty Buffer.
NOTE 3 The duplication status of a public key needs to be able to be the same as the full key which may be
resident on a different TPM. If both the public and private parts of the key are loaded, then it is not
possible for the key to be either fixedTPM or fixedParent, since, its private area would not be
available in the clear to load.
Objects loaded using this command will have a Name. The Name is the nameAlg of the object
concatenated with the digest of the public area using the nameAlg. The Qualified Name for the object will
be the same as its Name. The TPM will validate that the authPolicy is either the size of the digest
produced by nameAlg or the Empty Buffer.
NOTE 4 If nameAlg is TPM_ALG_NULL, then the Name is the Empty Buffer. When the authorization value for
an object with no Name is computed, no Name value is included in the HMAC. To ensure that these
unnamed entities are not substituted, they should have an authValue that is statistically unique.
If the nameAlg is TPM_ALG_NULL, the TPM shall not verify the cryptographic binding between the public
and sensitive areas, but the TPM will validate that the size of the key in the sensitive area is consistent
with the size indicated in the public area. If it is not, the TPM shall return TPM_RC_KEY_SIZE.
NOTE 6 For an ECC object, the TPM will verify that the public key is on the curve of the key before the public
area is used.
If nameAlg is not TPM_ALG_NULL, then the same consistency checks between inPublic and inPrivate
are made as for TPM2_Load().
NOTE 7 Consistency checks are necessary because an object with a Name needs to have the public and
sensitive portions cryptographically bound so that an attacker cannot mix pubic and sensitive areas.
The command returns a handle for the loaded object and the Name that the TPM computed for
inPublic.public (that is, the TPMT_PUBLIC structure in inPublic).
NOTE 8 The TPM-computed Name is provided as a convenience to the caller for those cases where the
caller does not implement the hash algorithm specified in the nameAlg of the object.
The hierarchy parameter associates the external object with a hierarchy. External objects are flushed
when their associated hierarchy is disabled. If hierarchy is TPM_RH_NULL, the object is part of no
hierarchy, and there is no implicit flush.
If hierarchy is TPM_RH_NULL or nameAlg is TPM_ALG_NULL, a ticket produced using the object shall
be a NULL Ticket.
EXAMPLE If a key is loaded with hierarchy set to TPM_RH_NULL, then TPM2_VerifySignature() will produce a
NULL Ticket of the required type.
External objects are Temporary Objects. The saved external object contexts shall be invalidated at the
next TPM Reset.
If a weak symmetric key is in the sensitive area, the TPM shall return TPM_RC_KEY.
For an RSA key, the private exponent is computed using the two prime factors of the public modulus. One
of the primes is P, and the second prime (Q) is found by dividing the public modulus by P. A TPM may
return an error (TPM_RC_BINDING) if the bit size of P and Q are not the same.”
Detailed Actions
1 #include "Tpm.h"
2 #include "LoadExternal_fp.h"
3 #if CC_LoadExternal // Conditional expansion of this file
4 #include "Object_spt_fp.h"
5 TPM_RC
6 TPM2_LoadExternal(
7 LoadExternal_In *in, // IN: input parameter list
8 LoadExternal_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result;
12 OBJECT *object;
13 TPMT_SENSITIVE *sensitive = NULL;
14
15 // Input Validation
16 // Don't get invested in loading if there is no place to put it.
17 object = FindEmptyObjectSlot(&out->objectHandle);
18 if(object == NULL)
19 return TPM_RC_OBJECT_MEMORY;
20
21 // If the hierarchy to be associated with this object is turned off, the object
22 // cannot be loaded.
23 if(!HierarchyIsEnabled(in->hierarchy))
24 return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy;
25
26 // For loading an object with both public and sensitive
27 if(in->inPrivate.size != 0)
28 {
29 // An external object with a sensitive area can only be loaded in the
30 // NULL hierarchy
31 if(in->hierarchy != TPM_RH_NULL)
32 return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy;
33 // An external object with a sensitive area must have fixedTPM == CLEAR
12.4 TPM2_ReadPublic
General Description
NOTE Since the caller is not likely to know the public area of the object associated with objectHandle, it
would not be possible to include the Name associated with objectHandle in the cpHash computation.
Detailed Actions
1 #include "Tpm.h"
2 #include "ReadPublic_fp.h"
3 #if CC_ReadPublic // Conditional expansion of this file
4 TPM_RC
5 TPM2_ReadPublic(
6 ReadPublic_In *in, // IN: input parameter list
7 ReadPublic_Out *out // OUT: output parameter list
8 )
9 {
10 OBJECT *object = HandleToObject(in->objectHandle);
11
12 // Input Validation
13 // Can not read public area of a sequence object
14 if(ObjectIsSequence(object))
15 return TPM_RC_SEQUENCE;
16
17 // Command Output
18 out->outPublic.publicArea = object->publicArea;
19 out->name = object->name;
20 out->qualifiedName = object->qualifiedName;
21
22 return TPM_RC_SUCCESS;
23 }
24 #endif // CC_ReadPublic
12.5 TPM2_ActivateCredential
General Description
This command enables the association of a credential with an object in a way that ensures that the TPM
has validated the parameters of the credentialed object.
If both the public and private portions of activateHandle and keyHandle are not loaded, then the TPM
shall return TPM_RC_AUTH_UNAVAILABLE.
If keyHandle is not a Storage Key, then the TPM shall return TPM_RC_TYPE.
Authorization for activateHandle requires the ADMIN role.
The key associated with keyHandle is used to recover a seed from secret, which is the encrypted seed.
The Name of the object associated with activateHandle and the recovered seed are used in a KDF to
recover the symmetric key. The recovered seed (but not the Name) is used in a KDF to recover the
HMAC key.
The HMAC is used to validate that the credentialBlob is associated with activateHandle and that the data
in credentialBlob has not been modified. The linkage to the object associated with activateHandle is
achieved by including the Name in the HMAC calculation.
If the integrity checks succeed, credentialBlob is decrypted and returned as certInfo.
NOTE The output certInfo parameter is an application defined value. It is typically a symmetric key or seed
that is used to decrypt a certificate. See the TPM2_MakeCredential credential input parameter.
Detailed Actions
1 #include "Tpm.h"
2 #include "ActivateCredential_fp.h"
3 #if CC_ActivateCredential // Conditional expansion of this file
4 #include "Object_spt_fp.h"
5 TPM_RC
6 TPM2_ActivateCredential(
7 ActivateCredential_In *in, // IN: input parameter list
8 ActivateCredential_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result = TPM_RC_SUCCESS;
12 OBJECT *object; // decrypt key
13 OBJECT *activateObject; // key associated with credential
14 TPM2B_DATA data; // credential data
15
16 // Input Validation
17
18 // Get decrypt key pointer
19 object = HandleToObject(in->keyHandle);
20
21 // Get certificated object pointer
22 activateObject = HandleToObject(in->activateHandle);
23
24 // input decrypt key must be an asymmetric, restricted decryption key
25 if(!CryptIsAsymAlgorithm(object->publicArea.type)
26 || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
27 || !IS_ATTRIBUTE(object->publicArea.objectAttributes,
28 TPMA_OBJECT, restricted))
29 return TPM_RCS_TYPE + RC_ActivateCredential_keyHandle;
30
31 // Command output
32
33 // Decrypt input credential data via asymmetric decryption. A
34 // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this
35 // point
36 result = CryptSecretDecrypt(object, NULL, IDENTITY_STRING, &in->secret, &data);
37 if(result != TPM_RC_SUCCESS)
38 {
39 if(result == TPM_RC_KEY)
40 return TPM_RC_FAILURE;
41 return RcSafeAddToResult(result, RC_ActivateCredential_secret);
42 }
43
12.6 TPM2_MakeCredential
General Description
This command allows the TPM to perform the actions required of a Certificate Authority (CA) in creating a
TPM2B_ID_OBJECT containing an activation credential.
NOTE The input credential parameter is an application defined value. It is typically a symmetric key or
seed that is used to encrypt a certificate. See the TPM2_ActivateCredential certInfo output
parameter.
The TPM will produce a TPM2B_ID_OBJECT according to the methods in “Credential Protection” in TPM
2.0 Part 1.
The loaded public area referenced by handle is required to be the public area of a Storage key,
otherwise, the credential cannot be properly sealed.
This command does not use any TPM secrets nor does it require authorization. It is a convenience
function, using the TPM to perform cryptographic calculations that could be done externally.
Detailed Actions
1 #include "Tpm.h"
2 #include "MakeCredential_fp.h"
3 #if CC_MakeCredential // Conditional expansion of this file
4 #include "Object_spt_fp.h"
5 TPM_RC
6 TPM2_MakeCredential(
7 MakeCredential_In *in, // IN: input parameter list
8 MakeCredential_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result = TPM_RC_SUCCESS;
12
13 OBJECT *object;
14 TPM2B_DATA data;
15
16 // Input Validation
17
18 // Get object pointer
19 object = HandleToObject(in->handle);
20
21 // input key must be an asymmetric, restricted decryption key
22 // NOTE: Needs to be restricted to have a symmetric value.
23 if(!CryptIsAsymAlgorithm(object->publicArea.type)
24 || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
25 || !IS_ATTRIBUTE(object->publicArea.objectAttributes,
26 TPMA_OBJECT, restricted))
27 return TPM_RCS_TYPE + RC_MakeCredential_handle;
28
29 // The credential information may not be larger than the digest size used for
30 // the Name of the key associated with handle.
31 if(in->credential.t.size > CryptHashGetDigestSize(object->publicArea.nameAlg))
32 return TPM_RCS_SIZE + RC_MakeCredential_credential;
33
34 // Command Output
35
36 // Make encrypt key and its associated secret structure.
37 out->secret.t.size = sizeof(out->secret.t.secret);
38 result = CryptSecretEncrypt(object, IDENTITY_STRING, &data, &out->secret);
39 if(result != TPM_RC_SUCCESS)
40 return result;
41
42 // Prepare output credential data from secret
43 SecretToCredential(&in->credential, &in->objectName.b, &data.b,
44 object, &out->credentialBlob);
45
46 return TPM_RC_SUCCESS;
47 }
48 #endif // CC_MakeCredential
12.7 TPM2_Unseal
General Description
NOTE 1 A random, TPM-generated, Sealed Data Object may be created by the TPM with TPM2_Create() or
TPM2_CreatePrimary() using the template for a Sealed Data Object.
NOTE 2 TPM 1.2 hard coded PCR authorization. TPM 2.0 PCR authorization requires a policy.
unsealed data
TPM2B_SENSITIVE_DATA outData
Size of outData is limited to be no more than 128 octets.
Detailed Actions
1 #include "Tpm.h"
2 #include "Unseal_fp.h"
3 #if CC_Unseal // Conditional expansion of this file
4 TPM_RC
5 TPM2_Unseal(
6 Unseal_In *in,
7 Unseal_Out *out
8 )
9 {
10 OBJECT *object;
11 // Input Validation
12 // Get pointer to loaded object
13 object = HandleToObject(in->itemHandle);
14
15 // Input handle must be a data object
16 if(object->publicArea.type != TPM_ALG_KEYEDHASH)
17 return TPM_RCS_TYPE + RC_Unseal_itemHandle;
18 if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt)
19 || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign)
20 || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted))
21 return TPM_RCS_ATTRIBUTES + RC_Unseal_itemHandle;
22 // Command Output
23 // Copy data
24 out->outData = object->sensitive.sensitive.bits;
25 return TPM_RC_SUCCESS;
26 }
27 #endif // CC_Unseal
12.8 TPM2_ObjectChangeAuth
General Description
This command is used to change the authorization secret for a TPM-resident object.
If successful, a new private area for the TPM-resident object associated with objectHandle is returned,
which includes the new authorization value.
This command does not change the authorization of the TPM-resident object on which it operates.
Therefore, the old authValue (of the TPM-resident object) is used when generating the response HMAC
key if required.
NOTE 1 The returned outPrivate will need to be loaded before the new authorization will apply.
NOTE 2 The TPM-resident object may be persistent and changing the authorization value of the persistent
object could prevent other users from accessing the object. This is why this command does not
change the TPM-resident object.
EXAMPLE If a persistent key is being used as a Storage Root Key and the authorizat ion of the key is a well-
known value so that the key can be used generally, then changing the authorization value in the
persistent key would deny access to other users.
This command may not be used to change the authorization value for an NV Index or a Primary Object.
Detailed Actions
1 #include "Tpm.h"
2 #include "ObjectChangeAuth_fp.h"
3 #if CC_ObjectChangeAuth // Conditional expansion of this file
4 #include "Object_spt_fp.h"
5 TPM_RC
6 TPM2_ObjectChangeAuth(
7 ObjectChangeAuth_In *in, // IN: input parameter list
8 ObjectChangeAuth_Out *out // OUT: output parameter list
9 )
10 {
11 TPMT_SENSITIVE sensitive;
12
13 OBJECT *object = HandleToObject(in->objectHandle);
14 TPM2B_NAME QNCompare;
15
16 // Input Validation
17
18 // Can not change authorization on sequence object
19 if(ObjectIsSequence(object))
20 return TPM_RCS_TYPE + RC_ObjectChangeAuth_objectHandle;
21
22 // Make sure that the authorization value is consistent with the nameAlg
23 if(!AdjustAuthSize(&in->newAuth, object->publicArea.nameAlg))
24 return TPM_RCS_SIZE + RC_ObjectChangeAuth_newAuth;
25
26 // Parent handle should be the parent of object handle. In this
27 // implementation we verify this by checking the QN of object. Other
28 // implementation may choose different method to verify this attribute.
29 ComputeQualifiedName(in->parentHandle,
30 object->publicArea.nameAlg,
31 &object->name, &QNCompare);
32 if(!MemoryEqual2B(&object->qualifiedName.b, &QNCompare.b))
33 return TPM_RCS_TYPE + RC_ObjectChangeAuth_parentHandle;
34
35 // Command Output
36 // Prepare the sensitive area with the new authorization value
37 sensitive = object->sensitive;
38 sensitive.authValue = in->newAuth;
39
40 // Protect the sensitive area
41 SensitiveToPrivate(&sensitive, &object->name, HandleToObject(in->parentHandle),
42 object->publicArea.nameAlg,
43 &out->outPrivate);
44 return TPM_RC_SUCCESS;
45 }
46 #endif // CC_ObjectChangeAuth
12.9 TPM2_CreateLoaded
General Description
This command creates an object and loads it in the TPM. This command allows creation of any type of
object (Primary, Ordinary, or Derived) depending on the type of parentHandle. If parentHandle references
a Primary Seed, then a Primary Object is created; if parentHandle references a Storage Parent, then an
Ordinary Object is created; and if parentHandle references a Derivation Parent, then a Derived Object is
generated.
The input validation is the same as for TPM2_Create() and TPM2_CreatePrimary() with one exception:
when parentHandle references a Derivation Parent, then sensitiveDataOrigin in inPublic is required to be
CLEAR.
Note 1 In the general descriptions of TPM2_Create() and TPM2_CreatePrimary() the validations refer to a
TPMT_PUBLIC structure that is in inPublic. For TPM2_CreateLoaded(), inPublic is a
TPM2B_TEMPLATE that may contain a TPMT_PUBLIC that is used for object creation. For object
derivation, the unique field can contain a label and context that are used in the derivation process.
To allow both the TPMT_PUBLIC and the derivation variation, a TPM2B_TEMPLATE is used. When
referring to the checks in TPM2_Create() and TPM2_CreatePrimary(), TPM2B_TEMPLATE should
be assumed to contain a TPMT_PUBLIC.
If parentHandle references a Derivation Parent, then the TPM may return TPM_RC_TYPE if the key type
to be generated is an RSA key.
If parentHandle references a Derivation Parent or a Primary Seed, then outPrivate will be an Empty
Buffer.
NOTE 2 Returning outPrivate would imply that the returned primary or derived object can be loaded and it
cannot. It can only be re-derived.
A primary key cannot be loaded is because loading a key is a way to attack the protections of a key
(e.g. using DPA). A saved context for a primary object is protected. The TPM will go into failure
mode if the integrity of a saved context is good but the fingerprint doesn’t decrypt. It is not possible
to have these protections on loaded objects because this would be a simple way for an attacker to
put the TPM into failure mode Saved contexts are assumed to be under control of the driver but
loaded objects are not.
If all objects were derived from their parents then, load could not be used as an attack. However,
that would preclude importation of objects and key hierarchies.
NOTE 3 Unlike TPM2_Create() and TPM2_CreatePrimary(), this command does not return creation data. If
creation data is needed, then TPM2_Create() or TPM2_CreatePrimary() should be used.
TPM2B_SENSITIVE_CREATE inSensitive the sensitive data, see TPM 2.0 Part 1 Sensitive Values
TPM2B_TEMPLATE inPublic the public template
Detailed Actions
1 #include "Tpm.h"
2 #include "CreateLoaded_fp.h"
3 #if CC_CreateLoaded // Conditional expansion of this file
4 TPM_RC
5 TPM2_CreateLoaded(
6 CreateLoaded_In *in, // IN: input parameter list
7 CreateLoaded_Out *out // OUT: output parameter list
8 )
9 {
10 TPM_RC result = TPM_RC_SUCCESS;
11 OBJECT *parent = HandleToObject(in->parentHandle);
12 OBJECT *newObject;
13 BOOL derivation;
14 TPMT_PUBLIC *publicArea;
15 RAND_STATE randState;
16 RAND_STATE *rand = &randState;
17 TPMS_DERIVE labelContext;
18
19 // Input Validation
20
21 // How the public area is unmarshaled is determined by the parent, so
22 // see if parent is a derivation parent
23 derivation = (parent != NULL && parent->attributes.derivation);
24
25 // If the parent is an object, then make sure that it is either a parent or
26 // derivation parent
27 if(parent != NULL && !parent->attributes.isParent && !derivation)
28 return TPM_RCS_TYPE + RC_CreateLoaded_parentHandle;
29
30 // Get a spot in which to create the newObject
31 newObject = FindEmptyObjectSlot(&out->objectHandle);
32 if(newObject == NULL)
33 return TPM_RC_OBJECT_MEMORY;
34
35 // Do this to save typing
36 publicArea = &newObject->publicArea;
37
38 // Unmarshal the template into the object space. TPM2_Create() and
39 // TPM2_CreatePrimary() have the publicArea unmarshaled by CommandDispatcher.
40 // This command is different because of an unfortunate property of the
41 // unique field of an ECC key. It is a structure rather than a single TPM2B. If
42 // if had been a TPM2B, then the label and context could be within a TPM2B and
43 // unmarshaled like other public areas. Since it is not, this command needs its
44 // on template that is a TPM2B that is unmarshaled as a BYTE array with a
45 // its own unmarshal function.
46 result = UnmarshalToPublic(publicArea, &in->inPublic, derivation,
47 &labelContext);
48 if(result != TPM_RC_SUCCESS)
49 return result + RC_CreateLoaded_inPublic;
50
51 // Validate that the authorization size is appropriate
52 if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg))
53 return TPM_RCS_SIZE + RC_CreateLoaded_inSensitive;
54
55 // Command output
56 if(derivation)
57 {
58 TPMT_KEYEDHASH_SCHEME *scheme;
59 scheme = &parent->publicArea.parameters.keyedHashDetail.scheme;
60
61 // SP800-108 is the only KDF supported by this implementation and there is
62 // no default hash algorithm.
63 pAssert(scheme->details.xor.hashAlg != TPM_ALG_NULL
64 && scheme->details.xor.kdf == TPM_ALG_KDF1_SP800_108);
65 // Don't derive RSA keys
66 if(publicArea->type == ALG_RSA_VALUE)
67 return TPM_RCS_TYPE + RC_CreateLoaded_inPublic;
68 // sensitiveDataOrigin has to be CLEAR in a derived object. Since this
69 // is specific to a derived object, it is checked here.
70 if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT,
71 sensitiveDataOrigin))
72 return TPM_RCS_ATTRIBUTES;
73 // Check the reset of the attributes
74 result = PublicAttributesValidation(parent, publicArea);
75 if(result != TPM_RC_SUCCESS)
76 return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
77 // Process the template and sensitive areas to get the actual 'label' and
78 // 'context' values to be used for this derivation.
79 result = SetLabelAndContext(&labelContext, &in->inSensitive.sensitive.data);
80 if(result != TPM_RC_SUCCESS)
81 return result;
82 // Set up the KDF for object generation
83 DRBG_InstantiateSeededKdf((KDF_STATE *)rand,
84 scheme->details.xor.hashAlg,
85 scheme->details.xor.kdf,
86 &parent->sensitive.sensitive.bits.b,
87 &labelContext.label.b,
88 &labelContext.context.b,
89 MAX_DERIVATION_BITS);
90 // Clear the sensitive size so that the creation functions will not try
91 // to use this value.
92 in->inSensitive.sensitive.data.t.size = 0;
93 }
94 else
95 {
96 // Check attributes in input public area. CreateChecks() checks the things
97 // that are unique to creation and then validates the attributes and values
98 // that are common to create and load.
99 result = CreateChecks(parent, publicArea,
100 in->inSensitive.sensitive.data.t.size);
101 if(result != TPM_RC_SUCCESS)
102 return RcSafeAddToResult(result, RC_CreateLoaded_inPublic);
103 // Creating a primary object
104 if(parent == NULL)
105 {
106 TPM2B_NAME name;
107 newObject->attributes.primary = SET;
108 if(in->parentHandle == TPM_RH_ENDORSEMENT)
109 newObject->attributes.epsHierarchy = SET;
110 // If so, use the primary seed and the digest of the template
111 // to seed the DRBG
112 result = DRBG_InstantiateSeeded((DRBG_STATE *)rand,
113 &HierarchyGetPrimarySeed(in->parentHandle)->b,
114 PRIMARY_OBJECT_CREATION,
115 (TPM2B *)PublicMarshalAndComputeName(publicArea,
116 &name),
117 &in->inSensitive.sensitive.data.b);
118 if(result != TPM_RC_SUCCESS)
119 return result;
120 }
121 else
122 {
123 // This is an ordinary object so use the normal random number generator
124 rand = NULL;
125 }
126 }
127 // Internal data update
128 // Create the object
129 result = CryptCreateObject(newObject, &in->inSensitive.sensitive, rand);
130 if(result != TPM_RC_SUCCESS)
131 return result;
132 // if this is not a Primary key and not a derived key, then return the sensitive
133 // area
134 if(parent != NULL && !derivation)
135 // Prepare output private data from sensitive
136 SensitiveToPrivate(&newObject->sensitive, &newObject->name,
137 parent, newObject->publicArea.nameAlg,
138 &out->outPrivate);
139 else
140 out->outPrivate.t.size = 0;
141 // Set the remaining return values
142 out->outPublic.publicArea = newObject->publicArea;
143 out->name = newObject->name;
144 // Set the remaining attributes for a loaded object
145 ObjectSetLoadedAttributes(newObject, in->parentHandle);
146
147 return result;
148 }
149 #endif // CC_CreateLoaded
13 Duplication Commands
13.1 TPM2_Duplicate
General Description
This command duplicates a loaded object so that it may be used in a different hierarchy. The new parent
key for the duplicate may be on the same or different TPM or TPM_RH_NULL. Only the public area of
newParentHandle is required to be loaded.
NOTE 1 Since the new parent may only be extant on a different TPM, it is likely that the new parent’s
sensitive area could not be loaded in the TPM from which objectHandle is being duplicated.
If encryptedDuplication is SET in the object being duplicated, then the TPM shall return
TPM_RC_SYMMETRIC if symmetricAlg.algorithm is TPM_ALG_NULL or TPM_RC_HIERARCHY if
newParentHandle is TPM_RH_NULL.
The authorization for this command shall be with a policy session.
If fixedParent of objectHandle→attributes is SET, the TPM shall return TPM_RC_ATTRIBUTES. If
objectHandle→nameAlg is TPM_ALG_NULL, the TPM shall return TPM_RC_TYPE.
The policySession→commandCode parameter in the policy session is required to be TPM_CC_Duplicate
to indicate that authorization for duplication has been provided. This indicates that the policy that is being
used is a policy that is for duplication, and not a policy that would approve another use. That is, authority
to use an object does not grant authority to duplicate the object.
The policy is likely to include cpHash in order to restrict where duplication can occur. If
TPM2_PolicyCpHash() has been executed as part of the policy, the policySession→cpHash is compared
to the cpHash of the command.
If TPM2_PolicyDuplicationSelect() has been executed as part of the policy, the
policySession→nameHash is compared to
HpolicyAlg(objectHandle→Name || newParentHandle→Name) (2)
If the compared hashes are not the same, then the TPM shall return TPM_RC_POLICY_FAIL.
NOTE 2 It is allowed that policySesion→nameHash and policySession→cpHash share the same memory
space.
The TPM shall follow the process of encryption defined in the “Duplication” subclause of “Protected
Storage Hierarchy” in TPM 2.0 Part 1.
Detailed Actions
1 #include "Tpm.h"
2 #include "Duplicate_fp.h"
3 #if CC_Duplicate // Conditional expansion of this file
4 #include "Object_spt_fp.h"
5 TPM_RC
6 TPM2_Duplicate(
7 Duplicate_In *in, // IN: input parameter list
8 Duplicate_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result = TPM_RC_SUCCESS;
12 TPMT_SENSITIVE sensitive;
13
14 UINT16 innerKeySize = 0; // encrypt key size for inner wrap
15
16 OBJECT *object;
17 OBJECT *newParent;
18 TPM2B_DATA data;
19
20 // Input Validation
21
22 // Get duplicate object pointer
23 object = HandleToObject(in->objectHandle);
24 // Get new parent
25 newParent = HandleToObject(in->newParentHandle);
26
27 // duplicate key must have fixParent bit CLEAR.
28 if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, fixedParent))
29 return TPM_RCS_ATTRIBUTES + RC_Duplicate_objectHandle;
30
31 // Do not duplicate object with NULL nameAlg
32 if(object->publicArea.nameAlg == TPM_ALG_NULL)
33 return TPM_RCS_TYPE + RC_Duplicate_objectHandle;
34
35 // new parent key must be a storage object or TPM_RH_NULL
36 if(in->newParentHandle != TPM_RH_NULL
37 && !ObjectIsStorage(in->newParentHandle))
38 return TPM_RCS_TYPE + RC_Duplicate_newParentHandle;
39
40 // If the duplicated object has encryptedDuplication SET, then there must be
41 // an inner wrapper and the new parent may not be TPM_RH_NULL
42 if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT,
43 encryptedDuplication))
44 {
45 if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
46 return TPM_RCS_SYMMETRIC + RC_Duplicate_symmetricAlg;
47 if(in->newParentHandle == TPM_RH_NULL)
48 return TPM_RCS_HIERARCHY + RC_Duplicate_newParentHandle;
49 }
50
51 if(in->symmetricAlg.algorithm == TPM_ALG_NULL)
52 {
53 // if algorithm is TPM_ALG_NULL, input key size must be 0
54 if(in->encryptionKeyIn.t.size != 0)
55 return TPM_RCS_SIZE + RC_Duplicate_encryptionKeyIn;
56 }
57 else
58 {
59 // Get inner wrap key size
60 innerKeySize = in->symmetricAlg.keyBits.sym;
61
62 // If provided the input symmetric key must match the size of the algorithm
63 if(in->encryptionKeyIn.t.size != 0
64 && in->encryptionKeyIn.t.size != (innerKeySize + 7) / 8)
65 return TPM_RCS_SIZE + RC_Duplicate_encryptionKeyIn;
66 }
67
68 // Command Output
69
70 if(in->newParentHandle != TPM_RH_NULL)
71 {
72 // Make encrypt key and its associated secret structure. A TPM_RC_KEY
73 // error may be returned at this point
74 out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret);
75 result = CryptSecretEncrypt(newParent, DUPLICATE_STRING, &data,
76 &out->outSymSeed);
77 if(result != TPM_RC_SUCCESS)
78 return result;
79 }
80 else
81 {
82 // Do not apply outer wrapper
83 data.t.size = 0;
84 out->outSymSeed.t.size = 0;
85 }
86
87 // Copy sensitive area
88 sensitive = object->sensitive;
89
90 // Prepare output private data from sensitive.
91 // Note: If there is no encryption key, one will be provided by
92 // SensitiveToDuplicate(). This is why the assignment of encryptionKeyIn to
93 // encryptionKeyOut will work properly and is not conditional.
94 SensitiveToDuplicate(&sensitive, &object->name.b, newParent,
95 object->publicArea.nameAlg, &data.b,
96 &in->symmetricAlg, &in->encryptionKeyIn,
97 &out->duplicate);
98
99 out->encryptionKeyOut = in->encryptionKeyIn;
100
101 return TPM_RC_SUCCESS;
102 }
103 #endif // CC_Duplicate
13.2 TPM2_Rewrap
General Description
This command allows the TPM to serve in the role as a Duplication Authority. If proper authorization for
use of the oldParent is provided, then an HMAC key and a symmetric key are recovered from inSymSeed
and used to integrity check and decrypt inDuplicate. A new protection seed value is generated according
to the methods appropriate for newParent and the blob is re-encrypted and a new integrity value is
computed. The re-encrypted blob is returned in outDuplicate and the symmetric key returned in
outSymKey.
In the rewrap process, L is “DUPLICATE” (see TPM 2.0 Part 1, Terms and Definitions).
If inSymSeed has a zero length, then oldParent is required to be TPM_RH_NULL and no decryption of
inDuplicate takes place.
If newParent is TPM_RH_NULL, then no encryption is performed on outDuplicate. outSymSeed will have
a zero length. See TPM 2.0 Part 2 encryptedDuplication.
parent of object
TPMI_DH_OBJECT+ @oldParent Auth Index: 1
Auth Role: User
new parent of the object
TPMI_DH_OBJECT+ newParent
Auth Index: None
Detailed Actions
1 #include "Tpm.h"
2 #include "Rewrap_fp.h"
3 #if CC_Rewrap // Conditional expansion of this file
4 #include "Object_spt_fp.h"
5 TPM_RC
6 TPM2_Rewrap(
7 Rewrap_In *in, // IN: input parameter list
8 Rewrap_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result = TPM_RC_SUCCESS;
12 TPM2B_DATA data; // symmetric key
13 UINT16 hashSize = 0;
14 TPM2B_PRIVATE privateBlob; // A temporary private blob
15 // to transit between old
16 // and new wrappers
17 // Input Validation
18 if((in->inSymSeed.t.size == 0 && in->oldParent != TPM_RH_NULL)
19 || (in->inSymSeed.t.size != 0 && in->oldParent == TPM_RH_NULL))
20 return TPM_RCS_HANDLE + RC_Rewrap_oldParent;
21 if(in->oldParent != TPM_RH_NULL)
22 {
23 OBJECT *oldParent = HandleToObject(in->oldParent);
24
25 // old parent key must be a storage object
26 if(!ObjectIsStorage(in->oldParent))
27 return TPM_RCS_TYPE + RC_Rewrap_oldParent;
28 // Decrypt input secret data via asymmetric decryption. A
29 // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this
30 // point
31 result = CryptSecretDecrypt(oldParent, NULL, DUPLICATE_STRING,
32 &in->inSymSeed, &data);
33 if(result != TPM_RC_SUCCESS)
34 return TPM_RCS_VALUE + RC_Rewrap_inSymSeed;
35 // Unwrap Outer
36 result = UnwrapOuter(oldParent, &in->name.b,
37 oldParent->publicArea.nameAlg, &data.b,
38 FALSE,
39 in->inDuplicate.t.size, in->inDuplicate.t.buffer);
40 if(result != TPM_RC_SUCCESS)
41 return RcSafeAddToResult(result, RC_Rewrap_inDuplicate);
13.3 TPM2_Import
General Description
This command allows an object to be encrypted using the symmetric encryption values of a Storage Key.
After encryption, the object may be loaded and used in the new hierarchy. The imported object (duplicate)
may be singly encrypted, multiply encrypted, or unencrypted.
If fixedTPM or fixedParent is SET in objectPublic, the TPM shall return TPM_RC_ATTRIBUTES.
If encryptedDuplication is SET in the object referenced by parentHandle and encryptedDuplication is
CLEAR in objectPublic, the TPM may return TPM_RC_ATTRIBUTES.
If encryptedDuplication is SET in objectPublic, then inSymSeed and encryptionKey shall not be Empty
buffers (TPM_RC_ATTRIBUTES). Recovery of the sensitive data of the object occurs in the TPM in a
multi--step process in the following order:
If inSymSeed has a non-zero size:
1) The asymmetric parameters and private key of parentHandle are used to recover the seed used
in the creation of the HMAC key and encryption keys used to protect the duplication blob.
2) The integrity value in duplicate.buffer.integrityOuter is used to verify the integrity of the data blob,
which is the remainder of duplicate.buffer (TPM_RC_INTEGRITY).
NOTE 2 The data blob will contain a TPMT_SENSITIVE and may contain a TPM2B_DIGEST for the
innerIntegrity.
NOTE 3 Checking the integrity before the data is used prevents attacks on the sensitive area by
fuzzing the data and looking at the differences in the response codes .
NOTE 4 It is not necessary to validate that the sensitive area data is cryptographically bound to the public
area other than that the Name of the public area is included in the HMAC. However, if the binding is
not validated by this command, the binding must be ch ecked each time the object is loaded. For an
object that is imported under a parent with fixedTPM SET, binding need only be checked at import. If
the parent has fixedTPM CLEAR, then the binding needs to be checked each time the object is
loaded, or before the TPM performs an operation for which the binding affects the outcome of the
operation (for example, TPM2_PolicySigned() or TPM2_Certify()).
Similarly, if the new parent's fixedTPM is set, the encryptedDuplication state need only be checked
at import.
If the new parent is not fixedTPM, then that object will be loadable on any TPM (including SW
versions) on which the new parent exists. This means that, each time an object is loaded under a
parent that is not fixedTPM, it is necessary to validate all of the properties of that object. If the
parent is fixedTPM, then the new private blob is integrity protected by the TPM that “owns” the
parent. So, it is sufficient to validate the object’s properties (attribute and public -private binding) on
import and not again.
If a weak symmetric key is being imported, the TPM shall return TPM_RC_KEY.
After integrity checks and decryption, the TPM will create a new symmetrically encrypted private area
using the encryption key of the parent.
NOTE 5 The symmetric re-encryption is the normal integrity generation and symmetric encryption applied to
a child object.
NOTE 6 Revision 01.16 of this specification required the ECC private key in duplicate to be padded.
Detailed Actions
1 #include "Tpm.h"
2 #include "Import_fp.h"
3 #if CC_Import // Conditional expansion of this file
4 #include "Object_spt_fp.h"
5 TPM_RC
6 TPM2_Import(
7 Import_In *in, // IN: input parameter list
8 Import_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result = TPM_RC_SUCCESS;
12 OBJECT *parentObject;
13 TPM2B_DATA data; // symmetric key
14 TPMT_SENSITIVE sensitive;
15 TPM2B_NAME name;
16 TPMA_OBJECT attributes;
17 UINT16 innerKeySize = 0; // encrypt key size for inner
18 // wrapper
19
20 // Input Validation
21 // to save typing
22 attributes = in->objectPublic.publicArea.objectAttributes;
23 // FixedTPM and fixedParent must be CLEAR
24 if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)
25 || IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent))
26 return TPM_RCS_ATTRIBUTES + RC_Import_objectPublic;
27
28 // Get parent pointer
29 parentObject = HandleToObject(in->parentHandle);
30
31 if(!ObjectIsParent(parentObject))
32 return TPM_RCS_TYPE + RC_Import_parentHandle;
33
34 if(in->symmetricAlg.algorithm != TPM_ALG_NULL)
35 {
36 // Get inner wrap key size
37 innerKeySize = in->symmetricAlg.keyBits.sym;
38 // Input symmetric key must match the size of algorithm.
39 if(in->encryptionKey.t.size != (innerKeySize + 7) / 8)
40 return TPM_RCS_SIZE + RC_Import_encryptionKey;
41 }
42 else
43 {
44 // If input symmetric algorithm is NULL, input symmetric key size must
45 // be 0 as well
46 if(in->encryptionKey.t.size != 0)
47 return TPM_RCS_SIZE + RC_Import_encryptionKey;
48 // If encryptedDuplication is SET, then the object must have an inner
49 // wrapper
50 if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication))
51 return TPM_RCS_ATTRIBUTES + RC_Import_encryptionKey;
52 }
53 // See if there is an outer wrapper
54 if(in->inSymSeed.t.size != 0)
55 {
56 // in->inParentHandle is a parent, but in order to decrypt an outer wrapper,
57 // it must be able to do key exchange and a symmetric key can't do that.
58 if(parentObject->publicArea.type == TPM_ALG_SYMCIPHER)
59 return TPM_RCS_TYPE + RC_Import_parentHandle;
60
61 // Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES,
62 // TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT,
63 // TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point
64 result = CryptSecretDecrypt(parentObject, NULL, DUPLICATE_STRING,
65 &in->inSymSeed, &data);
66 pAssert(result != TPM_RC_BINDING);
67 if(result != TPM_RC_SUCCESS)
68 return RcSafeAddToResult(result, RC_Import_inSymSeed);
69 }
70 else
71 {
14 Asymmetric Primitives
14.1 Introduction
The commands in this clause provide low-level primitives for access to the asymmetric algorithms
implemented in the TPM. Many of these commands are only allowed if the asymmetric key is an
unrestricted key.
14.2 TPM2_RSA_Encrypt
General Description
This command performs RSA encryption using the indicated padding scheme according to IETF RFC
8017. If the scheme of keyHandle is TPM_ALG_NULL, then the caller may use inScheme to specify the
padding scheme. If scheme of keyHandle is not TPM_ALG_NULL, then inScheme shall either be
TPM_ALG_NULL or be the same as scheme (TPM_RC_SCHEME).
The key referenced by keyHandle is required to be an RSA key (TPM_RC_KEY).
The three types of allowed padding are:
1) TPM_ALG_OAEP – Data is OAEP padded as described in 7.1 of IETF RFC 8017 (PKCS#1).
The only supported mask generation is MGF1.
2) TPM_ALG_RSAES – Data is padded as described in 7.2 of IETF R FC 8017 (PKCS#1).
3) TPM_ALG_NULL – Data is not padded by the TPM and the TPM will treat message as an
unsigned integer and perform a modular exponentiation of message using the public
exponent of the key referenced by keyHandle. This scheme is only used if both the scheme
in the key referenced by keyHandle is TPM_ALG_NULL, and the inScheme parameter of the
command is TPM_ALG_NULL. The input value cannot be larger than the public modulus of
the key referenced by keyHandle.
TPM_ALG_NULL none
TPM_ALG_NULL TPM_ALG_RSAES RSAES
TPM_ALG_OAEP OAEP
TPM_ALG_NULL RSAES
TPM_ALG_RSAES TPM_ALG_RSAES RSAES
TPM_ALG_OAEP error (TPM_RC_SCHEME)
TPM_ALG_NULL OAEP
TPM_ALG_OAEP TPM_ALG_RSAES error (TPM_RC_SCHEME)
TPM_ALG_OAEP OAEP
After padding, the data is RSAEP encrypted according to 5.1.1 of IETF RFC 8017 (PKCS#1).
If inScheme is used, and the scheme requires a hash algorithm it may not be TPM_ALG_NULL.
NOTE 1 Because only the public portion of the key needs to be loaded for this command, the caller can
manipulate the attributes of the key in any way desired. As a result, the T PM shall not check the
consistency of the attributes. The only property checking is that the key is an RSA key and that the
padding scheme is supported.
The message parameter is limited in size by the padding scheme according to the following table:
The label parameter is optional. If provided (label.size != 0) then the TPM shall return TPM_RC_VALUE if
the last octet in label is not zero. The terminating octet of zero is included in the label used in the padding
scheme.
NOTE 2 If the scheme does not use a label, the TPM will still verify that label is prop erly formatted if label is
present.
NOTE 3 Specifications before version 1.54 stated that label is truncated after the first zero octet.
Applications should not include embedded zero bytes for compatibility.
NOTE 4 Only the public area of keyHandle is required to be loaded. A public key may be loaded with any
desired scheme. If the scheme is to be changed, a different public area must be loaded.
message to be encrypted
NOTE 1 The data type was chosen because it limits
TPM2B_PUBLIC_KEY_RSA message the overall size of the input to no greater than
the size of the largest RSA public key. This
may be larger than allowed for keyHandle.
Detailed Actions
1 #include "Tpm.h"
2 #include "RSA_Encrypt_fp.h"
3 #if CC_RSA_Encrypt // Conditional expansion of this file
4 TPM_RC
5 TPM2_RSA_Encrypt(
6 RSA_Encrypt_In *in, // IN: input parameter list
7 RSA_Encrypt_Out *out // OUT: output parameter list
8 )
9 {
10 TPM_RC result;
11 OBJECT *rsaKey;
12 TPMT_RSA_DECRYPT *scheme;
13 // Input Validation
14 rsaKey = HandleToObject(in->keyHandle);
15
16 // selected key must be an RSA key
17 if(rsaKey->publicArea.type != TPM_ALG_RSA)
18 return TPM_RCS_KEY + RC_RSA_Encrypt_keyHandle;
19 // selected key must have the decryption attribute
20 if(!IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
21 return TPM_RCS_ATTRIBUTES + RC_RSA_Encrypt_keyHandle;
22
23 // Is there a label?
24 if(!IsLabelProperlyFormatted(&in->label.b))
25 return TPM_RCS_VALUE + RC_RSA_Encrypt_label;
26 // Command Output
27 // Select a scheme for encryption
28 scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme);
29 if(scheme == NULL)
30 return TPM_RCS_SCHEME + RC_RSA_Encrypt_inScheme;
31
32 // Encryption. TPM_RC_VALUE, or TPM_RC_SCHEME errors my be returned buy
33 // CryptEncyptRSA.
34 out->outData.t.size = sizeof(out->outData.t.buffer);
35
36 result = CryptRsaEncrypt(&out->outData, &in->message.b, rsaKey, scheme,
37 &in->label.b, NULL);
38 return result;
39 }
40 #endif // CC_RSA_Encrypt
14.3 TPM2_RSA_Decrypt
General Description
This command performs RSA decryption using the indicated padding scheme according to IETF RFC
8017 ((PKCS#1).
The scheme selection for this command is the same as for TPM2_RSA_Encrypt() and is shown in Table
43.
The key referenced by keyHandle shall be an RSA key (TPM_RC_KEY) with restricted CLEAR and
decrypt SET (TPM_RC_ATTRIBUTES).
This command uses the private key of keyHandle for this operation and authorization is required.
The TPM will perform a modular exponentiation of ciphertext using the private exponent associated with
keyHandle (this is described in IETF RFC 8017 (PKCS#1), clause 5.1.2). It will then validate the padding
according to the selected scheme. If the padding checks fail, TPM_RC_VALUE is returned. Otherwise,
the data is returned with the padding removed. If no padding is used, the returned value is an unsigned
integer value that is the result of the modular exponentiation of cipherText using the private exponent of
keyHandle. The returned value may include leading octets zeros so that it is the same size as the public
modulus. For the other padding schemes, the returned value will be smaller than the public modulus but
will contain all the data remaining after padding is removed and this may include leading zeros if the
original encrypted value contained leading zeros.
If a label is used in the padding process of the scheme during encryption, the label parameter is required
to be present in the decryption process and label is required to be the same in both cases. If label is not
the same, the decrypt operation is very likely to fail ((TPM_RC_VALUE). If label is present (label.size !=
0), it shall be a byte stream whose last byte is zero or the TPM will return TPM_RC_VALUE.
The message parameter in the response may be encrypted using parameter encryption.
If inScheme is used, and the scheme requires a hash algorithm it may not be TPM_ALG_NULL.
If the scheme does not require a label, the value in label is not used but the size of the label field is
checked for consistency with the indicated data type (TPM2B_DATA). That is, the field may not be larger
than allowed for a TPM2B_DATA.
Detailed Actions
1 #include "Tpm.h"
2 #include "RSA_Decrypt_fp.h"
3 #if CC_RSA_Decrypt // Conditional expansion of this file
4 TPM_RC
5 TPM2_RSA_Decrypt(
6 RSA_Decrypt_In *in, // IN: input parameter list
7 RSA_Decrypt_Out *out // OUT: output parameter list
8 )
9 {
10 TPM_RC result;
11 OBJECT *rsaKey;
12 TPMT_RSA_DECRYPT *scheme;
13
14 // Input Validation
15
16 rsaKey = HandleToObject(in->keyHandle);
17
18 // The selected key must be an RSA key
19 if(rsaKey->publicArea.type != TPM_ALG_RSA)
20 return TPM_RCS_KEY + RC_RSA_Decrypt_keyHandle;
21
22 // The selected key must be an unrestricted decryption key
23 if(IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, restricted)
24 || !IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
25 return TPM_RCS_ATTRIBUTES + RC_RSA_Decrypt_keyHandle;
26
27 // NOTE: Proper operation of this command requires that the sensitive area
28 // of the key is loaded. This is assured because authorization is required
29 // to use the sensitive area of the key. In order to check the authorization,
30 // the sensitive area has to be loaded, even if authorization is with policy.
31
32 // If label is present, make sure that it is a NULL-terminated string
33 if(!IsLabelProperlyFormatted(&in->label.b))
34 return TPM_RCS_VALUE + RC_RSA_Decrypt_label;
35 // Command Output
36 // Select a scheme for decrypt.
37 scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme);
38 if(scheme == NULL)
39 return TPM_RCS_SCHEME + RC_RSA_Decrypt_inScheme;
40
41 // Decryption. TPM_RC_VALUE, TPM_RC_SIZE, and TPM_RC_KEY error may be
42 // returned by CryptRsaDecrypt.
14.4 TPM2_ECDH_KeyGen
General Description
This command uses the TPM to generate an ephemeral key pair ( de, Qe where Qe ≔ [de]G). It uses the
private ephemeral key and a loaded public key (QS) to compute the shared secret value (P ≔ [hde]QS).
keyHandle shall refer to a loaded, ECC key (TPM_RC_KEY). The sensitive portion of this key need not
be loaded.
The curve parameters of the loaded ECC key are used to generate the ephemeral key.
NOTE This function is the equivalent of encrypting data to another obje ct’s public key. The seed value is
used in a KDF to generate a symmetric key and that key is used to encrypt the data. Once the data
is encrypted and the symmetric key discarded, only the object with the private portion of the
keyHandle will be able to decrypt it.
Detailed Actions
1 #include "Tpm.h"
2 #include "ECDH_KeyGen_fp.h"
3 #if CC_ECDH_KeyGen // Conditional expansion of this file
4 TPM_RC
5 TPM2_ECDH_KeyGen(
6 ECDH_KeyGen_In *in, // IN: input parameter list
7 ECDH_KeyGen_Out *out // OUT: output parameter list
8 )
9 {
10 OBJECT *eccKey;
11 TPM2B_ECC_PARAMETER sensitive;
12 TPM_RC result;
13
14 // Input Validation
15
16 eccKey = HandleToObject(in->keyHandle);
17
18 // Referenced key must be an ECC key
19 if(eccKey->publicArea.type != TPM_ALG_ECC)
20 return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle;
21
22 // Command Output
23 do
24 {
25 TPMT_PUBLIC *keyPublic = &eccKey->publicArea;
26 // Create ephemeral ECC key
27 result = CryptEccNewKeyPair(&out->pubPoint.point, &sensitive,
28 keyPublic->parameters.eccDetail.curveID);
29 if(result == TPM_RC_SUCCESS)
30 {
31 // Compute Z
32 result = CryptEccPointMultiply(&out->zPoint.point,
33 keyPublic->parameters.eccDetail.curveID,
34 &keyPublic->unique.ecc,
35 &sensitive,
36 NULL, NULL);
37 // The point in the key is not on the curve. Indicate
38 // that the key is bad.
39 if(result == TPM_RC_ECC_POINT)
40 return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle;
41 // The other possible error from CryptEccPointMultiply is
42 // TPM_RC_NO_RESULT indicating that the multiplication resulted in
43 // the point at infinity, so get a new random key and start over
44 // BTW, this never happens.
45 }
46 } while(result == TPM_RC_NO_RESULT);
47 return result;
48 }
49 #endif // CC_ECDH_KeyGen
14.5 TPM2_ECDH_ZGen
General Description
This command uses the TPM to recover the Z value from a public point (QB) and a private key (ds). It will
perform the multiplication of the provided inPoint (QB) with the private key (ds) and return the coordinates
of the resultant point (Z = (xZ , yZ) ≔ [hds]QB; where h is the cofactor of the curve).
keyHandle shall refer to a loaded, ECC key (TPM_RC_KEY) with the restricted attribute CLEAR and the
decrypt attribute SET (TPM_RC_ATTRIBUTES).
Detailed Actions
1 #include "Tpm.h"
2 #include "ECDH_ZGen_fp.h"
3 #if CC_ECDH_ZGen // Conditional expansion of this file
4 TPM_RC
5 TPM2_ECDH_ZGen(
6 ECDH_ZGen_In *in, // IN: input parameter list
7 ECDH_ZGen_Out *out // OUT: output parameter list
8 )
9 {
10 TPM_RC result;
11 OBJECT *eccKey;
12
13 // Input Validation
14 eccKey = HandleToObject(in->keyHandle);
15
16 // Selected key must be a non-restricted, decrypt ECC key
17 if(eccKey->publicArea.type != TPM_ALG_ECC)
18 return TPM_RCS_KEY + RC_ECDH_ZGen_keyHandle;
19 // Selected key needs to be unrestricted with the 'decrypt' attribute
20 if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted)
21 || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
22 return TPM_RCS_ATTRIBUTES + RC_ECDH_ZGen_keyHandle;
23 // Make sure the scheme allows this use
24 if(eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_ECDH
25 && eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_NULL)
26 return TPM_RCS_SCHEME + RC_ECDH_ZGen_keyHandle;
27 // Command Output
28 // Compute Z. TPM_RC_ECC_POINT or TPM_RC_NO_RESULT may be returned here.
29 result = CryptEccPointMultiply(&out->outPoint.point,
30 eccKey->publicArea.parameters.eccDetail.curveID,
31 &in->inPoint.point,
32 &eccKey->sensitive.sensitive.ecc,
33 NULL, NULL);
34 if(result != TPM_RC_SUCCESS)
35 return RcSafeAddToResult(result, RC_ECDH_ZGen_inPoint);
36 return result;
37 }
38 #endif // CC_ECDH_ZGen
14.6 TPM2_ECC_Parameters
General Description
This command returns the parameters of an ECC curve identified by its TCG-assigned curveID.
The value returned is the same as that from the TCG Algorithm Registry, but may not be the same size.
EXAMPLE The value 01 may be returned as 00000001.
Detailed Actions
1 #include "Tpm.h"
2 #include "ECC_Parameters_fp.h"
3 #if CC_ECC_Parameters // Conditional expansion of this file
4 TPM_RC
5 TPM2_ECC_Parameters(
6 ECC_Parameters_In *in, // IN: input parameter list
7 ECC_Parameters_Out *out // OUT: output parameter list
8 )
9 {
10 // Command Output
11
12 // Get ECC curve parameters
13 if(CryptEccGetParameters(in->curveID, &out->parameters))
14 return TPM_RC_SUCCESS;
15 else
16 return TPM_RCS_VALUE + RC_ECC_Parameters_curveID;
17 }
18 #endif // CC_ECC_Parameters
14.7 TPM2_ZGen_2Phase
General Description
This command supports two-phase key exchange protocols. The command is used in combination with
TPM2_EC_Ephemeral(). TPM2_EC_Ephemeral() generates an ephemeral key and returns the public
point of that ephemeral key along with a numeric value that allows the TPM to regenerate the associated
private key.
The input parameters for this command are a static public key (inQsU), an ephemeral key (inQeU) from
party B, and the commitCounter returned by TPM2_EC_Ephemeral(). The TPM uses the counter value to
regenerate the ephemeral private key (de,V) and the associated public key (Qe,V). keyA provides the static
ephemeral elements ds,V and Qs,V. This provides the two pairs of ephemeral and static keys that are
required for the schemes supported by this command.
The TPM will compute Z or Zs and Ze according to the selected scheme. If the scheme is not a two-phase
key exchange scheme or if the scheme is not supported, the TPM will return TPM_RC_SCHEME.
It is an error if inQsB or inQeB are not on the curve of keyA (TPM_RC_ECC_POINT).
The two-phase key schemes that were assigned an algorithm ID as of the time of the publication of this
specification are TPM_ALG_ECDH, TPM_ALG_ECMQV, and TPM_ALG_SM2.
If this command is supported, then support for TPM_ALG_ECDH is required. Support for
TPM_ALG_ECMQV or TPM_ALG_SM2 is optional.
NOTE 1 If SM2 is supported and this command is supported, then the implementation is required to support
the key exchange protocol of SM2, part 3.
For TPM_ALG_ECDH outZ1 will be Zs and outZ2 will Ze as defined in 6.1.1.2 of SP800-56A.
NOTE 2 An unrestricted decryption key using ECDH may be used in either TPM2_ECDH_ZGen() or
TPM2_ZGen_2Phase as the computation done with the private part of keyA is the same in both
cases.
For TPM_ALG_ECMQV or TPM_ALG_SM2 outZ1 will be Z and outZ2 will be an Empty Point.
NOTE 3 An Empty Point has two Empty Buffers as coordinates meaning the minimum size value for outZ2
will be four.
If the input scheme is TPM_ALG_ECDH, then outZ1 will be Zs and outZ2 will be Ze. For schemes like
MQV (including SM2), outZ1 will contain the computed value and outZ2 will be an Empty Point.
NOTE 4 The Z values returned by the TPM are a full point and not just an x -coordinate.
If a computation of either Z produces the point at infinity, then the corresponding Z value will be an Empty
Point.
TPM2B_ECC_POINT inQsB other party’s static public key (Qs,B = (Xs,B, Ys,B))
TPM2B_ECC_POINT inQeB other party's ephemeral public key (Qe,B = (Xe,B, Ye,B))
TPMI_ECC_KEY_EXCHANGE inScheme the key exchange scheme
UINT16 counter value returned by TPM2_EC_Ephemeral()
Detailed Actions
1 #include "Tpm.h"
2 #include "ZGen_2Phase_fp.h"
3 #if CC_ZGen_2Phase // Conditional expansion of this file
This command uses the TPM to recover one or two Z values in a two phase key exchange protocol
4 TPM_RC
5 TPM2_ZGen_2Phase(
6 ZGen_2Phase_In *in, // IN: input parameter list
7 ZGen_2Phase_Out *out // OUT: output parameter list
8 )
9 {
10 TPM_RC result;
11 OBJECT *eccKey;
12 TPM2B_ECC_PARAMETER r;
13 TPM_ALG_ID scheme;
14
15 // Input Validation
16
17 eccKey = HandleToObject(in->keyA);
18
19 // keyA must be an ECC key
20 if(eccKey->publicArea.type != TPM_ALG_ECC)
21 return TPM_RCS_KEY + RC_ZGen_2Phase_keyA;
22
23 // keyA must not be restricted and must be a decrypt key
24 if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted)
25 || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt))
26 return TPM_RCS_ATTRIBUTES + RC_ZGen_2Phase_keyA;
27
28 // if the scheme of keyA is TPM_ALG_NULL, then use the input scheme; otherwise
29 // the input scheme must be the same as the scheme of keyA
30 scheme = eccKey->publicArea.parameters.asymDetail.scheme.scheme;
31 if(scheme != TPM_ALG_NULL)
32 {
33 if(scheme != in->inScheme)
34 return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme;
35 }
36 else
37 scheme = in->inScheme;
38 if(scheme == TPM_ALG_NULL)
39 return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme;
40
41 // Input points must be on the curve of keyA
42 if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
43 &in->inQsB.point))
44 return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQsB;
45
46 if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID,
47 &in->inQeB.point))
48 return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQeB;
49
50 if(!CryptGenerateR(&r, &in->counter,
51 eccKey->publicArea.parameters.eccDetail.curveID,
52 NULL))
53 return TPM_RCS_VALUE + RC_ZGen_2Phase_counter;
54
55 // Command Output
56
57 result =
58 CryptEcc2PhaseKeyExchange(&out->outZ1.point,
59 &out->outZ2.point,
60 eccKey->publicArea.parameters.eccDetail.curveID,
61 scheme,
62 &eccKey->sensitive.sensitive.ecc,
63 &r,
64 &in->inQsB.point,
65 &in->inQeB.point);
66 if(result == TPM_RC_SCHEME)
67 return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme;
68
69 if(result == TPM_RC_SUCCESS)
70 CryptEndCommit(in->counter);
71
72 return result;
73 }
74 #endif // CC_ZGen_2Phase
15 Symmetric Primitives
15.1 Introduction
The commands in this clause provide low-level primitives for access to the symmetric algorithms
implemented in the TPM that operate on blocks of data. These include symmetric encryption and
decryption as well as hash and HMAC. All of the commands in this group are stateless. That is, they have
no persistent state that is retained in the TPM when the command is complete.
For hashing, HMAC, and Events that require large blocks of data with retained state, the sequence
commands are provided (see clause 1).
Some of the symmetric encryption/decryption modes use an IV. When an IV is used, it may be an
initiation value or a chained value from a previous stage. The chaining for each mode is:
15.2 TPM2_EncryptDecrypt
General Description
NOTE 1 This command is deprecated, and TPM2_EncryptDecrypt2() is preferred. This should be reflected in
platform-specific specifications.
This command performs symmetric encryption or decryption using the symmetric key referenced by
keyHandle and the selected mode.
keyHandle shall reference a symmetric cipher object (TPM_RC_KEY) with the restricted attribute CLEAR
(TPM_RC_ATTRIBUTES).
If the decrypt parameter of the command is TRUE, then the decrypt attribute of the key is required to be
SET (TPM_RC_ATTRIBUTES). If the decrypt parameter of the command is FALSE, then the sign
attribute of the key is required to be SET (TPM_RC_ATTRIBUTES).
If the mode of the key is not TPM_ALG_NULL, then that is the only mode that can be used with the key
and the caller is required to set mode either to TPM_ALG_NULL or to the same mode as the key
(TPM_RC_MODE). If the mode of the key is TPM_ALG_NULL, then the caller may set mode to any valid
symmetric encryption/decryption mode but may not select TPM_ALG_NULL (TPM_RC_MODE).
If the TPM allows this command to be canceled before completion, then the TPM may produce
incremental results and return TPM_RC_SUCCESS rather than TPM_RC_CANCELED. In such case,
outData may be less than inData.
NOTE 3 If all the data is encrypted/decrypted, the size of outData will be the same as inData.
Detailed Actions
1 #include "Tpm.h"
2 #include "EncryptDecrypt_fp.h"
3 #if CC_EncryptDecrypt2
4 #include "EncryptDecrypt_spt_fp.h"
5 #endif
6 #if CC_EncryptDecrypt // Conditional expansion of this file
7 TPM_RC
8 TPM2_EncryptDecrypt(
9 EncryptDecrypt_In *in, // IN: input parameter list
10 EncryptDecrypt_Out *out // OUT: output parameter list
11 )
12 {
13 #if CC_EncryptDecrypt2
14 return EncryptDecryptShared(in->keyHandle, in->decrypt, in->mode,
15 &in->ivIn, &in->inData, out);
16 #else
17 OBJECT *symKey;
18 UINT16 keySize;
19 UINT16 blockSize;
20 BYTE *key;
21 TPM_ALG_ID alg;
22 TPM_ALG_ID mode;
23 TPM_RC result;
24 BOOL OK;
25 TPMA_OBJECT attributes;
26
27 // Input Validation
28 symKey = HandleToObject(in->keyHandle);
29 mode = symKey->publicArea.parameters.symDetail.sym.mode.sym;
30 attributes = symKey->publicArea.objectAttributes;
31
32 // The input key should be a symmetric key
33 if(symKey->publicArea.type != TPM_ALG_SYMCIPHER)
34 return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle;
35 // The key must be unrestricted and allow the selected operation
36 OK = IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)
37 if(YES == in->decrypt)
38 OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt);
39 else
40 OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign);
41 if(!OK)
42 return TPM_RCS_ATTRIBUTES + RC_EncryptDecrypt_keyHandle;
43
44 // If the key mode is not TPM_ALG_NULL...
45 // or TPM_ALG_NULL
46 if(mode != TPM_ALG_NULL)
47 {
48 // then the input mode has to be TPM_ALG_NULL or the same as the key
49 if((in->mode != TPM_ALG_NULL) && (in->mode != mode))
15.3 TPM2_EncryptDecrypt2
General Description
This command is identical to TPM2_EncryptDecrypt(), except that the inData parameter is the first
parameter. This permits inData to be parameter encrypted.
NOTE In platform specification updates, this command is preferred and TPM2_EncryptDecrypt() should be
deprecated.
Detailed Actions
1 #include "Tpm.h"
2 #include "EncryptDecrypt2_fp.h"
3 #include "EncryptDecrypt_fp.h"
4 #include "EncryptDecrypt_spt_fp.h"
5 #if CC_EncryptDecrypt2 // Conditional expansion of this file
6 TPM_RC
7 TPM2_EncryptDecrypt2(
8 EncryptDecrypt2_In *in, // IN: input parameter list
9 EncryptDecrypt2_Out *out // OUT: output parameter list
10 )
11 {
12 TPM_RC result;
13 // EncryptDecyrptShared() performs the operations as shown in
14 // TPM2_EncrypDecrypt
15 result = EncryptDecryptShared(in->keyHandle, in->decrypt, in->mode,
16 &in->ivIn, &in->inData,
17 (EncryptDecrypt_Out *)out);
18 // Handle response code swizzle.
19 switch(result)
20 {
21 case TPM_RCS_MODE + RC_EncryptDecrypt_mode:
22 result = TPM_RCS_MODE + RC_EncryptDecrypt2_mode;
23 break;
24 case TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn:
25 result = TPM_RCS_SIZE + RC_EncryptDecrypt2_ivIn;
26 break;
27 case TPM_RCS_SIZE + RC_EncryptDecrypt_inData:
28 result = TPM_RCS_SIZE + RC_EncryptDecrypt2_inData;
29 break;
30 default:
31 break;
32 }
33 return result;
34 }
35 #endif // CC_EncryptDecrypt2
15.4 TPM2_Hash
General Description
This command performs a hash operation on a data buffer and returns the results.
NOTE If the data buffer to be hashed is larger than will fit into the TPM’s input buffer, then the sequence
hash commands will need to be used.
If the results of the hash will be used in a signing operation that uses a restricted signing key, then the
ticket returned by this command can indicate that the hash is safe to sign.
If the digest is not safe to sign, then the TPM will return a TPMT_TK_HASHCHECK with the hierarchy set
to TPM_RH_NULL and digest set to the Empty Buffer.
If hierarchy is TPM_RH_NULL, then digest in the ticket will be the Empty Buffer.
Detailed Actions
1 #include "Tpm.h"
2 #include "Hash_fp.h"
3 #if CC_Hash // Conditional expansion of this file
4 TPM_RC
5 TPM2_Hash(
6 Hash_In *in, // IN: input parameter list
7 Hash_Out *out // OUT: output parameter list
8 )
9 {
10 HASH_STATE hashState;
11
12 // Command Output
13
14 // Output hash
15 // Start hash stack
16 out->outHash.t.size = CryptHashStart(&hashState, in->hashAlg);
17 // Adding hash data
18 CryptDigestUpdate2B(&hashState, &in->data.b);
19 // Complete hash
20 CryptHashEnd2B(&hashState, &out->outHash.b);
21
22 // Output ticket
23 out->validation.tag = TPM_ST_HASHCHECK;
24 out->validation.hierarchy = in->hierarchy;
25
26 if(in->hierarchy == TPM_RH_NULL)
27 {
28 // Ticket is not required
29 out->validation.hierarchy = TPM_RH_NULL;
30 out->validation.digest.t.size = 0;
31 }
32 else if(in->data.t.size >= sizeof(TPM_GENERATED)
33 && !TicketIsSafe(&in->data.b))
34 {
35 // Ticket is not safe
36 out->validation.hierarchy = TPM_RH_NULL;
37 out->validation.digest.t.size = 0;
38 }
39 else
40 {
41 // Compute ticket
42 TicketComputeHashCheck(in->hierarchy, in->hashAlg,
43 &out->outHash, &out->validation);
44 }
45
46 return TPM_RC_SUCCESS;
47 }
48 #endif // CC_Hash
15.5 TPM2_HMAC
General Description
This command performs an HMAC on the supplied data using the indicated hash algorithm.
NOTE 1 A TPM may implement either TPM2_HMAC() or TPM2_MAC() but not both, as they have the same
command code and there is no way to distinguish them. A TPM that supports TPM2_MAC() will
support any code that was written to use TPM2_HMAC(), but a TPM that supports TPM2_HMAC()
will not support a MAC based on symmetric block ciphers.
If the default scheme of the key referenced by handle is not TPM_ALG_NULL, then the hashAlg
parameter is required to be either the same as the key’s default or TPM_ALG_NULL (TPM_RC_VALUE).
If the default scheme of the key is TPM_ALG_NULL, then hashAlg is required to be a valid hash and not
TPM_ALG_NULL (TPM_RC_VALUE) (see hash selection matrix in
Table 72).
NOTE 3 A key may only have both sign and decrypt SET if the key is unrestricted. When both sign and
decrypt are set, there is no default scheme for the key and the hash algorithm must be specified.
Detailed Actions
1 #include "Tpm.h"
2 #include "HMAC_fp.h"
3 #if CC_HMAC // Conditional expansion of this file
4 TPM_RC
5 TPM2_HMAC(
6 HMAC_In *in, // IN: input parameter list
7 HMAC_Out *out // OUT: output parameter list
8 )
9 {
10 HMAC_STATE hmacState;
11 OBJECT *hmacObject;
12 TPMI_ALG_HASH hashAlg;
13 TPMT_PUBLIC *publicArea;
14
15 // Input Validation
16
17 // Get HMAC key object and public area pointers
18 hmacObject = HandleToObject(in->handle);
19 publicArea = &hmacObject->publicArea;
20 // Make sure that the key is an HMAC key
21 if(publicArea->type != TPM_ALG_KEYEDHASH)
22 return TPM_RCS_TYPE + RC_HMAC_handle;
23
24 // and that it is unrestricted
25 if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
26 return TPM_RCS_ATTRIBUTES + RC_HMAC_handle;
27
28 // and that it is a signing key
29 if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
30 return TPM_RCS_KEY + RC_HMAC_handle;
31
32 // See if the key has a default
33 if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL)
34 // it doesn't so use the input value
35 hashAlg = in->hashAlg;
36 else
37 {
38 // key has a default so use it
39 hashAlg
40 = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg;
41 // and verify that the input was either the TPM_ALG_NULL or the default
42 if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg)
43 hashAlg = TPM_ALG_NULL;
44 }
45 // if we ended up without a hash algorithm then return an error
46 if(hashAlg == TPM_ALG_NULL)
47 return TPM_RCS_VALUE + RC_HMAC_hashAlg;
48
49 // Command Output
50
15.6 TPM2_MAC
General Description
This command performs an HMAC or a block cipher MAC on the supplied data using the indicated
algorithm.
NOTE 1 A TPM may implement either TPM2_HMAC() or TPM2_MAC() but not both as they have the same
command code and there is no way to distinguish them. A TPM that supports TPM2_MAC() will
support any code that was written to use TPM2_HMAC() but a TPM that supports TPM2_HMAC ()
will not support a MAC based on symmetric block ciphers.
If the default scheme or mode of the key referenced by handle is not TPM_ALG_NULL, then the
inScheme parameter is required to be either the same as the key’s default or TPM_ALG_NULL
(TPM_RC_VALUE).
If the default scheme of an HMAC key is TPM_ALG_NULL, then inScheme is required to be a valid hash
and not TPM_ALG_NULL (TPM_RC_VALUE) (see algorithm selection matrix in
Table 75).
If the default mode of a symmetric cipher key is TPM_ALG_NULL, then inScheme is required to be a valid
block cipher mode for authentication and not TPM_ALG_NULL (TPM_RC_VALUE)
NOTE 3 A key may only have both sign and decrypt SET if the key is unrestricted. When both sign and
decrypt are set, there is no default scheme for the key and inScheme may not be TPM_ALG_NULL.
Detailed Actions
1 #include "Tpm.h"
2 #include "MAC_fp.h"
3 #if CC_MAC // Conditional expansion of this file
4 TPM_RC
5 TPM2_MAC(
6 MAC_In *in, // IN: input parameter list
7 MAC_Out *out // OUT: output parameter list
8 )
9 {
10 OBJECT *keyObject;
11 HMAC_STATE state;
12 TPMT_PUBLIC *publicArea;
13 TPM_RC result;
14
15 // Input Validation
16 // Get MAC key object and public area pointers
17 keyObject = HandleToObject(in->handle);
18 publicArea = &keyObject->publicArea;
19
20 // If the key is not able to do a MAC, indicate that the handle selects an
21 // object that can't do a MAC
22 result = CryptSelectMac(publicArea, &in->inScheme);
23 if(result == TPM_RCS_TYPE)
24 return TPM_RCS_TYPE + RC_MAC_handle;
25 // If there is another error type, indicate that the scheme and key are not
26 // compatible
27 if(result != TPM_RC_SUCCESS)
28 return RcSafeAddToResult(result, RC_MAC_inScheme);
29 // Make sure that the key is not restricted
30 if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
31 return TPM_RCS_ATTRIBUTES + RC_MAC_handle;
32 // and that it is a signing key
33 if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
34 return TPM_RCS_KEY + RC_MAC_handle;
35 // Command Output
36 out->outMAC.t.size = CryptMacStart(&state, &publicArea->parameters,
37 in->inScheme,
38 &keyObject->sensitive.sensitive.any.b);
39 // If the mac can't start, treat it as a fatal error
40 if(out->outMAC.t.size == 0)
41 return TPM_RC_FAILURE;
42 CryptDigestUpdate2B(&state.hashState, &in->buffer.b);
43 // If the MAC result is not what was expected, it is a fatal error
44 if(CryptHmacEnd2B(&state, &out->outMAC.b) != out->outMAC.t.size)
45 return TPM_RC_FAILURE;
46 return TPM_RC_SUCCESS;
47 }
48 #endif // CC_MAC
16.1 TPM2_GetRandom
General Description
This command returns the next bytesRequested octets from the random number generator (RNG).
NOTE 1 It is recommended that a TPM implement the RNG in a manner that would allow it to return RNG
octets such that, as long as the value of bytesRequested is not greater than the maximum digest
size, the frequency of bytesRequested being more than the number of octets available is an
infrequent occurrence.
If bytesRequested is more than will fit into a TPM2B_DIGEST on the TPM, no error is returned but the
TPM will only return as much data as will fit into a TPM2B_DIGEST buffer for the TPM.
NOTE 2 TPM2B_DIGEST is large enough to hold the largest digest that may be produced by the TPM.
Because that digest size changes according to the implemented hashes, the maximum amount of
data returned by this command is TPM implementation-dependent.
Detailed Actions
1 #include "Tpm.h"
2 #include "GetRandom_fp.h"
3 #if CC_GetRandom // Conditional expansion of this file
4 TPM_RC
5 TPM2_GetRandom(
6 GetRandom_In *in, // IN: input parameter list
7 GetRandom_Out *out // OUT: output parameter list
8 )
9 {
10 // Command Output
11
12 // if the requested bytes exceed the output buffer size, generates the
13 // maximum bytes that the output buffer allows
14 if(in->bytesRequested > sizeof(TPMU_HA))
15 out->randomBytes.t.size = sizeof(TPMU_HA);
16 else
17 out->randomBytes.t.size = in->bytesRequested;
18
19 CryptRandomGenerate(out->randomBytes.t.size, out->randomBytes.t.buffer);
20
21 return TPM_RC_SUCCESS;
22 }
23 #endif // CC_GetRandom
16.2 TPM2_StirRandom
General Description
Detailed Actions
1 #include "Tpm.h"
2 #include "StirRandom_fp.h"
3 #if CC_StirRandom // Conditional expansion of this file
4 TPM_RC
5 TPM2_StirRandom(
6 StirRandom_In *in // IN: input parameter list
7 )
8 {
9 // Internal Data Update
10 CryptRandomStir(in->inData.t.size, in->inData.t.buffer);
11
12 return TPM_RC_SUCCESS;
13 }
14 #endif // CC_StirRandom
17 Hash/HMAC/Event Sequences
17.1 Introduction
All of the commands in this group are to support sequences for which an intermediate state must be
maintained. For a description of sequences, see “Hash, MAC, and Event Sequences” in TPM 2.0 Part 1.
A TPM may implement either TPM2_HMAC_Start() or TPM2_MAC_Start() but not both as they have the
same command code and there is no way to distinguish them. A TPM that supports TPM2_MAC_Start()
will support any code that was written to use TPM2_HMAC_Start() but a TPM that supports
TPM2_HMAC_Start() will not support a MAC based on symmetric block ciphers.
17.2 TPM2_HMAC_Start
General Description
This command starts an HMAC sequence. The TPM will create and initialize an HMAC sequence
structure, assign a handle to the sequence, and set the authValue of the sequence object to the value in
auth.
If the default scheme of the key referenced by handle is not TPM_ALG_NULL, then the hashAlg
parameter is required to be either the same as the key’s default or TPM_ALG_NULL (TPM_RC_VALUE).
If the default scheme of the key is TPM_ALG_NULL, then hashAlg is required to be a valid hash and not
TPM_ALG_NULL (TPM_RC_VALUE).
NOTE 1 A TPM may implement either TPM2_HMAC_Start() or TPM2_MAC_Start() but not both, as they have
the same command code and there is no way to distinguish them. A TPM that supports
TPM2_MAC_Start() will support any code that was written to use TPM2_HMAC_Start(), but a TPM
that supports TPM2_HMAC_Start() will not support a MAC based on symmetric block ciphers.
Detailed Actions
1 #include "Tpm.h"
2 #include "HMAC_Start_fp.h"
3 #if CC_HMAC_Start // Conditional expansion of this file
4 TPM_RC
5 TPM2_HMAC_Start(
6 HMAC_Start_In *in, // IN: input parameter list
7 HMAC_Start_Out *out // OUT: output parameter list
8 )
9 {
10 OBJECT *keyObject;
11 TPMT_PUBLIC *publicArea;
12 TPM_ALG_ID hashAlg;
13
14 // Input Validation
15
16 // Get HMAC key object and public area pointers
17 keyObject = HandleToObject(in->handle);
18 publicArea = &keyObject->publicArea;
19
20 // Make sure that the key is an HMAC key
21 if(publicArea->type != TPM_ALG_KEYEDHASH)
22 return TPM_RCS_TYPE + RC_HMAC_Start_handle;
23
24 // and that it is unrestricted
25 if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
26 return TPM_RCS_ATTRIBUTES + RC_HMAC_Start_handle;
27
28 // and that it is a signing key
29 if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
30 return TPM_RCS_KEY + RC_HMAC_Start_handle;
31
32 // See if the key has a default
33 if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL)
34 // it doesn't so use the input value
35 hashAlg = in->hashAlg;
36 else
37 {
38 // key has a default so use it
39 hashAlg
40 = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg;
41 // and verify that the input was either the TPM_ALG_NULL or the default
42 if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg)
43 hashAlg = TPM_ALG_NULL;
44 }
45 // if we ended up without a hash algorithm then return an error
46 if(hashAlg == TPM_ALG_NULL)
47 return TPM_RCS_VALUE + RC_HMAC_Start_hashAlg;
48
49 // Internal Data Update
50
17.3 TPM2_MAC_Start
General Description
This command starts a MAC sequence. The TPM will create and initialize a MAC sequence structure,
assign a handle to the sequence, and set the authValue of the sequence object to the value in auth.
If the default scheme of the key referenced by handle is not TPM_ALG_NULL, then the inScheme
parameter is required to be either the same as the key’s default or TPM_ALG_NULL (TPM_RC_VALUE).
If the default scheme of the key is TPM_ALG_NULL, then inSchemeis required to be a valid hash or
symmetric MAC scheme and not TPM_ALG_NULL (TPM_RC_VALUE).
NOTE 3 For a TPM_ALG_SYMCIPHER key, the symmetric block cipher algorithm is part of the key definition.
Detailed Actions
1 #include "Tpm.h"
2 #include "MAC_Start_fp.h"
3 #if CC_MAC_Start // Conditional expansion of this file
4 TPM_RC
5 TPM2_MAC_Start(
6 MAC_Start_In *in, // IN: input parameter list
7 MAC_Start_Out *out // OUT: output parameter list
8 )
9 {
10 OBJECT *keyObject;
11 TPMT_PUBLIC *publicArea;
12 TPM_RC result;
13
14 // Input Validation
15
16 // Get HMAC key object and public area pointers
17 keyObject = HandleToObject(in->handle);
18 publicArea = &keyObject->publicArea;
19
20 // Make sure that the key can do what is required
21 result = CryptSelectMac(publicArea, &in->inScheme);
22 // If the key is not able to do a MAC, indicate that the handle selects an
23 // object that can't do a MAC
24 if(result == TPM_RCS_TYPE)
25 return TPM_RCS_TYPE + RC_MAC_Start_handle;
26 // If there is another error type, indicate that the scheme and key are not
27 // compatible
28 if(result != TPM_RC_SUCCESS)
29 return RcSafeAddToResult(result, RC_MAC_Start_inScheme);
30 // Make sure that the key is not restricted
31 if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
32 return TPM_RCS_ATTRIBUTES + RC_MAC_Start_handle;
33 // and that it is a signing key
34 if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
35 return TPM_RCS_KEY + RC_MAC_Start_handle;
36
37 // Internal Data Update
38 // Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be
39 // returned at this point
40 return ObjectCreateHMACSequence(in->inScheme,
41 keyObject,
42 &in->auth,
43 &out->sequenceHandle);
44 }
45 #endif // CC_MAC_Start
17.4 TPM2_HashSequenceStart
General Description
This command starts a hash or an Event Sequence. If hashAlg is an implemented hash, then a hash
sequence is started. If hashAlg is TPM_ALG_NULL, then an Event Sequence is started. If hashAlg is
neither an implemented algorithm nor TPM_ALG_NULL, then the TPM shall return TPM_RC_HASH.
Depending on hashAlg, the TPM will create and initialize a Hash Sequence context or an Event
Sequence context. Additionally, it will assign a handle to the context and set the authValue of the context
to the value in auth. A sequence context for an Event (hashAlg = TPM_ALG_NULL) contains a hash
context for each of the PCR banks implemented on the TPM.
Detailed Actions
1 #include "Tpm.h"
2 #include "HashSequenceStart_fp.h"
3 #if CC_HashSequenceStart // Conditional expansion of this file
4 TPM_RC
5 TPM2_HashSequenceStart(
6 HashSequenceStart_In *in, // IN: input parameter list
7 HashSequenceStart_Out *out // OUT: output parameter list
8 )
9 {
10 // Internal Data Update
11
12 if(in->hashAlg == TPM_ALG_NULL)
13 // Start a event sequence. A TPM_RC_OBJECT_MEMORY error may be
14 // returned at this point
15 return ObjectCreateEventSequence(&in->auth, &out->sequenceHandle);
16
17 // Start a hash sequence. A TPM_RC_OBJECT_MEMORY error may be
18 // returned at this point
19 return ObjectCreateHashSequence(in->hashAlg, &in->auth, &out->sequenceHandle);
20 }
21 #endif // CC_HashSequenceStart
17.5 TPM2_SequenceUpdate
General Description
This command is used to add data to a hash or HMAC sequence. The amount of data in buffer may be
any size up to the limits of the TPM.
Proper authorization for the sequence object associated with sequenceHandle is required. If an
authorization or audit of this command requires computation of a cpHash and an rpHash, the Name
associated with sequenceHandle will be the Empty Buffer.
If the command does not return TPM_RC_SUCCESS, the state of the sequence is unmodified.
If the sequence is intended to produce a digest that will be signed by a restricted signing key, then the
first block of data shall contain sizeof(TPM_GENERATED) octets and the first octets shall not be
TPM_GENERATED_VALUE.
NOTE 2 This requirement allows the TPM to validate that the first block is safe to sign without having to
accumulate octets over multiple calls.
Detailed Actions
1 #include "Tpm.h"
2 #include "SequenceUpdate_fp.h"
3 #if CC_SequenceUpdate // Conditional expansion of this file
4 TPM_RC
5 TPM2_SequenceUpdate(
6 SequenceUpdate_In *in // IN: input parameter list
7 )
8 {
9 OBJECT *object;
10 HASH_OBJECT *hashObject;
11
12 // Input Validation
13
14 // Get sequence object pointer
15 object = HandleToObject(in->sequenceHandle);
16 hashObject = (HASH_OBJECT *)object;
17
18 // Check that referenced object is a sequence object.
19 if(!ObjectIsSequence(object))
20 return TPM_RCS_MODE + RC_SequenceUpdate_sequenceHandle;
21
22 // Internal Data Update
23
24 if(object->attributes.eventSeq == SET)
25 {
26 // Update event sequence object
27 UINT32 i;
28 for(i = 0; i < HASH_COUNT; i++)
29 {
30 // Update sequence object
31 CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b);
32 }
33 }
34 else
35 {
36 // Update hash/HMAC sequence object
37 if(hashObject->attributes.hashSeq == SET)
38 {
39 // Is this the first block of the sequence
40 if(hashObject->attributes.firstBlock == CLEAR)
41 {
42 // If so, indicate that first block was received
43 hashObject->attributes.firstBlock = SET;
44
45 // Check the first block to see if the first block can contain
46 // the TPM_GENERATED_VALUE. If it does, it is not safe for
47 // a ticket.
48 if(TicketIsSafe(&in->buffer.b))
49 hashObject->attributes.ticketSafe = SET;
50 }
51 // Update sequence object hash/HMAC stack
52 CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b);
53 }
54 else if(object->attributes.hmacSeq == SET)
55 {
17.6 TPM2_SequenceComplete
General Description
This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result.
For a hash sequence, if the results of the hash will be used in a signing operation that uses a restricted
signing key, then the ticket returned by this command can indicate that the hash is safe to sign.
If the digest is not safe to sign, then validation will be a TPMT_TK_HASHCHECK with the hierarchy set to
TPM_RH_NULL and digest set to the Empty Buffer.
If hierarchy is TPM_RH_NULL, then digest in the ticket will be the Empty Buffer.
NOTE 2 Regardless of the contents of the first octets of the hashed message, if the first buffer sent to the
TPM had fewer than sizeof(TPM_GENERATED) octets, then the TPM will operate as if digest is not
safe to sign.
NOTE 3 The ticket is only required for a signing operation that uses a restricted signing key. It is always
returned, but can be ignored if not needed.
If sequenceHandle references an Event Sequence, then the TPM shall return TPM_RC_MODE.
Proper authorization for the sequence object associated with sequenceHandle is required. If an
authorization or audit of this command requires computation of a cpHash and an rpHash, the Name
associated with sequenceHandle will be the Empty Buffer.
If this command completes successfully, the sequenceHandle object will be flushed.
Detailed Actions
1 #include "Tpm.h"
2 #include "SequenceComplete_fp.h"
3 #if CC_SequenceComplete // Conditional expansion of this file
4 TPM_RC
5 TPM2_SequenceComplete(
6 SequenceComplete_In *in, // IN: input parameter list
7 SequenceComplete_Out *out // OUT: output parameter list
8 )
9 {
10 HASH_OBJECT *hashObject;
11 // Input validation
12 // Get hash object pointer
13 hashObject = (HASH_OBJECT *)HandleToObject(in->sequenceHandle);
14
15 // input handle must be a hash or HMAC sequence object.
16 if(hashObject->attributes.hashSeq == CLEAR
17 && hashObject->attributes.hmacSeq == CLEAR)
18 return TPM_RCS_MODE + RC_SequenceComplete_sequenceHandle;
19 // Command Output
20 if(hashObject->attributes.hashSeq == SET) // sequence object for hash
21 {
22 // Get the hash algorithm before the algorithm is lost in CryptHashEnd
23 TPM_ALG_ID hashAlg = hashObject->state.hashState[0].hashAlg;
24
25 // Update last piece of the data
26 CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b);
27
28 // Complete hash
29 out->result.t.size = CryptHashEnd(&hashObject->state.hashState[0],
30 sizeof(out->result.t.buffer),
31 out->result.t.buffer);
32 // Check if the first block of the sequence has been received
33 if(hashObject->attributes.firstBlock == CLEAR)
34 {
35 // If not, then this is the first block so see if it is 'safe'
36 // to sign.
37 if(TicketIsSafe(&in->buffer.b))
38 hashObject->attributes.ticketSafe = SET;
39 }
40 // Output ticket
41 out->validation.tag = TPM_ST_HASHCHECK;
42 out->validation.hierarchy = in->hierarchy;
43
44 if(in->hierarchy == TPM_RH_NULL)
45 {
46 // Ticket is not required
47 out->validation.digest.t.size = 0;
48 }
49 else if(hashObject->attributes.ticketSafe == CLEAR)
50 {
51 // Ticket is not safe to generate
52 out->validation.hierarchy = TPM_RH_NULL;
53 out->validation.digest.t.size = 0;
54 }
55 else
56 {
57 // Compute ticket
58 TicketComputeHashCheck(out->validation.hierarchy, hashAlg,
59 &out->result, &out->validation);
60 }
61 }
62 else
63 {
64 // Update last piece of data
65 CryptDigestUpdate2B(&hashObject->state.hmacState.hashState, &in->buffer.b);
66 #if !SMAC_IMPLEMENTED
67 // Complete HMAC
68 out->result.t.size = CryptHmacEnd(&(hashObject->state.hmacState),
69 sizeof(out->result.t.buffer),
70 out->result.t.buffer);
71 #else
72 // Complete the MAC
73 out->result.t.size = CryptMacEnd(&hashObject->state.hmacState,
74 sizeof(out->result.t.buffer),
75 out->result.t.buffer);
76 #endif
77 // No ticket is generated for HMAC sequence
78 out->validation.tag = TPM_ST_HASHCHECK;
79 out->validation.hierarchy = TPM_RH_NULL;
80 out->validation.digest.t.size = 0;
81 }
82 // Internal Data Update
83 // mark sequence object as evict so it will be flushed on the way out
84 hashObject->attributes.evict = SET;
85
86 return TPM_RC_SUCCESS;
87 }
88 #endif // CC_SequenceComplete
17.7 TPM2_EventSequenceComplete
General Description
This command adds the last part of data, if any, to an Event Sequence and returns the result in a digest
list. If pcrHandle references a PCR and not TPM_RH_NULL, then the returned digest list is processed in
the same manner as the digest list input parameter to TPM2_PCR_Extend(). That is, if a bank contains a
PCR associated with pcrHandle, it is extended with the associated digest value from the list.
If sequenceHandle references a hash or HMAC sequence, the TPM shall return TPM_RC_MODE.
Proper authorization for the sequence object associated with sequenceHandle is required. If an
authorization or audit of this command requires computation of a cpHash and an rpHash, the Name
associated with sequenceHandle will be the Empty Buffer.
If this command completes successfully, the sequenceHandle object will be flushed.
NOTE: Unlike TPM2_PCR_Event(), a digest is always returned for each implemented hash algorithm . There
is no option to only return digests for which pcrHandle is allocated.
Detailed Actions
1 #include "Tpm.h"
2 #include "EventSequenceComplete_fp.h"
3 #if CC_EventSequenceComplete // Conditional expansion of this file
4 TPM_RC
5 TPM2_EventSequenceComplete(
6 EventSequenceComplete_In *in, // IN: input parameter list
7 EventSequenceComplete_Out *out // OUT: output parameter list
8 )
9 {
10 HASH_OBJECT *hashObject;
11 UINT32 i;
12 TPM_ALG_ID hashAlg;
13 // Input validation
14 // get the event sequence object pointer
15 hashObject = (HASH_OBJECT *)HandleToObject(in->sequenceHandle);
16
17 // input handle must reference an event sequence object
18 if(hashObject->attributes.eventSeq != SET)
19 return TPM_RCS_MODE + RC_EventSequenceComplete_sequenceHandle;
20
21 // see if a PCR extend is requested in call
22 if(in->pcrHandle != TPM_RH_NULL)
23 {
24 // see if extend of the PCR is allowed at the locality of the command,
25 if(!PCRIsExtendAllowed(in->pcrHandle))
26 return TPM_RC_LOCALITY;
27 // if an extend is going to take place, then check to see if there has
28 // been an orderly shutdown. If so, and the selected PCR is one of the
29 // state saved PCR, then the orderly state has to change. The orderly state
30 // does not change for PCR that are not preserved.
31 // NOTE: This doesn't just check for Shutdown(STATE) because the orderly
32 // state will have to change if this is a state-saved PCR regardless
33 // of the current state. This is because a subsequent Shutdown(STATE) will
34 // check to see if there was an orderly shutdown and not do anything if
35 // there was. So, this must indicate that a future Shutdown(STATE) has
36 // something to do.
37 if(PCRIsStateSaved(in->pcrHandle))
38 RETURN_IF_ORDERLY;
39 }
40 // Command Output
41 out->results.count = 0;
42
43 for(i = 0; i < HASH_COUNT; i++)
44 {
45 hashAlg = CryptHashGetAlgByIndex(i);
46 // Update last piece of data
47 CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b);
48 // Complete hash
49 out->results.digests[out->results.count].hashAlg = hashAlg;
50 CryptHashEnd(&hashObject->state.hashState[i],
51 CryptHashGetDigestSize(hashAlg),
52 (BYTE *)&out->results.digests[out->results.count].digest);
53 // Extend PCR
54 if(in->pcrHandle != TPM_RH_NULL)
55 PCRExtend(in->pcrHandle, hashAlg,
56 CryptHashGetDigestSize(hashAlg),
57 (BYTE *)&out->results.digests[out->results.count].digest);
58 out->results.count++;
59 }
60 // Internal Data Update
61 // mark sequence object as evict so it will be flushed on the way out
62 hashObject->attributes.evict = SET;
63
64 return TPM_RC_SUCCESS;
65 }
66 #endif // CC_EventSequenceComplete
18 Attestation Commands
18.1 Introduction
The attestation commands cause the TPM to sign an internally generated data structure. The contents of
the data structure vary according to the command.
If the sign attribute is not SET in the key referenced by signHandle then the TPM shall return
TPM_RC_KEY.
All signing commands include a parameter (typically inScheme) for the caller to specify a scheme to be
used for the signing operation. This scheme will be applied only if the scheme of the key is
TPM_ALG_NULL or the key handle is TPM_RH_NULL. If the scheme for signHandle is not
TPM_ALG_NULL, then inScheme.scheme shall be TPM_ALG_NULL or the same as scheme in the
public area of the key. If the scheme for signHandle is TPM_ALG_NULL or the key handle is
TPM_RH_NULL, then inScheme will be used for the signing operation and may not be TPM_ALG_NULL.
The TPM shall return TPM_RC_SCHEME to indicate that the scheme is not appropriate.
For a signing key that is not restricted, the caller may specify the scheme to be used as long as the
scheme is compatible with the family of the key (for example, TPM_ALG_RSAPSS cannot be selected for
an ECC key). If the caller sets scheme to TPM_ALG_NULL, then the default scheme of the key is used.
For a restricted signing key, the key's scheme cannot be TPM_ALG_NULL and cannot be overridden.
If the handle for the signing key (signHandle) is TPM_RH_NULL, then all of the actions of the command
are performed and the attestation block is “signed” with the NULL Signature.
NOTE 1 This mechanism is provided so that additional commands are not required to access the data that
might be in an attestation structure.
NOTE 2 When signHandle is TPM_RH_NULL, scheme is still required to be a valid signing scheme (may be
TPM_ALG_NULL), but the scheme will have no effect on the format of the signature. It will always
be the NULL Signature.
NOTE 3 The obfuscation value for each signing key will be unique to that key in a specific location. That is,
each version of a duplicated signing key will have a different obfuscation value.
When the signing key is TPM_RH_NULL, the data structure is produced but not signed; and the values in
the signed data structure are obfuscated. When computing the obfuscation value for TPM_RH_NULL, the
hash used for context integrity is used.
If the signing scheme of signHandle is an anonymous scheme, then the attestation blocks will not contain
the Qualified Name of the signHandle.
Each of the attestation structures allows the caller to provide some qualifying data (qualifyingData). For
most signing schemes, this value will be placed in the TPMS_ATTEST.extraData parameter that is then
hashed and signed. However, for some schemes such as ECDAA, the qualifyingData is used in a
different manner (for details, see “ECDAA” in TPM 2.0 Part 1).
18.2 TPM2_Certify
General Description
The purpose of this command is to prove that an object with a specific Name is loaded in the TPM. By
certifying that the object is loaded, the TPM warrants that a public area with a given Name is self-
consistent and associated with a valid sensitive area. If a relying party has a public area that has the
same Name as a Name certified with this command, then the values in that public area are correct.
NOTE 1 See 18.1 for description of how the signing scheme is selected.
Authorization for objectHandle requires ADMIN role authorization. If performed with a policy session, the
session shall have a policySession→commandCode set to TPM_CC_Certify. This indicates that the
policy that is being used is a policy that is for certification, and not a policy that would approve another
use. That is, authority to use an object does not grant authority to certify the object.
The object may be any object that is loaded with TPM2_Load() or TPM2_CreatePrimary(). An object that
only has its public area loaded cannot be certified.
NOTE 2 The restriction occurs because the Name is used to identify the object being certified. If the TPM
has not validated that the public area is associated with a matched sensitive area, then the public
area may not represent a valid object and cannot be certified.
The certification includes the Name and Qualified Name of the certified object as well as the Name and
the Qualified Name of the certifying object.
NOTE 3 If signHandle is TPM_RH_NULL, the TPMS_ATTEST structure is returned and signature is a NULL
Signature.
Detailed Actions
1 #include "Tpm.h"
2 #include "Attest_spt_fp.h"
3 #include "Certify_fp.h"
4 #if CC_Certify // Conditional expansion of this file
5 TPM_RC
6 TPM2_Certify(
7 Certify_In *in, // IN: input parameter list
8 Certify_Out *out // OUT: output parameter list
9 )
10 {
11 TPMS_ATTEST certifyInfo;
12 OBJECT *signObject = HandleToObject(in->signHandle);
13 OBJECT *certifiedObject = HandleToObject(in->objectHandle);
14 // Input validation
15 if(!IsSigningObject(signObject))
16 return TPM_RCS_KEY + RC_Certify_signHandle;
17 if(!CryptSelectSignScheme(signObject, &in->inScheme))
18 return TPM_RCS_SCHEME + RC_Certify_inScheme;
19
20 // Command Output
21 // Filling in attest information
22 // Common fields
23 FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
24 &certifyInfo);
25
26 // Certify specific fields
27 certifyInfo.type = TPM_ST_ATTEST_CERTIFY;
28 // NOTE: the certified object is not allowed to be TPM_ALG_NULL so
29 // 'certifiedObject' will never be NULL
30 certifyInfo.attested.certify.name = certifiedObject->name;
31
32 // When using an anonymous signing scheme, need to set the qualified Name to the
33 // empty buffer to avoid correlation between keys
34 if(CryptIsSchemeAnonymous(in->inScheme.scheme))
35 certifyInfo.attested.certify.qualifiedName.t.size = 0;
36 else
37 certifyInfo.attested.certify.qualifiedName = certifiedObject->qualifiedName;
38
39 // Sign attestation structure. A NULL signature will be returned if
40 // signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
41 // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned
42 // by SignAttestInfo()
43 return SignAttestInfo(signObject, &in->inScheme, &certifyInfo,
44 &in->qualifyingData, &out->certifyInfo, &out->signature);
45 }
46 #endif // CC_Certify
18.3 TPM2_CertifyCreation
General Description
This command is used to prove the association between an object and its creation data. The TPM will
validate that the ticket was produced by the TPM and that the ticket validates the association between a
loaded public area and the provided hash of the creation data (creationHash).
NOTE 1 See 18.1 for description of how the signing scheme is selected.
The TPM will create a test ticket using the Name associated with objectHandle and creationHash as:
HMAC(proof, (TPM_ST_CREATION || objectHandle→Name || creationHash)) (4)
This ticket is then compared to creation ticket. If the tickets are not the same, the TPM shall return
TPM_RC_TICKET.
If the ticket is valid, then the TPM will create a TPMS_ATTEST structure and place creationHash of the
command in the creationHash field of the structure. The Name associated with objectHandle will be
included in the attestation data that is then signed using the key associated with signHandle.
NOTE 2 If signHandle is TPM_RH_NULL, the TPMS_ATTEST structure is returned and signature is a NULL
Signature.
Detailed Actions
1 #include "Tpm.h"
2 #include "Attest_spt_fp.h"
3 #include "CertifyCreation_fp.h"
4 #if CC_CertifyCreation // Conditional expansion of this file
5 TPM_RC
6 TPM2_CertifyCreation(
7 CertifyCreation_In *in, // IN: input parameter list
8 CertifyCreation_Out *out // OUT: output parameter list
9 )
10 {
11 TPMT_TK_CREATION ticket;
12 TPMS_ATTEST certifyInfo;
13 OBJECT *certified = HandleToObject(in->objectHandle);
14 OBJECT *signObject = HandleToObject(in->signHandle);
15 // Input Validation
16 if(!IsSigningObject(signObject))
17 return TPM_RCS_KEY + RC_CertifyCreation_signHandle;
18 if(!CryptSelectSignScheme(signObject, &in->inScheme))
19 return TPM_RCS_SCHEME + RC_CertifyCreation_inScheme;
20
21 // CertifyCreation specific input validation
22 // Re-compute ticket
23 TicketComputeCreation(in->creationTicket.hierarchy, &certified->name,
24 &in->creationHash, &ticket);
25 // Compare ticket
26 if(!MemoryEqual2B(&ticket.digest.b, &in->creationTicket.digest.b))
27 return TPM_RCS_TICKET + RC_CertifyCreation_creationTicket;
28
29 // Command Output
30 // Common fields
31 FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
32 &certifyInfo);
33
34 // CertifyCreation specific fields
35 // Attestation type
36 certifyInfo.type = TPM_ST_ATTEST_CREATION;
37 certifyInfo.attested.creation.objectName = certified->name;
38
39 // Copy the creationHash
40 certifyInfo.attested.creation.creationHash = in->creationHash;
41
42 // Sign attestation structure. A NULL signature will be returned if
43 // signObject is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
44 // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
45 // this point
46 return SignAttestInfo(signObject, &in->inScheme, &certifyInfo,
47 &in->qualifyingData, &out->certifyInfo,
48 &out->signature);
49 }
50 #endif // CC_CertifyCreation
18.4 TPM2_Quote
General Description
NOTE 1 See 18.1 for description of how the signing scheme is selected.
The digest is computed as the hash of the concatenation of all of the digest values of the selected PCR.
The concatenation of PCR is described in TPM 2.0 Part 1, Selecting Multiple PCR.
NOTE 2 If signHandle is TPM_RH_NULL, the TPMS_ATTEST structure is returned and signature is a NULL
Signature.
NOTE 4 Unlike TPM 1.2, TPM2_Quote does not return the PCR values. See Part 1, “Attesting to PCR” for a
discussion of this issue.
Detailed Actions
1 #include "Tpm.h"
2 #include "Attest_spt_fp.h"
3 #include "Quote_fp.h"
4 #if CC_Quote // Conditional expansion of this file
5 TPM_RC
6 TPM2_Quote(
7 Quote_In *in, // IN: input parameter list
8 Quote_Out *out // OUT: output parameter list
9 )
10 {
11 TPMI_ALG_HASH hashAlg;
12 TPMS_ATTEST quoted;
13 OBJECT *signObject = HandleToObject(in->signHandle);
14 // Input Validation
15 if(!IsSigningObject(signObject))
16 return TPM_RCS_KEY + RC_Quote_signHandle;
17 if(!CryptSelectSignScheme(signObject, &in->inScheme))
18 return TPM_RCS_SCHEME + RC_Quote_inScheme;
19
20 // Command Output
21
22 // Filling in attest information
23 // Common fields
24 // FillInAttestInfo may return TPM_RC_SCHEME or TPM_RC_KEY
25 FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, "ed);
26
27 // Quote specific fields
28 // Attestation type
29 quoted.type = TPM_ST_ATTEST_QUOTE;
30
31 // Get hash algorithm in sign scheme. This hash algorithm is used to
32 // compute PCR digest. If there is no algorithm, then the PCR cannot
33 // be digested and this command returns TPM_RC_SCHEME
34 hashAlg = in->inScheme.details.any.hashAlg;
35
36 if(hashAlg == TPM_ALG_NULL)
37 return TPM_RCS_SCHEME + RC_Quote_inScheme;
38
39 // Compute PCR digest
40 PCRComputeCurrentDigest(hashAlg, &in->PCRselect,
41 "ed.attested.quote.pcrDigest);
42
43 // Copy PCR select. "PCRselect" is modified in PCRComputeCurrentDigest
44 // function
45 quoted.attested.quote.pcrSelect = in->PCRselect;
46
47 // Sign attestation structure. A NULL signature will be returned if
48 // signObject is NULL.
49 return SignAttestInfo(signObject, &in->inScheme, "ed, &in->qualifyingData,
50 &out->quoted, &out->signature);
51 }
52 #endif // CC_Quote
18.5 TPM2_GetSessionAuditDigest
General Description
NOTE 1 See 18.1 for description of how the signing scheme is selected.
NOTE 2 A session does not become an audit session until the successful completion of the command in
which the session is first used as an audit session.
This command requires authorization from the privacy administrator of the TPM (expressed with
Endorsement Authorization) as well as authorization to use the key associated with signHandle.
If this command is audited, then the audit digest that is signed will not include the digest of this command
because the audit digest is only updated when the command completes successfully.
This command does not cause the audit session to be closed and does not reset the digest value.
NOTE 3 If sessionHandle is used as an audit session for this command, the command is audited in the same
manner as any other command.
NOTE 4 If signHandle is TPM_RH_NULL, the TPMS_ATTEST structure is returned and signature is a NULL
Signature.
Detailed Actions
1 #include "Tpm.h"
2 #include "Attest_spt_fp.h"
3 #include "GetSessionAuditDigest_fp.h"
4 #if CC_GetSessionAuditDigest // Conditional expansion of this file
5 TPM_RC
6 TPM2_GetSessionAuditDigest(
7 GetSessionAuditDigest_In *in, // IN: input parameter list
8 GetSessionAuditDigest_Out *out // OUT: output parameter list
9 )
10 {
11 SESSION *session = SessionGet(in->sessionHandle);
12 TPMS_ATTEST auditInfo;
13 OBJECT *signObject = HandleToObject(in->signHandle);
14 // Input Validation
15 if(!IsSigningObject(signObject))
16 return TPM_RCS_KEY + RC_GetSessionAuditDigest_signHandle;
17 if(!CryptSelectSignScheme(signObject, &in->inScheme))
18 return TPM_RCS_SCHEME + RC_GetSessionAuditDigest_inScheme;
19
20 // session must be an audit session
21 if(session->attributes.isAudit == CLEAR)
22 return TPM_RCS_TYPE + RC_GetSessionAuditDigest_sessionHandle;
23
24 // Command Output
25 // Fill in attest information common fields
26 FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
27 &auditInfo);
28
29 // SessionAuditDigest specific fields
30 auditInfo.type = TPM_ST_ATTEST_SESSION_AUDIT;
31 auditInfo.attested.sessionAudit.sessionDigest = session->u2.auditDigest;
32
33 // Exclusive audit session
34 auditInfo.attested.sessionAudit.exclusiveSession
35 = (g_exclusiveAuditSession == in->sessionHandle);
36
37 // Sign attestation structure. A NULL signature will be returned if
38 // signObject is NULL.
39 return SignAttestInfo(signObject, &in->inScheme, &auditInfo,
40 &in->qualifyingData, &out->auditInfo,
41 &out->signature);
42 }
43 #endif // CC_GetSessionAuditDigest
18.6 TPM2_GetCommandAuditDigest
General Description
This command returns the current value of the command audit digest, a digest of the commands being
audited, and the audit hash algorithm. These values are placed in an attestation structure and signed with
the key referenced by signHandle.
NOTE 1 See 18.1 for description of how the signing scheme is selected.
When this command completes successfully, and signHandle is not TPM_RH_NULL, the audit digest is
cleared. If signHandle is TPM_RH_NULL, signature is the Empty Buffer and the audit digest is not
cleared.
NOTE 2 The way that the TPM tracks that the digest is clear is vendor -dependent. The reference
implementation resets the size of the digest to zero.
If this command is being audited, then the signed digest produced by the command will not include the
command. At the end of this command, the audit digest will be extended with cpHash and the rpHash of
the command, which would change the command audit digest signed by the next invocation of this
command.
This command requires authorization from the privacy administrator of the TPM (expressed with
Endorsement Authorization) as well as authorization to use the key associated with signHandle.
Detailed Actions
1 #include "Tpm.h"
2 #include "Attest_spt_fp.h"
3 #include "GetCommandAuditDigest_fp.h"
4 #if CC_GetCommandAuditDigest // Conditional expansion of this file
5 TPM_RC
6 TPM2_GetCommandAuditDigest(
7 GetCommandAuditDigest_In *in, // IN: input parameter list
8 GetCommandAuditDigest_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result;
12 TPMS_ATTEST auditInfo;
13 OBJECT *signObject = HandleToObject(in->signHandle);
14 // Input validation
15 if(!IsSigningObject(signObject))
16 return TPM_RCS_KEY + RC_GetCommandAuditDigest_signHandle;
17 if(!CryptSelectSignScheme(signObject, &in->inScheme))
18 return TPM_RCS_SCHEME + RC_GetCommandAuditDigest_inScheme;
19
20 // Command Output
21 // Fill in attest information common fields
22 FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
23 &auditInfo);
24
25 // CommandAuditDigest specific fields
26 auditInfo.type = TPM_ST_ATTEST_COMMAND_AUDIT;
27 auditInfo.attested.commandAudit.digestAlg = gp.auditHashAlg;
28 auditInfo.attested.commandAudit.auditCounter = gp.auditCounter;
29
30 // Copy command audit log
31 auditInfo.attested.commandAudit.auditDigest = gr.commandAuditDigest;
32 CommandAuditGetDigest(&auditInfo.attested.commandAudit.commandDigest);
33
34 // Sign attestation structure. A NULL signature will be returned if
35 // signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE,
36 // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at
37 // this point
38 result = SignAttestInfo(signObject, &in->inScheme, &auditInfo,
39 &in->qualifyingData, &out->auditInfo,
40 &out->signature);
41 // Internal Data Update
42 if(result == TPM_RC_SUCCESS && in->signHandle != TPM_RH_NULL)
43 // Reset log
44 gr.commandAuditDigest.t.size = 0;
45
46 return result;
47 }
48 #endif // CC_GetCommandAuditDigest
18.7 TPM2_GetTime
General Description
NOTE 1 See 18.1 for description of how the signing scheme is selected.
The values of Clock, resetCount and restartCount appear in two places in timeInfo: once in
TPMS_ATTEST.clockInfo and again in TPMS_ATTEST.attested.time.clockInfo. The firmware version
number also appears in two places (TPMS_ATTEST.firmwareVersion and
TPMS_ATTEST.attested.time.firmwareVersion). If signHandle is in the endorsement or platform
hierarchies, both copies of the data will be the same. However, if signHandle is in the storage hierarchy or
is TPM_RH_NULL, the values in TPMS_ATTEST.clockInfo and TPMS_ATTEST.firmwareVersion are
obfuscated but the values in TPMS_ATTEST.attested.time are not.
NOTE 2 The purpose of this duplication is to allow an entity who is trusted by the privacy Administrator to
correlate the obfuscated values with the clear-text values. This command requires Endorsement
Authorization.
NOTE 3 If signHandle is TPM_RH_NULL, the TPMS_ATTEST structure is returned and signature is a NULL
Signature.
Detailed Actions
1 #include "Tpm.h"
2 #include "Attest_spt_fp.h"
3 #include "GetTime_fp.h"
4 #if CC_GetTime // Conditional expansion of this file
5 TPM_RC
6 TPM2_GetTime(
7 GetTime_In *in, // IN: input parameter list
8 GetTime_Out *out // OUT: output parameter list
9 )
10 {
11 TPMS_ATTEST timeInfo;
12 OBJECT *signObject = HandleToObject(in->signHandle);
13 // Input Validation
14 if(!IsSigningObject(signObject))
15 return TPM_RCS_KEY + RC_GetTime_signHandle;
16 if(!CryptSelectSignScheme(signObject, &in->inScheme))
17 return TPM_RCS_SCHEME + RC_GetTime_inScheme;
18
19 // Command Output
20 // Fill in attest common fields
21 FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &timeInfo);
22
23 // GetClock specific fields
24 timeInfo.type = TPM_ST_ATTEST_TIME;
25 timeInfo.attested.time.time.time = g_time;
26 TimeFillInfo(&timeInfo.attested.time.time.clockInfo);
27
28 // Firmware version in plain text
29 timeInfo.attested.time.firmwareVersion
30 = (((UINT64)gp.firmwareV1) << 32) + gp.firmwareV2;
31
32 // Sign attestation structure. A NULL signature will be returned if
33 // signObject is NULL.
34 return SignAttestInfo(signObject, &in->inScheme, &timeInfo, &in->qualifyingData,
35 &out->timeInfo, &out->signature);
36 }
37 #endif // CC_GetTime
18.8 TPM2_CertifyX509
General Description
The purpose of this command is to generate an X.509 certificate that proves an object with a specific
public key and attributes is loaded in the TPM. In contrast to TPM2_Certify, which uses a TCG-defined
data structure to convey attestation information, TPM2_CertifyX509 encodes the attestation information in
a DER-encoded X.509 certificate that is compliant with RFC5280 Internet X.509 Public Key Infrastructure
Certificate and Certificate Revocation List (CRL) Profile.
As described in RFC, an X.509 certificate contains a collection of data that is hashed and signed. The full
signature is the combination of the to be signed (TBS) data, a description of the signature algorithm, and
the signature over the TBS data. The elements of the TBS data structure are DER-encoded values. They
are:
1) Version [0] – integer value of 2 indicating version 3
2) Certificate Serial Number – integer value
3) Signature Algorithm Identifier – values (usually a collection of OIDs) identifying the algorithm
used for the signature
4) Issuer Name – X.501 type Name to identify the entity that has authorized the use of
signHandle to create the certificate.
5) Validity – two time values indicating the period during which the certificate is valid
6) Subject Name – X.501 type Name that identifies the entity that authorized the use of
objectHandle
7) Subject Public Key Info – the public key associated with objectHandle,
8) Extensions [3] – a set of values that “provide methods for associating additional attributes
with users or public keys and for managin g relationships between CAs.”
NOTE 1: The numbers in square brackets (e.g., [0]) indicate application -specific tag values that are used to
identify the type of the field.
NOTE 2: RFC 5280 describes two fields (issuerUniqueID and subjectUniqueID) but goes o n to say: “CAs
conforming to this profile MUST NOT generate certificates with unique identifiers.” The TPM does
not allow them to be present.
The caller provides a partial certificate (partialCertificate) parameter that contains four or five of the
elements enumerated above in a DER encoded SEQUENCE. They are:
1) Signature Algorithm Identifier (optional)
2) Issuer (mandatory)
3) Validity (mandatory)
4) Subject Name (mandatory)
5) Extensions (mandatory)
The fields are required to be in the order in which they are listed above.
NOTE 3: The TPM determines if the Signature Algorithm Identifier element is present by counting the
elements.
The optional Signature Algorithm Identifier may be provided by the caller. If it is not present, the TPM will
generate the value based on the selected signing scheme. If the caller provides this value, then the TPM
will use it in the completed TBS. The TPM will not validate that the provided values are compatible with
the signing scheme. If the caller does not provide this field and the TPM does not have OID values for the
signing scheme, then the TPM will return an error (TPM_RC_SCHEME).
NOTE 4: The TPM may implement signing schemes for which OIDs are not defined at the time t he TPM was
manufactured. Those schemes may still be used if the caller can provide the Signature Algorithm
Identifier.
The Extensions element is required to contain a Key Usage extension. The TPM will extract the Key
Usage values and verify that the attributes of objectHandle are consistent with the selected values
(TPM_RC_ATTRIBUTES)(See Part 2, TPMA_X509_KEY_USAGE).
The Extensions element may contain a TPMA_OBJECT extension. If present, the TPM will extract the
value and verify that the extension value exactly matches the TPMA_OBJECT of objectKey
(TPM_RC_ATTRIBUTES). The element uses the TCG OID tcg-tpmaObject, 2.23.133.10.1.1.1. It is a
SEQUENCE containing that OID and an OCTET STRING encapsulating a 4-byte BIT STRING holding
the big endian TPMA_OBJECT.
signHandle is required to have the sign attribute SET (TPM_RC_KEY).
NOTE 5: See 18.1 for description of how the signing scheme is selected.
Authorization for objectHandle requires ADMIN role authorization. If performed with a policy session, the
session shall have a policySession→commandCode set to TPM_CC_CertifyX509. This indicates that the
policy that is being used is a policy that is for certification, and not a policy that would approve another
use. That is, authority to use an object does not grant authority to certify the object.
If objectHandle does not have a sensitive area loaded, the TPM will return an error
(TPM_RC_AUTH_UNAVAILABLE).
NOTE 6: The command requires that authorization be provided for use of objectHandle. An object that only
has its publicArea loaded does not have an authorization value and the authPolicy has no meaning
as the sensitive area is not present.
The TPM will create the Version, the Certificate Serial Number, the Subject Public Key Info, and, if not
provided by the caller, the Signature Algorithm Identifier. These TPM-created values will be combined
with the provided values to make a full TBSCerfificate structure (See RFC 5280, clause 4.1). The TPM
will then sign the certificate using the selected signing scheme.
The TPM-created values will be returned in addedToCertificate. If the TPM creates the Signature
Algorithm Identifier, it will be in addedToCertificate before the Subject Public Key Info. The TPM returns
tbsDigest as a debugging aid.
NOTE 7: These returned fields allow the caller to unambiguously create a full RFC5280 -defined
TBSCertificate.
Detailed Actions
1 #include "Tpm.h"
2 #include "CertifyX509_fp.h"
3 #include "X509.h"
4 #include "TpmASN1_fp.h"
5 #include "X509_spt_fp.h"
6 #include "Attest_spt_fp.h"
7 #include "Platform_fp.h"
8 #if CC_CertifyX509 // Conditional expansion of this file
9 TPM_RC
10 TPM2_CertifyX509(
11 CertifyX509_In *in, // IN: input parameter list
12 CertifyX509_Out *out // OUT: output parameter list
13 )
14 {
15 TPM_RC result;
16 OBJECT *signKey = HandleToObject(in->signHandle);
17 OBJECT *object = HandleToObject(in->objectHandle);
18 HASH_STATE hash;
19 INT16 length; // length for a tagged element
20 ASN1UnmarshalContext ctx;
21 ASN1MarshalContext ctxOut;
22 // certTBS holds an array of pointers and lengths. Each entry references the
23 // corresponding value in a TBSCertificate structure. For example, the 1th
24 // element references the version number
25 stringRef certTBS[REF_COUNT] = {{0}};
26 #define ALLOWED_SEQUENCES (SUBJECT_PUBLIC_KEY_REF - SIGNATURE_REF)
27 stringRef partial[ALLOWED_SEQUENCES] = {{0}};
28 INT16 countOfSequences = 0;
29 INT16 i;
30 //
31 #if CERTIFYX509_DEBUG
32 DebugFileOpen();
33 DebugDumpBuffer(in->partialCertificate.t.size, in->partialCertificate.t.buffer,
34 "partialCertificate");
35 #endif
36
37 // Input Validation
38 if(in->reserved.b.size != 0)
39 return TPM_RC_SIZE + RC_CertifyX509_reserved;
40 // signing key must be able to sign
41 if(!IsSigningObject(signKey))
42 return TPM_RCS_KEY + RC_CertifyX509_signHandle;
43 // Pick a scheme for sign. If the input sign scheme is not compatible with
44 // the default scheme, return an error.
45 if(!CryptSelectSignScheme(signKey, &in->inScheme))
46 return TPM_RCS_SCHEME + RC_CertifyX509_inScheme;
47 // Make sure that the public Key encoding is known
48 if(X509AddPublicKey(NULL, object) == 0)
49 return TPM_RCS_ASYMMETRIC + RC_CertifyX509_objectHandle;
50 // Unbundle 'partialCertificate'.
51 // Initialize the unmarshaling context
52 if(!ASN1UnmarshalContextInitialize(&ctx, in->partialCertificate.t.size,
53 in->partialCertificate.t.buffer))
54 return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate;
55 // Make sure that this is a constructed SEQUENCE
56 length = ASN1NextTag(&ctx);
57 // Must be a constructed SEQUENCE that uses all of the input parameter
58 if((ctx.tag != (ASN1_CONSTRUCTED_SEQUENCE))
59 || ((ctx.offset + length) != in->partialCertificate.t.size))
60 return TPM_RCS_SIZE + RC_CertifyX509_partialCertificate;
61
62 // This scans through the contents of the outermost SEQUENCE. This would be the
63 // 'issuer', 'validity', 'subject', 'issuerUniqueID' (optional),
64 // 'subjectUniqueID' (optional), and 'extensions.'
65 while(ctx.offset < ctx.size)
66 {
67 INT16 startOfElement = ctx.offset;
68 //
69 // Read the next tag and length field.
70 length = ASN1NextTag(&ctx);
71 if(length < 0)
72 break;
73 if(ctx.tag == ASN1_CONSTRUCTED_SEQUENCE)
74 {
75 partial[countOfSequences].buf = &ctx.buffer[startOfElement];
76 ctx.offset += length;
77 partial[countOfSequences].len = (INT16)ctx.offset - startOfElement;
78 if(++countOfSequences > ALLOWED_SEQUENCES)
79 break;
80 }
81 else if(ctx.tag == X509_EXTENSIONS)
82 {
83 if(certTBS[EXTENSIONS_REF].len != 0)
84 return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate;
85 certTBS[EXTENSIONS_REF].buf = &ctx.buffer[startOfElement];
86 ctx.offset += length;
87 certTBS[EXTENSIONS_REF].len =
88 (INT16)ctx.offset - startOfElement;
89 }
90 else
91 return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate;
92 }
93 // Make sure that we used all of the data and found at least the required
94 // number of elements.
95 if((ctx.offset != ctx.size) || (countOfSequences < 3)
96 || (countOfSequences > 4)
97 || (certTBS[EXTENSIONS_REF].buf == NULL))
98 return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate;
99 // Now that we know how many sequences there were, we can put them where they
100 // belong
101 for(i = 0; i < countOfSequences; i++)
102 certTBS[SUBJECT_KEY_REF - i] = partial[countOfSequences - 1 - i];
103
104 // If only three SEQUENCES, then the TPM needs to produce the signature algorithm.
105 // See if it can
106 if((countOfSequences == 3) &&
107 (X509AddSigningAlgorithm(NULL, signKey, &in->inScheme) == 0))
108 return TPM_RCS_SCHEME + RC_CertifyX509_signHandle;
109
110 // Process the extensions
19 Ephemeral EC Keys
19.1 Introduction
The TPM generates keys that have different lifetimes. TPM keys in a hierarchy can be persistent for as
long as the seed of the hierarchy is unchanged and these keys may be used multiple times. Other TPM-
generated keys are only useful for a single operation. Some of these single-use keys are used in the
command in which they are created. Examples of this use are TPM2_Duplicate() where an ephemeral
key is created for a single pass key exchange with another TPM. However, there are other cases, such
as anonymous attestation, where the protocol requires two passes where the public part of the ephemeral
key is used outside of the TPM before the final command "consumes" the ephemeral key.
For these uses, TPM2_Commit() or TPM2_EC_Ephemeral() may be used to have the TPM create an
ephemeral EC key and return the public part of the key for external use. Then in a subsequent command,
the caller provides a reference to the ephemeral key so that the TPM can retrieve or recreate the
associated private key.
When an ephemeral EC key is created, it is assigned a number and that number is returned to the caller
as the identifier for the key. This number is not a handle. A handle is assigned to a key that may be
context saved but these ephemeral EC keys may not be saved and do not have a full key context. When
a subsequent command uses the ephemeral key, the caller provides the number of the ephemeral key.
The TPM uses that number to either look up or recompute the associated private key. After the key is
used, the TPM records the fact that the key has been used so that it cannot be used again.
As mentioned, the TPM can keep each assigned private ephemeral key in memory until it is used.
However, this could consume a large amount of memory. To limit the memory size, the TPM is allowed to
restrict the number of pending private keys – keys that have been allocated but not used.
NOTE The minimum number of ephemeral keys is determined by a pla tform specific specification
To further reduce the memory requirements for the ephemeral private keys, the TPM is allowed to use
pseudo-random values for the ephemeral keys. Instead of keeping the full value of the key in memory, the
TPM can use a counter as input to a KDF. Incrementing the counter will cause the TPM to generate a
new pseudo-random value.
Using the counter to generate pseudo-random private ephemeral keys greatly simplifies tracking of key
usage. When a counter value is used to create a key, a bit in an array may be set to indicate that the key
use is pending. When the ephemeral key is consumed, the bit is cleared. This prevents the key from
being used more than once.
Since the TPM is allowed to restrict the number of pending ephemeral keys, the array size can be limited.
For example, a 128 bit array would allow 128 keys to be "pending".
The management of the array is described in greater detail in the Split Operations clause in Annex C of
TPM 2.0 Part 1.
19.2 TPM2_Commit
General Description
TPM2_Commit() performs the first part of an ECC anonymous signing operation. The TPM will perform
the point multiplications on the provided points and return intermediate signing values. The signHandle
parameter shall refer to an ECC key and the signing scheme must be anonymous (TPM_RC_SCHEME).
NOTE 2 This command cannot be used with a sign+decrypt key because that type of key is required to have
a scheme of TPM_ALG_NULL.
For this command, p1, s2 and y2 are optional parameters. If s2 is an Empty Buffer, then the TPM shall
return TPM_RC_SIZE if y2 is not an Empty Buffer.
The algorithm is specified in the TPM 2.0 Part 1 Annex for ECC, TPM2_Commit().
UINT32 commandSize
UINT32 responseSize
TPM_RC responseCode
Detailed Actions
1 #include "Tpm.h"
2 #include "Commit_fp.h"
3 #if CC_Commit // Conditional expansion of this file
4 TPM_RC
5 TPM2_Commit(
6 Commit_In *in, // IN: input parameter list
7 Commit_Out *out // OUT: output parameter list
8 )
9 {
10 OBJECT *eccKey;
11 TPMS_ECC_POINT P2;
12 TPMS_ECC_POINT *pP2 = NULL;
13 TPMS_ECC_POINT *pP1 = NULL;
14 TPM2B_ECC_PARAMETER r;
15 TPM2B_ECC_PARAMETER p;
16 TPM_RC result;
17 TPMS_ECC_PARMS *parms;
18
19 // Input Validation
20
21 eccKey = HandleToObject(in->signHandle);
22 parms = &eccKey->publicArea.parameters.eccDetail;
23
24 // Input key must be an ECC key
25 if(eccKey->publicArea.type != TPM_ALG_ECC)
26 return TPM_RCS_KEY + RC_Commit_signHandle;
27
28 // This command may only be used with a sign-only key using an anonymous
29 // scheme.
30 // NOTE: a sign + decrypt key has no scheme so it will not be an anonymous one
31 // and an unrestricted sign key might no have a signing scheme but it can't
32 // be use in Commit()
33 if(!CryptIsSchemeAnonymous(parms->scheme.scheme))
34 return TPM_RCS_SCHEME + RC_Commit_signHandle;
35
36 // Make sure that both parts of P2 are present if either is present
37 if((in->s2.t.size == 0) != (in->y2.t.size == 0))
38 return TPM_RCS_SIZE + RC_Commit_y2;
39
40 // Get prime modulus for the curve. This is needed later but getting this now
41 // allows confirmation that the curve exists.
42 if(!CryptEccGetParameter(&p, 'p', parms->curveID))
43 return TPM_RCS_KEY + RC_Commit_signHandle;
44
45 // Get the random value that will be used in the point multiplications
19.3 TPM2_EC_Ephemeral
General Description
TPM2_EC_Ephemeral() creates an ephemeral key for use in a two-phase key exchange protocol.
The TPM will use the commit mechanism to assign an ephemeral key r and compute a public point Q ≔
[r]G where G is the generator point associated with curveID.
UINT32 commandSize
UINT32 responseSize
TPM_RC responseCode
Detailed Actions
1 #include "Tpm.h"
2 #include "EC_Ephemeral_fp.h"
3 #if CC_EC_Ephemeral // Conditional expansion of this file
4 TPM_RC
5 TPM2_EC_Ephemeral(
6 EC_Ephemeral_In *in, // IN: input parameter list
7 EC_Ephemeral_Out *out // OUT: output parameter list
8 )
9 {
10 TPM2B_ECC_PARAMETER r;
11 TPM_RC result;
12 //
13 do
14 {
15 // Get the random value that will be used in the point multiplications
16 // Note: this does not commit the count.
17 if(!CryptGenerateR(&r, NULL, in->curveID, NULL))
18 return TPM_RC_NO_RESULT;
19 // do a point multiply
20 result = CryptEccPointMultiply(&out->Q.point, in->curveID, NULL, &r,
21 NULL, NULL);
22 // commit the count value if either the r value results in the point at
23 // infinity or if the value is good. The commit on the r value for infinity
24 // is so that the r value will be skipped.
25 if((result == TPM_RC_SUCCESS) || (result == TPM_RC_NO_RESULT))
26 out->counter = CryptCommit();
27 } while(result == TPM_RC_NO_RESULT);
28
29 return TPM_RC_SUCCESS;
30 }
31 #endif // CC_EC_Ephemeral
20.1 TPM2_VerifySignature
General Description
This command uses loaded keys to validate a signature on a message with the message digest passed
to the TPM.
If the signature check succeeds, then the TPM will produce a TPMT_TK_VERIFIED. Otherwise, the TPM
shall return TPM_RC_SIGNATURE.
If the key is in the NULL hierarchy, then digest in the ticket will be the Empty Buffer.
NOTE 1 A valid ticket may be used in subsequent commands to provide proof to the TPM that the TPM has
validated the signature over the message using the key referenced by keyHandle.
If keyHandle references an asymmetric key, only the public portion of the key needs to be loaded. If
keyHandle references a symmetric key, both the public and private portions need to be loaded.
NOTE 2 The sensitive area of the symmetric object is required to allow verification of the symmetric
signature (the HMAC).
TPMT_TK_VERIFIED validation
Detailed Actions
1 #include "Tpm.h"
2 #include "VerifySignature_fp.h"
3 #if CC_VerifySignature // Conditional expansion of this file
4 TPM_RC
5 TPM2_VerifySignature(
6 VerifySignature_In *in, // IN: input parameter list
7 VerifySignature_Out *out // OUT: output parameter list
8 )
9 {
10 TPM_RC result;
11 OBJECT *signObject = HandleToObject(in->keyHandle);
12 TPMI_RH_HIERARCHY hierarchy;
13
14 // Input Validation
15 // The object to validate the signature must be a signing key.
16 if(!IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, sign))
17 return TPM_RCS_ATTRIBUTES + RC_VerifySignature_keyHandle;
18
19 // Validate Signature. TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE
20 // error may be returned by CryptCVerifySignatrue()
21 result = CryptValidateSignature(in->keyHandle, &in->digest, &in->signature);
22 if(result != TPM_RC_SUCCESS)
23 return RcSafeAddToResult(result, RC_VerifySignature_signature);
24
25 // Command Output
26
27 hierarchy = GetHeriarchy(in->keyHandle);
28 if(hierarchy == TPM_RH_NULL
29 || signObject->publicArea.nameAlg == TPM_ALG_NULL)
30 {
31 // produce empty ticket if hierarchy is TPM_RH_NULL or nameAlg is
32 // TPM_ALG_NULL
33 out->validation.tag = TPM_ST_VERIFIED;
34 out->validation.hierarchy = TPM_RH_NULL;
35 out->validation.digest.t.size = 0;
36 }
37 else
38 {
39 // Compute ticket
40 TicketComputeVerified(hierarchy, &in->digest, &signObject->name,
41 &out->validation);
42 }
43
44 return TPM_RC_SUCCESS;
45 }
46 #endif // CC_VerifySignature
20.2 TPM2_Sign
General Description
This command causes the TPM to sign an externally provided hash with the specified symmetric or
asymmetric signing key.
NOTE 1 If keyhandle references an unrestricted signing key, a digest can be signed using either this
command or an HMAC command.
If keyHandle references a restricted signing key, then validation shall be provided, indicating that the TPM
performed the hash of the data and validation shall indicate that hashed data did not start with
TPM_GENERATED_VALUE.
NOTE 2 If the hashed data did start with TPM_GENERATED_VALUE, then the validation will be a NULL
ticket.
NOTE 3 When the signing scheme uses a hash algorithm, the algorithm is defined in the qualifying data of
the scheme. This is the same algorithm that is required to be used in producing digest. The size of
digest must match that of the hash algorithm in the scheme.
If inScheme is not a valid signing scheme for the type of keyHandle (or TPM_ALG_NULL), then the TPM
shall return TPM_RC_SCHEME.
If the scheme of keyHandle is an anonymous scheme, then inScheme shall have the same scheme
algorithm as keyHandle and inScheme will contain a counter value that will be used in the signing
process.
EXAMPLE For ECDAA, inScheme.details.ecdaa.count will contain the count value.
If validation is provided, then the hash algorithm used in computing the digest is required to be the hash
algorithm specified in the scheme of keyHandle (TPM_RC_TICKET).
If the validation parameter is not the Empty Buffer, then it will be checked even if the key referenced by
keyHandle is not a restricted signing key.
NOTE 4 If keyHandle is both a sign and decrypt key, keyHandle will have a scheme of TPM_ALG_NULL. If
validation is provided, then it must be a NULL validation ticket or the ticket validation will fail.
Detailed Actions
1 #include "Tpm.h"
2 #include "Sign_fp.h"
3 #if CC_Sign // Conditional expansion of this file
4 #include "Attest_spt_fp.h"
5 TPM_RC
6 TPM2_Sign(
7 Sign_In *in, // IN: input parameter list
8 Sign_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result;
12 TPMT_TK_HASHCHECK ticket;
13 OBJECT *signObject = HandleToObject(in->keyHandle);
14 //
15 // Input Validation
16 if(!IsSigningObject(signObject))
17 return TPM_RCS_KEY + RC_Sign_keyHandle;
18
19 // A key that will be used for x.509 signatures can't be used in TPM2_Sign().
20 if(IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, x509sign))
21 return TPM_RCS_ATTRIBUTES + RC_Sign_keyHandle;
22
23 // pick a scheme for sign. If the input sign scheme is not compatible with
24 // the default scheme, return an error.
25 if(!CryptSelectSignScheme(signObject, &in->inScheme))
26 return TPM_RCS_SCHEME + RC_Sign_inScheme;
27
28 // If validation is provided, or the key is restricted, check the ticket
29 if(in->validation.digest.t.size != 0
30 || IS_ATTRIBUTE(signObject->publicArea.objectAttributes,
31 TPMA_OBJECT, restricted))
32 {
33 // Compute and compare ticket
34 TicketComputeHashCheck(in->validation.hierarchy,
35 in->inScheme.details.any.hashAlg,
36 &in->digest, &ticket);
37
38 if(!MemoryEqual2B(&in->validation.digest.b, &ticket.digest.b))
39 return TPM_RCS_TICKET + RC_Sign_validation;
40 }
41 else
42 // If we don't have a ticket, at least verify that the provided 'digest'
43 // is the size of the scheme hashAlg digest.
44 // NOTE: this does not guarantee that the 'digest' is actually produced using
45 // the indicated hash algorithm, but at least it might be.
46 {
47 if(in->digest.t.size
48 != CryptHashGetDigestSize(in->inScheme.details.any.hashAlg))
49 return TPM_RCS_SIZE + RC_Sign_digest;
50 }
51
52 // Command Output
53 // Sign the hash. A TPM_RC_VALUE or TPM_RC_SCHEME
54 // error may be returned at this point
55 result = CryptSign(signObject, &in->inScheme, &in->digest, &out->signature);
56
57 return result;
58 }
59 #endif // CC_Sign
21 Command Audit
21.1 Introduction
If a command has been selected for command audit, the command audit status will be updated when that
command completes successfully. The digest is updated as:
commandAuditDigestnew ≔ HauditAlg(commandAuditDigestold || cpHash || rpHash) (5)
where
HauditAlg hash function using the algorithm of the audit sequence
commandAuditDigest accumulated digest
cpHash the command parameter hash
rpHash the response parameter hash
TPM2_Shutdown() cannot be audited but TPM2_Startup() can be audited. If the cpHash of the
TPM2_Startup() is TPM_SU_STATE, that would indicate that a TPM2_Shutdown() had been successfully
executed.
TPM2_SetCommandCodeAuditStatus() is always audited, except when it is used to change auditAlg.
If the TPM is in Failure mode, command audit is not functional.
21.2 TPM2_SetCommandCodeAuditStatus
General Description
This command may be used by the Privacy Administrator or platform to change the audit status of a
command or to set the hash algorithm used for the audit digest, but not both at the same time.
If the auditAlg parameter is a supported hash algorithm and not the same as the current algorithm, then
the TPM will check both setList and clearList are empty (zero length). If so, then the algorithm is changed,
and the audit digest is cleared. If auditAlg is TPM_ALG_NULL or the same as the current algorithm, then
the algorithm and audit digest are unchanged and the setList and clearList will be processed.
NOTE 1 Because the audit digest is cleared, the audit counter will increment the next time that an audited
command is executed.
NOTE 2 Use of this command to change the audit hash algorit hm is not audited and the digest is reset when
the command completes. The change in the audit hash algorithm is the evidence that this command
was used to change the algorithm.
The commands in setList indicate the commands to be added to the list of audited commands and the
commands in clearList indicate the commands that will no longer be audited. It is not an error if a
command in setList is already audited or is not implemented. It is not an error if a command in clearList is
not currently being audited or is not implemented.
If a command code is in both setList and clearList, then it will not be audited (that is, setList shall be
processed first).
TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
TPMI_RH_PROVISION @auth Auth Index: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "SetCommandCodeAuditStatus_fp.h"
3 #if CC_SetCommandCodeAuditStatus // Conditional expansion of this file
4 TPM_RC
5 TPM2_SetCommandCodeAuditStatus(
6 SetCommandCodeAuditStatus_In *in // IN: input parameter list
7 )
8 {
9
10 // The command needs NV update. Check if NV is available.
11 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
12 // this point
13 RETURN_IF_NV_IS_NOT_AVAILABLE;
14
15 // Internal Data Update
16
17 // Update hash algorithm
18 if(in->auditAlg != TPM_ALG_NULL && in->auditAlg != gp.auditHashAlg)
19 {
20 // Can't change the algorithm and command list at the same time
21 if(in->setList.count != 0 || in->clearList.count != 0)
22 return TPM_RCS_VALUE + RC_SetCommandCodeAuditStatus_auditAlg;
23
24 // Change the hash algorithm for audit
25 gp.auditHashAlg = in->auditAlg;
26
27 // Set the digest size to a unique value that indicates that the digest
28 // algorithm has been changed. The size will be cleared to zero in the
29 // command audit processing on exit.
30 gr.commandAuditDigest.t.size = 1;
31
32 // Save the change of command audit data (this sets g_updateNV so that NV
33 // will be updated on exit.)
34 NV_SYNC_PERSISTENT(auditHashAlg);
35 }
36 else
37 {
38 UINT32 i;
39 BOOL changed = FALSE;
40
41 // Process set list
42 for(i = 0; i < in->setList.count; i++)
43
44 // If change is made in CommandAuditSet, set changed flag
45 if(CommandAuditSet(in->setList.commandCodes[i]))
46 changed = TRUE;
47
48 // Process clear list
49 for(i = 0; i < in->clearList.count; i++)
50 // If change is made in CommandAuditClear, set changed flag
51 if(CommandAuditClear(in->clearList.commandCodes[i]))
52 changed = TRUE;
53
54 // if change was made to command list, update NV
55 if(changed)
56 // this sets g_updateNV so that NV will be updated on exit.
57 NV_SYNC_PERSISTENT(auditCommands);
58 }
59
60 return TPM_RC_SUCCESS;
61 }
62 #endif // CC_SetCommandCodeAuditStatus
22.1 Introduction
In TPM 1.2, an Event was hashed using SHA-1 and then the 20-octet digest was extended to a PCR
using TPM_Extend(). This specification allows the use of multiple PCR at a given Index, each using a
different hash algorithm. Rather than require that the external software generate multiple hashes of the
Event with each being extended to a different PCR, the Event data may be sent to the TPM for hashing.
This ensures that the resulting digests will properly reflect the algorithms chosen for the PCR even if the
calling software is unable to implement the hash algorithm.
NOTE 1 There is continued support for software hashing of events with TPM2_PCR_Extend().
To support recording of an Event that is larger than the TPM input buffer, the caller may use the
command sequence described in clause 1.
Change to a PCR requires authorization. The authorization may be with either an authorization value or
an authorization policy. The platform-specific specifications determine which PCR may be controlled by
policy. All other PCR are controlled by authorization.
If a PCR may be associated with a policy, then the algorithm ID of that policy determines whether the
policy is to be applied. If the algorithm ID is not TPM_ALG_NULL, then the policy digest associated with
the PCR must match the policySession→policyDigest in a policy session. If the algorithm ID is
TPM_ALG_NULL, then no policy is present and the authorization requires an EmptyAuth.
If a platform-specific specification indicates that PCR are grouped, then all the PCR in the group use the
same authorization policy or authorization value.
pcrUpdateCounter counter will be incremented on the successful completion of any command that
modifies (Extends or resets) a PCR unless the platform-specific specification explicitly excludes the PCR
from being counted.
NOTE 2 If a command causes PCR in multiple banks to change, the PCR Update Counter m ust be
incremented once for each bank. The commands that extend PCR are: TPM2_PCR_Extend,
TPM2_PCR_Event, and TPM2_EventSequenceComplete.
If a command resets PCR in multiple banks, the PCR Update Counter must be incremented only
once. The commands that reset PCR are: TPM2_PCR_Reset, and TPM2_Startup.
A platform-specific specification may designate a set of PCR that are under control of the TCB. These
PCR may not be modified without the proper authorization. Updates of these PCR shall not cause the
PCR Update Counter to increment.
EXAMPLE Updates of the TCB PCR will not cause the PCR update counter to increment beca use these PCR
are changed at the whim of the TCB and may not represent the trust state of the platform.
22.2 TPM2_PCR_Extend
General Description
This command is used to cause an update to the indicated PCR. The digests parameter contains one or
more tagged digest values identified by an algorithm ID. For each digest, the PCR associated with
pcrHandle is Extended into the bank identified by the tag (hashAlg).
EXAMPLE A SHA1 digest would be Extended into the SHA1 bank and a SHA256 digest would be Extended into
the SHA256 bank.
For each list entry, the TPM will check to see if pcrNum is implemented for that algorithm. If so, the TPM
shall perform the following operation:
PCR.digestnew [pcrNum][alg] ≔ Halg(PCR.digestold [pcrNum][alg] || data[alg].buffer)) (6)
where
Halg() hash function using the hash algorithm associated with the PCR
instance
PCR.digest the digest value in a PCR
pcrNum the PCR numeric selector (pcrHandle)
alg the PCR algorithm selector for the digest
data[alg].buffer the bank-specific data to be extended
If no digest value is specified for a bank, then the PCR in that bank is not modified.
NOTE 1 This allows consistent operation of the digests list for all of the Event recording commands.
If a digest is present and the PCR in that bank is not implemented, the digest value is not used.
NOTE 2 If the caller includes digests for algorithms that are not implemented, then the TPM will fail the call
because the unmarshalling of digests will fail. Each of the entries in the list is a TPMT_HA, which is
a hash algorithm followed by a digest. If the algorithm is not implemented, unmarshalling of the
hashAlg will fail and the TPM will return TPM_RC_HASH.
If the TPM unmarshals the hashAlg of a list entry and the unmarshaled value is not a hash algorithm
implemented on the TPM, the TPM shall return TPM_RC_HASH.
The pcrHandle parameter is allowed to reference TPM_RH_NULL. If so, the input parameters are
processed but no action is taken by the TPM. This permits the caller to probe for implemented hash
algorithms as an alternative to TPM2_GetCapability.
NOTE 3 This command allows a list of digests so that PCR in all banks may be updated in a single
command. While the semantics of this command allow multiple extends to a single PCR bank, this is
not the preferred use and the limit on the number of entries in the list make this use somewhat
impractical.
Detailed Actions
1 #include "Tpm.h"
2 #include "PCR_Extend_fp.h"
3 #if CC_PCR_Extend // Conditional expansion of this file
4 TPM_RC
5 TPM2_PCR_Extend(
6 PCR_Extend_In *in // IN: input parameter list
7 )
8 {
9 UINT32 i;
10
11 // Input Validation
12
13 // NOTE: This function assumes that the unmarshaling function for 'digests' will
14 // have validated that all of the indicated hash algorithms are valid. If the
15 // hash algorithms are correct, the unmarshaling code will unmarshal a digest
16 // of the size indicated by the hash algorithm. If the overall size is not
17 // consistent, the unmarshaling code will run out of input data or have input
18 // data left over. In either case, it will cause an unmarshaling error and this
19 // function will not be called.
20
21 // For NULL handle, do nothing and return success
22 if(in->pcrHandle == TPM_RH_NULL)
23 return TPM_RC_SUCCESS;
24
25 // Check if the extend operation is allowed by the current command locality
26 if(!PCRIsExtendAllowed(in->pcrHandle))
27 return TPM_RC_LOCALITY;
28
29 // If PCR is state saved and we need to update orderlyState, check NV
30 // availability
31 if(PCRIsStateSaved(in->pcrHandle))
32 RETURN_IF_ORDERLY;
33
34 // Internal Data Update
35
36 // Iterate input digest list to extend
37 for(i = 0; i < in->digests.count; i++)
38 {
39 PCRExtend(in->pcrHandle, in->digests.digests[i].hashAlg,
40 CryptHashGetDigestSize(in->digests.digests[i].hashAlg),
41 (BYTE *)&in->digests.digests[i].digest);
42 }
43
44 return TPM_RC_SUCCESS;
45 }
46 #endif // CC_PCR_Extend
22.3 TPM2_PCR_Event
General Description
EXAMPLE 1 If the command implements PCR[2] in a SHA1 bank and a SHA256 bank, then an extend to PCR[2]
will cause eventData to be hashed twice, once with SHA1 and once with SHA256. The SHA1 hash of
eventData will be Extended to PCR[2] in the SHA1 bank and the SHA256 hash of eventData will be
Extended to PCR[2] of the SHA256 bank.
On successful command completion, digests will contain the list of tagged digests of eventData that was
computed in preparation for extending the data into the PCR. At the option of the TPM, the list may
contain a digest for each bank, or it may only contain a digest for each bank in which pcrHandle is extant.
If pcrHandle is TPM_RH_NULL, the TPM may return either an empty list or a digest for each bank.
EXAMPLE 2 Assume a TPM that implements a SHA1 bank and a SHA256 bank and that PCR[22] is only
implemented in the SHA1 bank. If pcrHandle references PCR[22], then digests may contain either a
SHA1 and a SHA256 digest or just a SHA1 digest.
TPML_DIGEST_VALUES digests
Detailed Actions
1 #include "Tpm.h"
2 #include "PCR_Event_fp.h"
3 #if CC_PCR_Event // Conditional expansion of this file
4 TPM_RC
5 TPM2_PCR_Event(
6 PCR_Event_In *in, // IN: input parameter list
7 PCR_Event_Out *out // OUT: output parameter list
8 )
9 {
10 HASH_STATE hashState;
11 UINT32 i;
12 UINT16 size;
13
14 // Input Validation
15
16 // If a PCR extend is required
17 if(in->pcrHandle != TPM_RH_NULL)
18 {
19 // If the PCR is not allow to extend, return error
20 if(!PCRIsExtendAllowed(in->pcrHandle))
21 return TPM_RC_LOCALITY;
22
23 // If PCR is state saved and we need to update orderlyState, check NV
24 // availability
25 if(PCRIsStateSaved(in->pcrHandle))
26 RETURN_IF_ORDERLY;
27 }
28
29 // Internal Data Update
30
31 out->digests.count = HASH_COUNT;
32
33 // Iterate supported PCR bank algorithms to extend
34 for(i = 0; i < HASH_COUNT; i++)
35 {
36 TPM_ALG_ID hash = CryptHashGetAlgByIndex(i);
37 out->digests.digests[i].hashAlg = hash;
38 size = CryptHashStart(&hashState, hash);
39 CryptDigestUpdate2B(&hashState, &in->eventData.b);
40 CryptHashEnd(&hashState, size,
41 (BYTE *)&out->digests.digests[i].digest);
42 if(in->pcrHandle != TPM_RH_NULL)
43 PCRExtend(in->pcrHandle, hash, size,
44 (BYTE *)&out->digests.digests[i].digest);
45 }
46
47 return TPM_RC_SUCCESS;
48 }
49 #endif // CC_PCR_Event
22.4 TPM2_PCR_Read
General Description
NOTE If no PCR are returned from a bank, the selector for the bank will be present in pcrSelectionOut.
No authorization is required to read a PCR and any implemented PCR may be read from any locality.
Detailed Actions
1 #include "Tpm.h"
2 #include "PCR_Read_fp.h"
3 #if CC_PCR_Read // Conditional expansion of this file
4 TPM_RC
5 TPM2_PCR_Read(
6 PCR_Read_In *in, // IN: input parameter list
7 PCR_Read_Out *out // OUT: output parameter list
8 )
9 {
10 // Command Output
11
12 // Call PCR read function. input pcrSelectionIn parameter could be changed
13 // to reflect the actual PCR being returned
14 PCRRead(&in->pcrSelectionIn, &out->pcrValues, &out->pcrUpdateCounter);
15
16 out->pcrSelectionOut = in->pcrSelectionIn;
17
18 return TPM_RC_SUCCESS;
19 }
20 #endif // CC_PCR_Read
22.5 TPM2_PCR_Allocate
General Description
This command is used to set the desired PCR allocation of PCR and algorithms. This command requires
Platform Authorization.
The TPM will evaluate the request and, if sufficient memory is available for the requested allocation, the
TPM will store the allocation request for use during the next _TPM_Init operation. The PCR allocation in
place when this command is executed will be retained until the next _TPM_Init. If this command is
received multiple times before a _TPM_Init, each one overwrites the previous stored allocation.
This command will only change the allocations of banks that are listed in pcrAllocation.
EXAMPLE 1 If a TPM supports SHA1 and SHA256, then it maintains a n allocation for two banks (one of which
could be empty). If pcrAllocation only has a selector for the SHA1 bank, then only the allocation of
the SHA1 bank will be changed and the SHA256 bank will remain unchanged. To change the
allocation of a TPM from 24 SHA1 PCR and no SHA256 PCR to 24 SHA256 PCR and no SHA1 PCR,
the pcrAllocation would have to have two selections: one for the empty SHA1 bank and one for the
SHA256 bank with 24 PCR.
If a bank is listed more than once, then the last selection in the pcrAllocation list is the one that the TPM
will attempt to allocate.
NOTE 1 This does not mean to imply that pcrAllocation.count can exceed HASH_COUNT, the number of
digests implemented in the TPM.
EXAMPLE 2 If HASH_COUNT is 2, pcrAllocation can specify SHA-256 twice, and the second one is used.
However, if SHA_256 is specified three times, the unmarshaling may fail and the TPM may return an
error.
This command shall not allocate more PCR in any bank than there are PCR attribute definitions. The
PCR attribute definitions indicate how a PCR is to be managed – if it is resettable, the locality for update,
etc. In the response to this command, the TPM returns the maximum number of PCR allowed for any
bank.
When PCR are allocated, if DRTM_PCR is defined, the resulting allocation must have at least one bank
with the D-RTM PCR allocated. If HCRTM_PCR is defined, the resulting allocation must have at least one
bank with the HCRTM_PCR allocated. If not, the TPM returns TPM_RC_PCR.
The TPM may return TPM_RC_SUCCESS even though the request fails. This is to allow the TPM to
return information about the size needed for the requested allocation and the size available. If the
sizeNeeded parameter in the return is less than or equal to the sizeAvailable parameter, then the
allocationSuccess parameter will be YES. Alternatively, if the request fails, The TPM may return
TPM_RC_NO_RESULT.
NOTE 2 An example for this type of failure is a TPM that can only support one bank at a time and cannot
support arbitrary distribution of PCR among banks.
After this command, TPM2_Shutdown() is only allowed to have a startupType equal to TPM_SU_CLEAR
until after the next _TPM_Init.
NOTE 3 Even if this command does not cause the PCR allocation to change, the T PM cannot have its state
saved. This is done in order to simplify the implementation. There is no need to optimize this
command as it is not expected to be used more than once in the lifetime of the TPM (it can be used
any number of times but there is no justification for optimization).
TPM_RH_PLATFORM+{PP}
TPMI_RH_PLATFORM @authHandle Auth Index: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "PCR_Allocate_fp.h"
3 #if CC_PCR_Allocate // Conditional expansion of this file
4 TPM_RC
5 TPM2_PCR_Allocate(
6 PCR_Allocate_In *in, // IN: input parameter list
7 PCR_Allocate_Out *out // OUT: output parameter list
8 )
9 {
10 TPM_RC result;
11
12 // The command needs NV update. Check if NV is available.
13 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
14 // this point.
15 // Note: These codes are not listed in the return values above because it is
16 // an implementation choice to check in this routine rather than in a common
17 // function that is called before these actions are called. These return values
18 // are described in the Response Code section of Part 3.
19 RETURN_IF_NV_IS_NOT_AVAILABLE;
20
21 // Command Output
22
23 // Call PCR Allocation function.
24 result = PCRAllocate(&in->pcrAllocation, &out->maxPCR,
25 &out->sizeNeeded, &out->sizeAvailable);
26 if(result == TPM_RC_PCR)
27 return result;
28
29 //
30 out->allocationSuccess = (result == TPM_RC_SUCCESS);
31
32 // if re-configuration succeeds, set the flag to indicate PCR configuration is
33 // going to be changed in next boot
34 if(out->allocationSuccess == YES)
35 g_pcrReConfig = TRUE;
36
37 return TPM_RC_SUCCESS;
38 }
39 #endif // CC_PCR_Allocate
22.6 TPM2_PCR_SetAuthPolicy
General Description
This command is used to associate a policy with a PCR or group of PCR. The policy determines the
conditions under which a PCR may be extended or reset.
A policy may only be associated with a PCR that has been defined by a platform-specific specification as
allowing a policy. If the TPM implementation does not allow a policy for pcrNum, the TPM shall return
TPM_RC_VALUE.
A platform-specific specification may group PCR so that they share a common policy. In such case, a
pcrNum that selects any of the PCR in the group will change the policy for all PCR in the group.
The policy setting is persistent and may only be changed by TPM2_PCR_SetAuthPolicy() or by
TPM2_ChangePPS().
Before this command is first executed on a TPM or after TPM2_ChangePPS(), the access control on the
PCR will be set to the default value defined in the platform-specific specification.
NOTE 1 It is expected that the typical default will be with the policy hash set to TPM_ALG_NULL and an
Empty Buffer for the authPolicy value. This will allow an EmptyAuth to be used as the authorization
value.
If the size of the data buffer in authPolicy is not the size of a digest produced by hashAlg, the TPM shall
return TPM_RC_SIZE.
NOTE 3 If the PCR is in multiple policy sets, the policy will be change d in only one set. The set that is
changed will be implementation dependent.
TPM_RH_PLATFORM+{PP}
TPMI_RH_PLATFORM @authHandle Auth Index: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "PCR_SetAuthPolicy_fp.h"
3 #if CC_PCR_SetAuthPolicy // Conditional expansion of this file
4 TPM_RC
5 TPM2_PCR_SetAuthPolicy(
6 PCR_SetAuthPolicy_In *in // IN: input parameter list
7 )
8 {
9 UINT32 groupIndex;
10
11 // The command needs NV update. Check if NV is available.
12 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
13 // this point
14 RETURN_IF_NV_IS_NOT_AVAILABLE;
15
16 // Input Validation:
17
18 // Check the authPolicy consistent with hash algorithm
19 if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg))
20 return TPM_RCS_SIZE + RC_PCR_SetAuthPolicy_authPolicy;
21
22 // If PCR does not belong to a policy group, return TPM_RC_VALUE
23 if(!PCRBelongsPolicyGroup(in->pcrNum, &groupIndex))
24 return TPM_RCS_VALUE + RC_PCR_SetAuthPolicy_pcrNum;
25
26 // Internal Data Update
27
28 // Set PCR policy
29 gp.pcrPolicies.hashAlg[groupIndex] = in->hashAlg;
30 gp.pcrPolicies.policy[groupIndex] = in->authPolicy;
31
32 // Save new policy to NV
33 NV_SYNC_PERSISTENT(pcrPolicies);
34
35 return TPM_RC_SUCCESS;
36 }
37 #endif // CC_PCR_SetAuthPolicy
22.7 TPM2_PCR_SetAuthValue
General Description
Detailed Actions
1 #include "Tpm.h"
2 #include "PCR_SetAuthValue_fp.h"
3 #if CC_PCR_SetAuthValue // Conditional expansion of this file
4 TPM_RC
5 TPM2_PCR_SetAuthValue(
6 PCR_SetAuthValue_In *in // IN: input parameter list
7 )
8 {
9 UINT32 groupIndex;
10 // Input Validation:
11
12 // If PCR does not belong to an auth group, return TPM_RC_VALUE
13 if(!PCRBelongsAuthGroup(in->pcrHandle, &groupIndex))
14 return TPM_RC_VALUE;
15
16 // The command may cause the orderlyState to be cleared due to the update of
17 // state clear data. If this is the case, Check if NV is available.
18 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
19 // this point
20 RETURN_IF_ORDERLY;
21
22 // Internal Data Update
23
24 // Set PCR authValue
25 MemoryRemoveTrailingZeros(&in->auth);
26 gc.pcrAuthValues.auth[groupIndex] = in->auth;
27
28 return TPM_RC_SUCCESS;
29 }
30 #endif // CC_PCR_SetAuthValue
22.8 TPM2_PCR_Reset
General Description
If the attribute of a PCR allows the PCR to be reset and proper authorization is provided, then this
command may be used to set the PCR in all banks to zero. The attributes of the PCR may restrict the
locality that can perform the reset operation.
NOTE 1 The definition of TPMI_DH_PCR in TPM 2.0 Part 2 indicates that if pcrHandle is out of the allowed
range for PCR, then the appropriate return value is TPM_RC_VALUE.
If pcrHandle references a PCR that cannot be reset, the TPM shall return TPM_RC_LOCALITY.
NOTE 2 TPM_RC_LOCALITY is returned because the reset attributes are defined on a per -locality basis.
Detailed Actions
1 #include "Tpm.h"
2 #include "PCR_Reset_fp.h"
3 #if CC_PCR_Reset // Conditional expansion of this file
4 TPM_RC
5 TPM2_PCR_Reset(
6 PCR_Reset_In *in // IN: input parameter list
7 )
8 {
9 // Input Validation
10
11 // Check if the reset operation is allowed by the current command locality
12 if(!PCRIsResetAllowed(in->pcrHandle))
13 return TPM_RC_LOCALITY;
14
15 // If PCR is state saved and we need to update orderlyState, check NV
16 // availability
17 if(PCRIsStateSaved(in->pcrHandle))
18 RETURN_IF_ORDERLY;
19
20 // Internal Data Update
21
22 // Reset selected PCR in all banks to 0
23 PCRSetValue(in->pcrHandle, 0);
24
25 // Indicate that the PCR changed so that pcrCounter will be incremented if
26 // necessary.
27 PCRChanged(in->pcrHandle);
28
29 return TPM_RC_SUCCESS;
30 }
31 #endif // CC_PCR_Reset
22.9 _TPM_Hash_Start
Description
This indication from the TPM interface indicates the start of an H-CRTM measurement sequence. On
receipt of this indication, the TPM will initialize an H-CRTM Event Sequence context.
If no object memory is available for creation of the sequence context, the TPM will flush the context of an
object so that creation of the sequence context will always succeed.
A platform-specific specification may allow this indication before TPM2_Startup().
NOTE If this indication occurs after TPM2_Startup(), it is the responsibility of software to ensure that an
object context slot is available or to deal with the consequences of having the TPM sel ect an
arbitrary object to be flushed. If this indication occurs before TPM2_Startup() then all context slots
are available.
Detailed Actions
1 #include "Tpm.h"
2 LIB_EXPORT void
3 _TPM_Hash_Start(
4 void
5 )
6 {
7 TPM_RC result;
8 TPMI_DH_OBJECT handle;
9
10 // If a DRTM sequence object exists, free it up
11 if(g_DRTMHandle != TPM_RH_UNASSIGNED)
12 {
13 FlushObject(g_DRTMHandle);
14 g_DRTMHandle = TPM_RH_UNASSIGNED;
15 }
16
17 // Create an event sequence object and store the handle in global
18 // g_DRTMHandle. A TPM_RC_OBJECT_MEMORY error may be returned at this point
19 // The NULL value for the first parameter will cause the sequence structure to
20 // be allocated without being set as present. This keeps the sequence from
21 // being left behind if the sequence is terminated early.
22 result = ObjectCreateEventSequence(NULL, &g_DRTMHandle);
23
24 // If a free slot was not available, then free up a slot.
25 if(result != TPM_RC_SUCCESS)
26 {
27 // An implementation does not need to have a fixed relationship between
28 // slot numbers and handle numbers. To handle the general case, scan for
29 // a handle that is assigned and free it for the DRTM sequence.
30 // In the reference implementation, the relationship between handles and
31 // slots is fixed. So, if the call to ObjectCreateEvenSequence()
32 // failed indicating that all slots are occupied, then the first handle we
33 // are going to check (TRANSIENT_FIRST) will be occupied. It will be freed
34 // so that it can be assigned for use as the DRTM sequence object.
35 for(handle = TRANSIENT_FIRST; handle < TRANSIENT_LAST; handle++)
36 {
37 // try to flush the first object
38 if(IsObjectPresent(handle))
39 break;
40 }
41 // If the first call to find a slot fails but none of the slots is occupied
42 // then there's a big problem
43 pAssert(handle < TRANSIENT_LAST);
44
45 // Free the slot
46 FlushObject(handle);
47
48 // Try to create an event sequence object again. This time, we must
49 // succeed.
50 result = ObjectCreateEventSequence(NULL, &g_DRTMHandle);
51 if(result != TPM_RC_SUCCESS)
52 FAIL(FATAL_ERROR_INTERNAL);
53 }
54
55 return;
56 }
22.10 _TPM_Hash_Data
Description
This indication from the TPM interface indicates arrival of one or more octets of data that are to be
included in the H-CRTM Event Sequence sequence context created by the _TPM_Hash_Start indication.
The context holds data for each hash algorithm for each PCR bank implemented on the TPM.
If no H-CRTM Event Sequence context exists, this indication is discarded and no other action is
performed.
Detailed Actions
1 #include "Tpm.h"
2 LIB_EXPORT void
3 _TPM_Hash_Data(
4 uint32_t dataSize, // IN: size of data to be extend
5 unsigned char *data // IN: data buffer
6 )
7 {
8 UINT32 i;
9 HASH_OBJECT *hashObject;
10 TPMI_DH_PCR pcrHandle = TPMIsStarted()
11 ? PCR_FIRST + DRTM_PCR : PCR_FIRST + HCRTM_PCR;
12
13 // If there is no DRTM sequence object, then _TPM_Hash_Start
14 // was not called so this function returns without doing
15 // anything.
16 if(g_DRTMHandle == TPM_RH_UNASSIGNED)
17 return;
18
19 hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle);
20 pAssert(hashObject->attributes.eventSeq);
21
22 // For each of the implemented hash algorithms, update the digest with the
23 // data provided.
24 for(i = 0; i < HASH_COUNT; i++)
25 {
26 // make sure that the PCR is implemented for this algorithm
27 if(PcrIsAllocated(pcrHandle,
28 hashObject->state.hashState[i].hashAlg))
29 // Update sequence object
30 CryptDigestUpdate(&hashObject->state.hashState[i], dataSize, data);
31 }
32
33 return;
34 }
22.11 _TPM_Hash_End
Description
This indication from the TPM interface indicates the end of the H-CRTM measurement. This indication is
discarded and no other action performed if the TPM does not contain an H-CRTM Event Sequence
context.
If the H-CRTM Event Sequence occurs after TPM2_Startup(), the TPM will set all of the PCR designated
in the platform-specific specifications as resettable by this event to the value indicated in the platform
specific specification and increment restartCount. The TPM will then Extend the Event Sequence
digest/digests into the designated D-RTM PCR (PCR[17]).
PCR[17][hashAlg] ≔ HhashAlg (initial_value || HhashAlg (hash_data)) (7)
where
hashAlg hash algorithm associated with a bank of PCR
initial_value initialization value specified in the platform-specific specification
(should be 0…0)
hash_data all the octets of data received in _TPM_Hash_Data indications
A _TPM_Hash_End indication that occurs after TPM2_Startup() will increment pcrUpdateCounter unless
a platform-specific specification excludes modifications of PCR[DRTM] from causing an increment.
A platform-specific specification may allow an H-CRTM Event Sequence before TPM2_Startup(). If so,
_TPM_Hash_End will complete the digest, initialize PCR[0] with a digest-size value of 4, and then extend
the H-CRTM Event Sequence data into PCR[0].
PCR[0][hashAlg] ≔ HhashAlg (0…04 || HhashAlg (hash_data)) (8)
NOTE 2 The entire sequence of _TPM_Hash_Start, _TPM_Hash_Data, and _TPM_Hash_End are required to
complete before TPM2_Startup() or the sequence will have no effect on the TPM.
NOTE 3 PCR[0] does not need to be updated according to (8) until the end of TPM2_Startup().
Detailed Actions
1 #include "Tpm.h"
2 LIB_EXPORT void
3 _TPM_Hash_End(
4 void
5 )
6 {
7 UINT32 i;
8 TPM2B_DIGEST digest;
9 HASH_OBJECT *hashObject;
10 TPMI_DH_PCR pcrHandle;
11
12 // If the DRTM handle is not being used, then either _TPM_Hash_Start has not
13 // been called, _TPM_Hash_End was previously called, or some other command
14 // was executed and the sequence was aborted.
15 if(g_DRTMHandle == TPM_RH_UNASSIGNED)
16 return;
17
18 // Get DRTM sequence object
19 hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle);
20
21 // Is this _TPM_Hash_End after Startup or before
22 if(TPMIsStarted())
23 {
24 // After
25
26 // Reset the DRTM PCR
27 PCRResetDynamics();
28
29 // Extend the DRTM_PCR.
30 pcrHandle = PCR_FIRST + DRTM_PCR;
31
32 // DRTM sequence increments restartCount
33 gr.restartCount++;
34 }
35 else
36 {
37 pcrHandle = PCR_FIRST + HCRTM_PCR;
38 g_DrtmPreStartup = TRUE;
39 }
40
41 // Complete hash and extend PCR, or if this is an HCRTM, complete
42 // the hash, reset the H-CRTM register (PCR[0]) to 0...04, and then
43 // extend the H-CRTM data
44 for(i = 0; i < HASH_COUNT; i++)
45 {
46 TPMI_ALG_HASH hash = CryptHashGetAlgByIndex(i);
47 // make sure that the PCR is implemented for this algorithm
48 if(PcrIsAllocated(pcrHandle,
49 hashObject->state.hashState[i].hashAlg))
50 {
51 // Complete hash
52 digest.t.size = CryptHashGetDigestSize(hash);
53 CryptHashEnd2B(&hashObject->state.hashState[i], &digest.b);
54
55 PcrDrtm(pcrHandle, hash, &digest);
56 }
57 }
58
59 // Flush sequence object.
60 FlushObject(g_DRTMHandle);
61
62 g_DRTMHandle = TPM_RH_UNASSIGNED;
63
64 return;
65 }
23.1 Introduction
The commands in this clause 1 are used for policy evaluation. When successful, each command will
update the policySession→policyDigest in a policy session context in order to establish that the
authorizations required to use an object have been provided. Many of the commands will also modify
other parts of a policy context so that the caller may constrain the scope of the authorization that is
provided.
NOTE 1 Many of the terms used in this clause are described in detail in TPM 2.0 Part 1 and are not redefined
in this clause.
The policySession parameter of the command is the handle of the policy session context to be modified
by the command.
If the policySession parameter indicates a trial policy session, then the policySession→policyDigest will
be updated and the indicated validations are not performed. However, any authorizations required to
perform the policy command will be checked and dictionary attack logic invoked as necessary.
NOTE 2 If software is used to create policies, no authorization values are used. For example,
TPM_PolicySecret requires an authorization in a trial policy session, but not in a policy calculation
outside the TPM.
NOTE 4 Unless there is an unmarshaling error in the parameters of the command, these commands will
return TPM_RC_SUCCESS when policySession references a trial session.
NOTE 5 Policy context other than the policySession→policyDigest may be updated for a trial policy but it is
not required.
Introduction
The TPM2_PolicySigned, TPM_PolicySecret, and TPM2_PolicyTicket commands use many of the same
functions. This clause consolidates those functions to simplify the document and to ensure uniformity of
the operations.
These parameter checks will be performed when indicated in the description of each of the commands:
nonceTPM – If this parameter is not the Empty Buffer, and it does not match
policySession→nonceTPM, then the TPM shall return TPM_RC_VALUE.
expiration – If this parameter is not zero, then:
1) if nonceTPM is not an Empty Buffer, then the absolute value of expiration is converted to
milliseconds and added to policySession→startTime to create the timeout value and proceed to
c).
2) If nonceTPM is an Empty Buffer, then the absolute value of expiration is converted to
milliseconds and used as the timeout value and proceed to c).
However, timeout can only be changed to a smaller value.
timeout – If timeout is less than the current value of Time, or the current timeEpoch is not the same
as policySession→timeEpoch, the TPM shall return TPM_RC_EXPIRED
cpHashA – If this parameter is not an Empty Buffer
NOTE 2 cpHashA is the hash of the command to be executed using this policy session in the
authorization. The algorithm used to compute this hash is required to be the algorithm of the
policy session.
1) the TPM shall return TPM_RC_CPHASH if policySession→cpHash is set and the contents of
policySession→cpHash are not the same as cpHashA; or
NOTE 3 cpHash is the expected cpHash value held in the policy session context.
2) the TPM shall return TPM_RC_SIZE if cpHashA is not the same size as
policySession→policyDigest.
NOTE 4 policySession→policyDigest is the size of the digest produced by the hash algorithm used
to compute policyDigest.
NOTE 2 The arg2.size and arg3.size fields are not included in the hashes.
NOTE 3 PolicyUpdate() uses two hash operations because arg2 and arg3 are variable-sized and the
concatenation of arg2 and arg3 in a single hash could produce the same digest even though arg2
and arg3 are different. For example, arg2 = 1 2 3 and arg3 = 4 5 6 would produce the same digest
as arg2 = 1 2 and arg3 = 3 4 5 6. Processing of the arguments separately in different Extend
operation ensures that the digest produced by PolicyUpdate() will be different if arg2 and arg3 are
different.
When a policy command modifies some part of the policy session context other than the
policySession→policyDigest, the following rules apply.
• cpHash – this parameter may only be changed if it contains its initialization value (an Empty Buffer).
If cpHash is not the Empty Buffer when a policy command attempts to update it, the TPM will return
an error (TPM_RC_CPHASH) if the current and update values are not the same.
• timeOut – this parameter may only be changed to a smaller value. If a command attempts to update
this value with a larger value (longer into the future), the TPM will discard the update value. This is
not an error condition.
• commandCode – once set by a policy command, this value may not be changed except by
TPM2_PolicyRestart(). If a policy command tries to change this to a different value, an error is
returned (TPM_RC_POLICY_CC).
• pcrUpdateCounter – this parameter is updated by TPM2_PolicyPCR(). This value may only be set
once during a policy. Each time TPM2_PolicyPCR() executes, it checks to see if
policySession→pcrUpdateCounter has its default state, indicating that this is the first
TPM2_PolicyPCR(). If it has its default value, then policySession→pcrUpdateCounter is set to the
current value of pcrUpdateCounter. If policySession→pcrUpdateCounter does not have its default
value and its value is not the same as pcrUpdateCounter, the TPM shall return
TPM_RC_PCR_CHANGED.
NOTE 1 If this parameter and pcrUpdateCounter are not the same, it indicates that PCR have changed
since checked by the previous TPM2_PolicyPCR(). Since they have changed, the previous PCR
validation is no longer valid.
• commandLocality – this parameter is the logical AND of all enabled localities. All localities are
enabled for a policy when the policy session is created. TPM2_PolicyLocalities() selectively disables
localities. Once use of a policy for a locality has been disabled, it cannot be enabled except by
TPM2_PolicyRestart().
• isPPRequired – once SET, this parameter may only be CLEARed by TPM2_PolicyRestart().
• isAuthValueNeeded – once SET, this parameter may only be CLEARed by TPM2_PolicyPassword()
or TPM2_PolicyRestart().
• isPasswordNeeded – once SET, this parameter may only be CLEARed by TPM2_PolicyAuthValue()
or TPM2_PolicyRestart(),
For TPM2_PolicySigned() or TPM2_PolicySecret(), if the caller specified a negative value for expiration,
then the TPM will return a ticket that includes a value indicating when the authorization expires.
Otherwise, the TPM will return a NULL Ticket.
NOTE 1 If the authHandle in TPM2_PolicySecret() references a PIN Pass Index, then the command may
succeed but a NULL Ticket will be returned.
The required computation for the digest in the authorization ticket is:
HMACcontextAlg(proof, (TPM_ST_AUTH_xxx || cpHash || policyRef || authName
|| timeout || [timeEpoch] || [resetCount])) (12)
where
HMACcontextAlg() an HMAC using the context integrity hash
proof a TPM secret value associated with the hierarchy of the object
associated with authName
TPM_ST_AUTH_xxx either TPM_ST_AUTH_SIGNED or TPM_ST_AUTH_SECRET;
used to ensure that the ticket is properly used
cpHash optional hash of the authorized command
policyRef optional reference to a policy value
authName Name of the object that signed the authorization
timeout implementation-specific value indicating when the authorization
expires
timeEpoch implementation-specific representation of the timeEpoch at the
time the ticket was created
NOTE 3 Not included it timeout is zero or if nonceTPM was include in the authorization.
23.3 TPM2_PolicySigned
General Description
This command includes a signed authorization in a policy. The command ties the policy to a signing key
by including the Name of the signing key in the policyDigest
If policySession is a trial session, the TPM will not check the signature and will update
policySession→policyDigest as described in 23.2.3 as if a properly signed authorization was received, but
no ticket will be produced.
If policySession is not a trial session, the TPM will validate auth and only perform the update if it is a valid
signature over the fields of the command.
The authorizing entity will sign a digest of the authorization qualifiers: nonceTPM, expiration, cpHashA,
and policyRef. The digest is computed as:
aHash ≔ HauthAlg(nonceTPM || expiration || cpHashA || policyRef) (13)
where
HauthAlg() the hash associated with the auth parameter of this command
NOTE 1 Each signature and key combination indicates the scheme and each scheme has an
associated hash.
NOTE 4 The nonceTPM, cpHashA, and policyRef qualifiers used to compute aHash use the TPM2B buffer
but do not prepend the size.
The aHash is signed by the key associated with a key whose handle is authObject. The signature and
signing parameters are combined to create the auth parameter.
The TPM will perform the parameter checks listed in 23.2.2
If the parameter checks succeed, the TPM will construct a test digest (tHash) over the provided
parameters using the same formulation as shown in equation (13) above.
If tHash does not match the digest of the signed aHash, then the authorization fails and the TPM shall
return TPM_RC_POLICY_FAIL and make no change to policySession→policyDigest.
Detailed Actions
1 #include "Tpm.h"
2 #include "Policy_spt_fp.h"
3 #include "PolicySigned_fp.h"
4 #if CC_PolicySigned // Conditional expansion of this file
5 TPM_RC
6 TPM2_PolicySigned(
7 PolicySigned_In *in, // IN: input parameter list
8 PolicySigned_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result = TPM_RC_SUCCESS;
12 SESSION *session;
13 TPM2B_NAME entityName;
14 TPM2B_DIGEST authHash;
15 HASH_STATE hashState;
16 UINT64 authTimeout = 0;
17 // Input Validation
18 // Set up local pointers
19 session = SessionGet(in->policySession); // the session structure
20
21 // Only do input validation if this is not a trial policy session
22 if(session->attributes.isTrialPolicy == CLEAR)
23 {
24 authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM);
25
26 result = PolicyParameterChecks(session, authTimeout,
27 &in->cpHashA, &in->nonceTPM,
28 RC_PolicySigned_nonceTPM,
29 RC_PolicySigned_cpHashA,
30 RC_PolicySigned_expiration);
31 if(result != TPM_RC_SUCCESS)
32 return result;
33 // Re-compute the digest being signed
34
35 // Start hash
36 authHash.t.size = CryptHashStart(&hashState,
37 CryptGetSignHashAlg(&in->auth));
38 // If there is no digest size, then we don't have a verification function
39 // for this algorithm (e.g. TPM_ALG_ECDAA) so indicate that it is a
40 // bad scheme.
41 if(authHash.t.size == 0)
42 return TPM_RCS_SCHEME + RC_PolicySigned_auth;
43
44 // nonceTPM
45 CryptDigestUpdate2B(&hashState, &in->nonceTPM.b);
46
47 // expiration
48 CryptDigestUpdateInt(&hashState, sizeof(UINT32), in->expiration);
49
50 // cpHashA
51 CryptDigestUpdate2B(&hashState, &in->cpHashA.b);
52
53 // policyRef
54 CryptDigestUpdate2B(&hashState, &in->policyRef.b);
55
56 // Complete digest
57 CryptHashEnd2B(&hashState, &authHash.b);
58
59 // Validate Signature. A TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE
60 // error may be returned at this point
61 result = CryptValidateSignature(in->authObject, &authHash, &in->auth);
62 if(result != TPM_RC_SUCCESS)
63 return RcSafeAddToResult(result, RC_PolicySigned_auth);
64 }
65 // Internal Data Update
66 // Update policy with input policyRef and name of authorization key
67 // These values are updated even if the session is a trial session
68 PolicyContextUpdate(TPM_CC_PolicySigned,
69 EntityGetName(in->authObject, &entityName),
70 &in->policyRef,
71 &in->cpHashA, authTimeout, session);
72 // Command Output
73 // Create ticket and timeout buffer if in->expiration < 0 and this is not
74 // a trial session.
75 // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present
76 // when expiration is non-zero.
77 if(in->expiration < 0
78 && session->attributes.isTrialPolicy == CLEAR)
79 {
80 BOOL expiresOnReset = (in->nonceTPM.t.size == 0);
81 // Compute policy ticket
82 authTimeout &= ~EXPIRATION_BIT;
83
84 TicketComputeAuth(TPM_ST_AUTH_SIGNED, EntityGetHierarchy(in->authObject),
85 authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef,
86 &entityName, &out->policyTicket);
87 // Generate timeout buffer. The format of output timeout buffer is
88 // TPM-specific.
89 // Note: In this implementation, the timeout buffer value is computed after
90 // the ticket is produced so, when the ticket is checked, the expiration
91 // flag needs to be extracted before the ticket is checked.
92 // In the Windows compatible version, the least-significant bit of the
93 // timeout value is used as a flag to indicate if the authorization expires
94 // on reset. The flag is the MSb.
95 out->timeout.t.size = sizeof(authTimeout);
96 if(expiresOnReset)
97 authTimeout |= EXPIRATION_BIT;
98 UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
99 }
100 else
101 {
102 // Generate a null ticket.
103 // timeout buffer is null
104 out->timeout.t.size = 0;
105
106 // authorization ticket is null
107 out->policyTicket.tag = TPM_ST_AUTH_SIGNED;
108 out->policyTicket.hierarchy = TPM_RH_NULL;
109 out->policyTicket.digest.t.size = 0;
110 }
111 return TPM_RC_SUCCESS;
112 }
23.4 TPM2_PolicySecret
General Description
This command includes a secret-based authorization to a policy. The caller proves knowledge of the
secret value using an authorization session using the authValue associated with authHandle. A password
session, an HMAC session, or a policy session containing TPM2_PolicyAuthValue() or
TPM2_PolicyPassword() will satisfy this requirement.
If a policy session is used and use of the authValue of authHandle is not required, the TPM will return
TPM_RC_MODE. That is, the session for authHandle must have either isAuthValueNeeded or
isPasswordNeeded SET.
The secret is the authValue of the entity whose handle is authHandle, which may be any TPM entity with
a handle and an associated authValue. This includes the reserved handles (for example, Platform,
Storage, and Endorsement), NV Indexes, and loaded objects. authEntity is the entity referenced by
authHandle. If authEntity references an Ordinary object, it must have userWithAuth SET.
NOTE 1 The userWithAuth requirement permits the implementation to use common authorization code.
NOTE 2 The authorization value for a hierarchy cannot be used in this command if the hierarchy is disabled.
If the authorization check fails, then the normal dictionary attack logic is invoked.
If the authorization provided by the authorization session is valid, the command parameters are checked
as described in 23.2.2.
When all validations have succeeded, policySession→policyDigest is updated by PolicyUpdate() (see
23.2.3).
PolicyUpdate(TPM_CC_PolicySecret, authEntity→Name, policyRef) (15)
authEntity→Name is a TPM2B_NAME. policySession is updated as described in 23.2.4. The TPM will
optionally produce a ticket as described in 23.2.5.
If the session is a trial session, policySession→policyDigest is updated if the authorization is valid.
NOTE 2 If an HMAC is used to convey the authorization, a separate session is needed for the authorization.
Because the HMAC in that authorization will include a nonce that prevents replay of the
authorization, the value of the nonceTPM parameter in this command is limited. It is retained mostly
to provide processing consistency with TPM2_PolicySigned().
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicySecret_fp.h"
3 #if CC_PolicySecret // Conditional expansion of this file
4 #include "Policy_spt_fp.h"
5 #include "NV_spt_fp.h"
6 TPM_RC
7 TPM2_PolicySecret(
8 PolicySecret_In *in, // IN: input parameter list
9 PolicySecret_Out *out // OUT: output parameter list
10 )
11 {
12 TPM_RC result;
13 SESSION *session;
14 TPM2B_NAME entityName;
15 UINT64 authTimeout = 0;
16 // Input Validation
17 // Get pointer to the session structure
18 session = SessionGet(in->policySession);
19
20 //Only do input validation if this is not a trial policy session
21 if(session->attributes.isTrialPolicy == CLEAR)
22 {
23 authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM);
24
25 result = PolicyParameterChecks(session, authTimeout,
26 &in->cpHashA, &in->nonceTPM,
27 RC_PolicySecret_nonceTPM,
28 RC_PolicySecret_cpHashA,
29 RC_PolicySecret_expiration);
30 if(result != TPM_RC_SUCCESS)
31 return result;
32 }
33 // Internal Data Update
34 // Update policy context with input policyRef and name of authorizing key
35 // This value is computed even for trial sessions. Possibly update the cpHash
36 PolicyContextUpdate(TPM_CC_PolicySecret,
37 EntityGetName(in->authHandle, &entityName), &in->policyRef,
38 &in->cpHashA, authTimeout, session);
39 // Command Output
40 // Create ticket and timeout buffer if in->expiration < 0 and this is not
41 // a trial session.
42 // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present
43 // when expiration is non-zero.
44 if(in->expiration < 0
45 && session->attributes.isTrialPolicy == CLEAR
46 && !NvIsPinPassIndex(in->authHandle))
47 {
48 BOOL expiresOnReset = (in->nonceTPM.t.size == 0);
49 // Compute policy ticket
23.5 TPM2_PolicyTicket
General Description
This command is similar to TPM2_PolicySigned() except that it takes a ticket instead of a signed
authorization. The ticket represents a validated authorization that had an expiration time associated with
it.
The parameters of this command are checked as described in 23.2.2.
If the checks succeed, the TPM uses the timeout, cpHashA, policyRef, and authName to construct a
ticket to compare with the value in ticket. If these tickets match, then the TPM will create a TPM2B_NAME
(objectName) using authName and update the context of policySession by PolicyUpdate() (see 23.2.3).
PolicyUpdate(commandCode, authName, policyRef) (16)
If the structure tag of ticket is TPM_ST_AUTH_SECRET, then commandCode will be
TPM_CC_PolicySecret. If the structure tag of ticket is TPM_ST_AUTH_SIGNED, then commandCode will
be TPM_CC_PolicySIgned.
policySession is updated as described in 23.2.4.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyTicket_fp.h"
3 #if CC_PolicyTicket // Conditional expansion of this file
4 #include "Policy_spt_fp.h"
5 TPM_RC
6 TPM2_PolicyTicket(
7 PolicyTicket_In *in // IN: input parameter list
8 )
9 {
10 TPM_RC result;
11 SESSION *session;
12 UINT64 authTimeout;
13 TPMT_TK_AUTH ticketToCompare;
14 TPM_CC commandCode = TPM_CC_PolicySecret;
15 BOOL expiresOnReset;
16
17 // Input Validation
18
19 // Get pointer to the session structure
20 session = SessionGet(in->policySession);
21
22 // NOTE: A trial policy session is not allowed to use this command.
23 // A ticket is used in place of a previously given authorization. Since
24 // a trial policy doesn't actually authenticate, the validated
25 // ticket is not necessary and, in place of using a ticket, one
26 // should use the intended authorization for which the ticket
27 // would be a substitute.
28 if(session->attributes.isTrialPolicy)
29 return TPM_RCS_ATTRIBUTES + RC_PolicyTicket_policySession;
30 // Restore timeout data. The format of timeout buffer is TPM-specific.
31 // In this implementation, the most significant bit of the timeout value is
32 // used as the flag to indicate that the ticket expires on TPM Reset or
33 // TPM Restart. The flag has to be removed before the parameters and ticket
34 // are checked.
35 if(in->timeout.t.size != sizeof(UINT64))
36 return TPM_RCS_SIZE + RC_PolicyTicket_timeout;
37 authTimeout = BYTE_ARRAY_TO_UINT64(in->timeout.t.buffer);
38
39 // extract the flag
40 expiresOnReset = (authTimeout & EXPIRATION_BIT) != 0;
41 authTimeout &= ~EXPIRATION_BIT;
42
43 // Do the normal checks on the cpHashA and timeout values
44 result = PolicyParameterChecks(session, authTimeout,
45 &in->cpHashA,
46 NULL, // no nonce
47 0, // no bad nonce return
48 RC_PolicyTicket_cpHashA,
49 RC_PolicyTicket_timeout);
50 if(result != TPM_RC_SUCCESS)
51 return result;
52 // Validate Ticket
53 // Re-generate policy ticket by input parameters
54 TicketComputeAuth(in->ticket.tag, in->ticket.hierarchy,
55 authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef,
56 &in->authName, &ticketToCompare);
57 // Compare generated digest with input ticket digest
58 if(!MemoryEqual2B(&in->ticket.digest.b, &ticketToCompare.digest.b))
59 return TPM_RCS_TICKET + RC_PolicyTicket_ticket;
60
61 // Internal Data Update
62
63 // Is this ticket to take the place of a TPM2_PolicySigned() or
64 // a TPM2_PolicySecret()?
65 if(in->ticket.tag == TPM_ST_AUTH_SIGNED)
66 commandCode = TPM_CC_PolicySigned;
67 else if(in->ticket.tag == TPM_ST_AUTH_SECRET)
68 commandCode = TPM_CC_PolicySecret;
69 else
70 // There could only be two possible tag values. Any other value should
71 // be caught by the ticket validation process.
72 FAIL(FATAL_ERROR_INTERNAL);
73
74 // Update policy context
75 PolicyContextUpdate(commandCode, &in->authName, &in->policyRef,
76 &in->cpHashA, authTimeout, session);
77
78 return TPM_RC_SUCCESS;
79 }
80 #endif // CC_PolicyTicket
23.6 TPM2_PolicyOR
General Description
This command allows options in authorizations without requiring that the TPM evaluate all of the options.
If a policy may be satisfied by different sets of conditions, the TPM need only evaluate one set that
satisfies the policy. This command will indicate that one of the required sets of conditions has been
satisfied.
PolicySession→policyDigest is compared against the list of provided values. If the current
policySession→policyDigest does not match any value in the list, the TPM shall return TPM_RC_VALUE.
Otherwise, the TPM will reset policySession→policyDigest to a Zero Digest. Then
policySession→policyDigest is extended by the concatenation of TPM_CC_PolicyOR and the
concatenation of all of the digests.
If policySession is a trial session, the TPM will assume that policySession→policyDigest matches one of
the list entries and compute the new value of policyDigest.
The algorithm for computing the new value for policyDigest of policySession is:
Concatenate all the digest values in pHashList:
digests ≔ pHashList.digests[1].buffer || … || pHashList.digests[n].buffer (17)
NOTE 1 The TPM will not return an error if the size of an entry is not the same as the size of the digest
of the policy. However, that entry cannot match policyDigest.
A TPM shall support a list with at least eight tagged digest values.
NOTE 3 If policies are to be portable between TPMs, then they should not use more than eight values.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyOR_fp.h"
3 #if CC_PolicyOR // Conditional expansion of this file
4 #include "Policy_spt_fp.h"
5 TPM_RC
6 TPM2_PolicyOR(
7 PolicyOR_In *in // IN: input parameter list
8 )
9 {
10 SESSION *session;
11 UINT32 i;
12
13 // Input Validation and Update
14
15 // Get pointer to the session structure
16 session = SessionGet(in->policySession);
17
18 // Compare and Update Internal Session policy if match
19 for(i = 0; i < in->pHashList.count; i++)
20 {
21 if(session->attributes.isTrialPolicy == SET
22 || (MemoryEqual2B(&session->u2.policyDigest.b,
23 &in->pHashList.digests[i].b)))
24 {
25 // Found a match
26 HASH_STATE hashState;
27 TPM_CC commandCode = TPM_CC_PolicyOR;
28
29 // Start hash
30 session->u2.policyDigest.t.size
31 = CryptHashStart(&hashState, session->authHashAlg);
32 // Set policyDigest to 0 string and add it to hash
33 MemorySet(session->u2.policyDigest.t.buffer, 0,
34 session->u2.policyDigest.t.size);
35 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
36
37 // add command code
38 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
39
40 // Add each of the hashes in the list
41 for(i = 0; i < in->pHashList.count; i++)
42 {
43 // Extend policyDigest
44 CryptDigestUpdate2B(&hashState, &in->pHashList.digests[i].b);
45 }
46 // Complete digest
47 CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
48
49 return TPM_RC_SUCCESS;
50 }
51 }
52 // None of the values in the list matched the current policyDigest
53 return TPM_RCS_VALUE + RC_PolicyOR_pHashList;
54 }
55 #endif // CC_PolicyOR
23.7 TPM2_PolicyPCR
General Description
This command is used to cause conditional gating of a policy based on PCR. This command together
with TPM2_PolicyOR() allows one group of authorizations to occur when PCR are in one state and a
different set of authorizations when the PCR are in a different state.
The TPM will modify the pcrs parameter so that bits that correspond to unimplemented PCR are CLEAR.
If policySession is not a trial policy session, the TPM will use the modified value of pcrs to select PCR
values to hash according to TPM 2.0 Part 1, Selecting Multiple PCR. The hash algorithm of the policy
session is used to compute a digest (digestTPM) of the selected PCR. If pcrDigest does not have a length
of zero, then it is compared to digestTPM; and if the values do not match, the TPM shall return
TPM_RC_VALUE and make no change to policySession→policyDigest. If the values match, or if the
length of pcrDigest is zero, then policySession→policyDigest is extended by:
policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyPCR || pcrs || digestTPM) (19)
where
pcrs the pcrs parameter with bits corresponding to unimplemented
PCR set to 0
digestTPM the digest of the selected PCR using the hash algorithm of the
policy session
NOTE 1 If the caller provides the expected PCR value, the intention is that the policy evaluation stop at that
point if the PCR do not match. If the caller does not provide the expected PCR value, then the
validity of the settings will not be determined until an attempt is made to use the policy for
authorization. If the policy is constructed such that the PCR check comes before user author ization
checks, this early termination would allow software to avoid unnecessary prompts for user input to
satisfy a policy that would fail later due to incorrect PCR values.
After this command completes successfully, the TPM shall return TPM_RC_PCR_CHANGED if the policy
session is used for authorization and the PCR are not known to be correct.
The TPM uses a “generation” number (pcrUpdateCounter) that is incremented each time PCR are
updated (unless the PCR being changed is specified not to cause a change to this counter). The value of
this counter is stored in the policy session context (policySession→pcrUpdateCounter) when this
command is executed. When the policy is used for authorization, the current value of the counter is
compared to the value in the policy session context and the authorization will fail if the values are not the
same.
When this command is executed, policySession→pcrUpdateCounter is checked to see if it has been
previously set (in the reference implementation, it has a value of zero if not previously set). If it has been
set, it will be compared with the current value of pcrUpdateCounter to determine if any PCR changes
have occurred. If the values are different, the TPM shall return TPM_RC_PCR_CHANGED.
NOTE 2 Since the pcrUpdateCounter is updated if any PCR is extended (except those specified not to do
so), this means that the command will fail even if a PCR not specified in the pol icy is updated. This
is an optimization for the purposes of conserving internal TPM memory. This would be a rare
occurrence, and, if this should occur, the policy could be reset using the TPM2_PolicyRestart
command and rerun.
If policySession→pcrUpdateCounter has not been set, then it is set to the current value of
pcrUpdateCounter.
If this command is used for a trial policySession, policySession→policyDigest will be updated using the
values from the command rather than the values from a digest of the TPM PCR. If the caller does not
provide PCR settings (pcrDigest has a length of zero), the TPM may (and it is preferred to) use the
current TPM PCR settings (digestTPM) in the calculation for the new policyDigest. The TPM may return
an error if the caller does not provide a PCR digest for a trial policy session but this is not the preferred
behavior.
The TPM will not check any PCR and will compute:
policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyPCR || pcrs || pcrDigest) (20)
In this computation, pcrs is the input parameter without modification.
NOTE 3 The pcrs parameter is expected to match the configuration of the TPM for which the policy is being
computed which may not be the same as the TPM on which the trial policy is being compute d.
NOTE 4 Although no PCR are checked in a trial policy session, pcrDigest is expected to correspond to some
useful PCR values. It is legal, but pointless, to have the TPM aid in calculating a policyDigest
corresponding to PCR values that are not useful in practice.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyPCR_fp.h"
3 #if CC_PolicyPCR // Conditional expansion of this file
4 TPM_RC
5 TPM2_PolicyPCR(
6 PolicyPCR_In *in // IN: input parameter list
7 )
8 {
9 SESSION *session;
10 TPM2B_DIGEST pcrDigest;
11 BYTE pcrs[sizeof(TPML_PCR_SELECTION)];
12 UINT32 pcrSize;
13 BYTE *buffer;
14 TPM_CC commandCode = TPM_CC_PolicyPCR;
15 HASH_STATE hashState;
16
17 // Input Validation
18
19 // Get pointer to the session structure
20 session = SessionGet(in->policySession);
21
22 // Compute current PCR digest
23 PCRComputeCurrentDigest(session->authHashAlg, &in->pcrs, &pcrDigest);
24
25 // Do validation for non trial session
26 if(session->attributes.isTrialPolicy == CLEAR)
27 {
28 // Make sure that this is not going to invalidate a previous PCR check
29 if(session->pcrCounter != 0 && session->pcrCounter != gr.pcrCounter)
30 return TPM_RC_PCR_CHANGED;
31
32 // If the caller specified the PCR digest and it does not
33 // match the current PCR settings, return an error..
34 if(in->pcrDigest.t.size != 0)
35 {
36 if(!MemoryEqual2B(&in->pcrDigest.b, &pcrDigest.b))
37 return TPM_RCS_VALUE + RC_PolicyPCR_pcrDigest;
38 }
39 }
40 else
41 {
42 // For trial session, just use the input PCR digest if one provided
43 // Note: It can't be too big because it is a TPM2B_DIGEST and the size
44 // would have been checked during unmarshaling
45 if(in->pcrDigest.t.size != 0)
46 pcrDigest = in->pcrDigest;
47 }
48 // Internal Data Update
49 // Update policy hash
50 // policyDigestnew = hash( policyDigestold || TPM_CC_PolicyPCR
51 // || PCRS || pcrDigest)
52 // Start hash
53 CryptHashStart(&hashState, session->authHashAlg);
54
23.8 TPM2_PolicyLocality
General Description
This command indicates that the authorization will be limited to a specific locality.
policySession→commandLocality is a parameter kept in the session context. When the policy session is
started, this parameter is initialized to a value that allows the policy to apply to any locality.
If locality has a value greater than 31, then an extended locality is indicated. For an extended locality, the
TPM will validate that policySession→commandLocality has not previously been set or that the current
value of policySession→commandLocality is the same as locality (TPM_RC_RANGE).
When locality is not an extended locality, the TPM will validate that the policySession→commandLocality
is not set to an extended locality value (TPM_RC_RANGE). If not the TPM will disable any locality not
SET in the locality parameter. If the result of disabling localities results in no locality being enabled, the
TPM will return TPM_RC_RANGE.
If no error occurred in the validation of locality, policySession→policyDigest is extended with
policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyLocality || locality) (21)
Then policySession→commandLocality is updated to indicate which localities are still allowed after
execution of TPM2_PolicyLocality().
When the policy session is used to authorize a command, the authorization will fail if the locality used for
the command is not one of the enabled localities in policySession→commandLocality.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyLocality_fp.h"
3 #if CC_PolicyLocality // Conditional expansion of this file
4 TPM_RC
5 TPM2_PolicyLocality(
6 PolicyLocality_In *in // IN: input parameter list
7 )
8 {
9 SESSION *session;
10 BYTE marshalBuffer[sizeof(TPMA_LOCALITY)];
11 BYTE prevSetting[sizeof(TPMA_LOCALITY)];
12 UINT32 marshalSize;
13 BYTE *buffer;
14 TPM_CC commandCode = TPM_CC_PolicyLocality;
15 HASH_STATE hashState;
16
17 // Input Validation
18
19 // Get pointer to the session structure
20 session = SessionGet(in->policySession);
21
22 // Get new locality setting in canonical form
23 marshalBuffer[0] = 0; // Code analysis says that this is not initialized
24 buffer = marshalBuffer;
25 marshalSize = TPMA_LOCALITY_Marshal(&in->locality, &buffer, NULL);
26
27 // Its an error if the locality parameter is zero
28 if(marshalBuffer[0] == 0)
29 return TPM_RCS_RANGE + RC_PolicyLocality_locality;
30
31 // Get existing locality setting in canonical form
32 prevSetting[0] = 0; // Code analysis says that this is not initialized
33 buffer = prevSetting;
34 TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL);
35
36 // If the locality has previously been set
37 if(prevSetting[0] != 0
38 // then the current locality setting and the requested have to be the same
39 // type (that is, either both normal or both extended
40 && ((prevSetting[0] < 32) != (marshalBuffer[0] < 32)))
41 return TPM_RCS_RANGE + RC_PolicyLocality_locality;
42
43 // See if the input is a regular or extended locality
44 if(marshalBuffer[0] < 32)
45 {
46 // if there was no previous setting, start with all normal localities
47 // enabled
48 if(prevSetting[0] == 0)
49 prevSetting[0] = 0x1F;
50
51 // AND the new setting with the previous setting and store it in prevSetting
52 prevSetting[0] &= marshalBuffer[0];
53
54 // The result setting can not be 0
55 if(prevSetting[0] == 0)
23.9 TPM2_PolicyNV
General Description
This command is used to cause conditional gating of a policy based on the contents of an NV Index. It is
an immediate assertion. The NV index is validated during the TPM2_PolicyNV() command, not when the
session is used for authorization.
The authorization to read the NV Index must succeed even if policySession is a trial policy session.
If policySession is a trial policy session, the TPM will update policySession→policyDigest as shown in
equations (22) and (23) below and return TPM_RC_SUCCESS. It will not perform any further validation.
The remainder of this general description would apply only if policySession is not a trial policy session.
An authorization session providing authorization to read the NV Index shall be provided.
If TPMA_NV_WRITTEN is not SET in the NV Index, the TPM shall return TPM_RC_NV_UNINITIALIZED.
If TPMA_NV_READLOCKED of the NV Index is SET, then the TPM shall return TPM_RC_NV_LOCKED.
For an NV Index with the TPM_NT_COUNTER or TPM_NT_BITS attribute SET, the TPM may ignore the
offset parameter and use an offset of 0. Therefore, it is recommended that the caller set the offset
parameter to 0 for interoperability.
If offset and the size field of data add to a value that is greater than the dataSize field of the NV Index
referenced by nvIndex, the TPM shall return an error (TPM_RC_NV_RANGE). The implementation may
return an error (TPM_RC_VALUE) if it performs an additional check and determines that offset is greater
than the dataSize field of the NV Index.
operandA begins at offset into the NV index contents and has a size equal to the size of operandB. The
TPM will perform the indicated arithmetic check using operandA and operandB. If the check fails, the
TPM shall return TPM_RC_POLICY and not change policySession→policyDigest. If the check succeeds,
the TPM will hash the arguments:
args ≔ HpolicyAlg(operandB.buffer || offset || operation) (22)
where
HpolicyAlg() hash function using the algorithm of the policy session
operandB the value used for the comparison
offset offset from the start of the NV Index data to start the comparison
operation the operation parameter indicating the comparison being
performed
The value of args and the Name of the NV Index are extended to policySession→policyDigest by
policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyNV || args || nvIndex→Name) (23)
where
HpolicyAlg() hash function using the algorithm of the policy session
args value computed in equation (22)
nvIndex→Name the Name of the NV Index
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyNV_fp.h"
3 #if CC_PolicyNV // Conditional expansion of this file
4 #include "Policy_spt_fp.h"
5 TPM_RC
6 TPM2_PolicyNV(
7 PolicyNV_In *in // IN: input parameter list
8 )
9 {
10 TPM_RC result;
11 SESSION *session;
12 NV_REF locator;
13 NV_INDEX *nvIndex;
14 BYTE nvBuffer[sizeof(in->operandB.t.buffer)];
15 TPM2B_NAME nvName;
16 TPM_CC commandCode = TPM_CC_PolicyNV;
17 HASH_STATE hashState;
18 TPM2B_DIGEST argHash;
19
20 // Input Validation
21
22 // Get pointer to the session structure
23 session = SessionGet(in->policySession);
24
25 //If this is a trial policy, skip all validations and the operation
26 if(session->attributes.isTrialPolicy == CLEAR)
27 {
28 // No need to access the actual NV index information for a trial policy.
29 nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
30
31 // Common read access checks. NvReadAccessChecks() may return
32 // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED
33 result = NvReadAccessChecks(in->authHandle,
34 in->nvIndex,
35 nvIndex->publicArea.attributes);
36 if(result != TPM_RC_SUCCESS)
37 return result;
38
39 // Make sure that offset is withing range
40 if(in->offset > nvIndex->publicArea.dataSize)
41 return TPM_RCS_VALUE + RC_PolicyNV_offset;
42
43 // Valid NV data size should not be smaller than input operandB size
44 if((nvIndex->publicArea.dataSize - in->offset) < in->operandB.t.size)
45 return TPM_RCS_SIZE + RC_PolicyNV_operandB;
46
47 // Get NV data. The size of NV data equals the input operand B size
48 NvGetIndexData(nvIndex, locator, in->offset, in->operandB.t.size, nvBuffer);
49
50 // Check to see if the condition is valid
51 if(!PolicySptCheckCondition(in->operation, nvBuffer,
52 in->operandB.t.buffer, in->operandB.t.size))
53 return TPM_RC_POLICY;
54 }
55 // Internal Data Update
56
57 // Start argument hash
58 argHash.t.size = CryptHashStart(&hashState, session->authHashAlg);
59
60 // add operandB
61 CryptDigestUpdate2B(&hashState, &in->operandB.b);
62
63 // add offset
64 CryptDigestUpdateInt(&hashState, sizeof(UINT16), in->offset);
65
66 // add operation
67 CryptDigestUpdateInt(&hashState, sizeof(TPM_EO), in->operation);
68
69 // complete argument digest
70 CryptHashEnd2B(&hashState, &argHash.b);
71
72 // Update policyDigest
73 // Start digest
74 CryptHashStart(&hashState, session->authHashAlg);
75
76 // add old digest
77 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
78
79 // add commandCode
80 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
81
82 // add argument digest
83 CryptDigestUpdate2B(&hashState, &argHash.b);
84
85 // Adding nvName
86 CryptDigestUpdate2B(&hashState, &EntityGetName(in->nvIndex, &nvName)->b);
87
88 // complete the digest
89 CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
90
91 return TPM_RC_SUCCESS;
92 }
93 #endif // CC_PolicyNV
23.10 TPM2_PolicyCounterTimer
General Description
This command is used to cause conditional gating of a policy based on the contents of the
TPMS_TIME_INFO structure.
If policySession is a trial policy session, the TPM will update policySession→policyDigest as shown in
equations (24) and (25) below and return TPM_RC_SUCCESS. It will not perform any validation. The
remainder of this general description would apply only if policySession is not a trial policy session.
The TPM will perform the indicated arithmetic check on the indicated portion of the TPMS_TIME_INFO
structure. If the check fails, the TPM shall return TPM_RC_POLICY and not change
policySession→policyDigest. If the check succeeds, the TPM will hash the arguments:
args ≔ HpolicyAlg(operandB.buffer || offset || operation) (24)
where
HpolicyAlg() hash function using the algorithm of the policy session
operandB.buffer the value used for the comparison
offset offset from the start of the TPMS_TIME_INFO structure at which
the comparison starts
operation the operation parameter indicating the comparison being
performed
The signed arithmetic operations are performed using twos-compliment. The indicated portion of the
TPMS_TIME_INFO structure begins at offset and has a length of operandB.size. If the number of octets
to be compared overflows the TPMS_TIME_INFO structure, the TPM returns TPM_RC_RANGE. If offset
is greater than the size of the marshaled TPMS_TIME_INFO structure, the TPM returns
TPM_RC_VALUE. The structure is marshaled into its canonical form with no padding. The TPM does not
check for alignment of the offset with a TPMS_TIME_INFO structure member.
Magnitude comparisons assume that the octet at offset zero in the referenced location and in operandB
contain the most significant octet of the data.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyCounterTimer_fp.h"
3 #if CC_PolicyCounterTimer // Conditional expansion of this file
4 #include "Policy_spt_fp.h"
5 TPM_RC
6 TPM2_PolicyCounterTimer(
7 PolicyCounterTimer_In *in // IN: input parameter list
8 )
9 {
10 SESSION *session;
11 TIME_INFO infoData; // data buffer of TPMS_TIME_INFO
12 BYTE *pInfoData = (BYTE *)&infoData;
13 UINT16 infoDataSize;
14 TPM_CC commandCode = TPM_CC_PolicyCounterTimer;
15 HASH_STATE hashState;
16 TPM2B_DIGEST argHash;
17
18 // Input Validation
19 // Get a marshaled time structure
20 infoDataSize = TimeGetMarshaled(&infoData);
21 // Make sure that the referenced stays within the bounds of the structure.
22 // NOTE: the offset checks are made even for a trial policy because the policy
23 // will not make any sense if the references are out of bounds of the timer
24 // structure.
25 if(in->offset > infoDataSize)
26 return TPM_RCS_VALUE + RC_PolicyCounterTimer_offset;
27 if((UINT32)in->offset + (UINT32)in->operandB.t.size > infoDataSize)
28 return TPM_RCS_RANGE;
29 // Get pointer to the session structure
30 session = SessionGet(in->policySession);
31
32 //If this is a trial policy, skip the check to see if the condition is met.
33 if(session->attributes.isTrialPolicy == CLEAR)
34 {
35 // If the command is going to use any part of the counter or timer, need
36 // to verify that time is advancing.
37 // The time and clock vales are the first two 64-bit values in the clock
38 if(in->offset < sizeof(UINT64) + sizeof(UINT64))
39 {
40 // Using Clock or Time so see if clock is running. Clock doesn't
41 // run while NV is unavailable.
42 // TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned here.
43 RETURN_IF_NV_IS_NOT_AVAILABLE;
44 }
45 // offset to the starting position
46 pInfoData = (BYTE *)infoData;
47 // Check to see if the condition is valid
48 if(!PolicySptCheckCondition(in->operation, pInfoData + in->offset,
49 in->operandB.t.buffer, in->operandB.t.size))
50 return TPM_RC_POLICY;
51 }
52 // Internal Data Update
53 // Start argument list hash
23.11 TPM2_PolicyCommandCode
General Description
This command indicates that the authorization will be limited to a specific command code.
If policySession→commandCode has its default value, then it will be set to code. If
policySession→commandCode does not have its default value, then the TPM will return
TPM_RC_VALUE if the two values are not the same.
If code is not implemented, the TPM will return TPM_RC_POLICY_CC.
If the TPM does not return an error, it will update policySession→policyDigest by
policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyCommandCode || code) (26)
NOTE 1 If a previous TPM2_PolicyCommandCode() had been executed, then it is probable that the policy
expression is improperly formed but the TPM does not return an error if code is the same.
NOTE 2 A TPM2_PolicyOR() would be used to allow an authorization to be used for multiple commands.
When the policy session is used to authorize a command, the TPM will fail the command if the
commandCode of that command does not match policySession→commandCode.
This command, or TPM2_PolicyDuplicationSelect(), is required to enable the policy to be used for ADMIN
role authorization.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyCommandCode_fp.h"
3 #if CC_PolicyCommandCode // Conditional expansion of this file
4 TPM_RC
5 TPM2_PolicyCommandCode(
6 PolicyCommandCode_In *in // IN: input parameter list
7 )
8 {
9 SESSION *session;
10 TPM_CC commandCode = TPM_CC_PolicyCommandCode;
11 HASH_STATE hashState;
12
13 // Input validation
14
15 // Get pointer to the session structure
16 session = SessionGet(in->policySession);
17
18 if(session->commandCode != 0 && session->commandCode != in->code)
19 return TPM_RCS_VALUE + RC_PolicyCommandCode_code;
20 if(CommandCodeToCommandIndex(in->code) == UNIMPLEMENTED_COMMAND_INDEX)
21 return TPM_RCS_POLICY_CC + RC_PolicyCommandCode_code;
22
23 // Internal Data Update
24 // Update policy hash
25 // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCommandCode || code)
26 // Start hash
27 CryptHashStart(&hashState, session->authHashAlg);
28
29 // add old digest
30 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
31
32 // add commandCode
33 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
34
35 // add input commandCode
36 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), in->code);
37
38 // complete the hash and get the results
39 CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
40
41 // update commandCode value in session context
42 session->commandCode = in->code;
43
44 return TPM_RC_SUCCESS;
45 }
46 #endif // CC_PolicyCommandCode
23.12 TPM2_PolicyPhysicalPresence
General Description
This command indicates that physical presence will need to be asserted at the time the authorization is
performed.
If this command is successful, policySession→isPPRequired will be SET to indicate that this check is
required when the policy is used for authorization. Additionally, policySession→policyDigest is extended
with
policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyPhysicalPresence) (27)
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyPhysicalPresence_fp.h"
3 #if CC_PolicyPhysicalPresence // Conditional expansion of this file
4 TPM_RC
5 TPM2_PolicyPhysicalPresence(
6 PolicyPhysicalPresence_In *in // IN: input parameter list
7 )
8 {
9 SESSION *session;
10 TPM_CC commandCode = TPM_CC_PolicyPhysicalPresence;
11 HASH_STATE hashState;
12
13 // Internal Data Update
14
15 // Get pointer to the session structure
16 session = SessionGet(in->policySession);
17
18 // Update policy hash
19 // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyPhysicalPresence)
20 // Start hash
21 CryptHashStart(&hashState, session->authHashAlg);
22
23 // add old digest
24 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
25
26 // add commandCode
27 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
28
29 // complete the digest
30 CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
31
32 // update session attribute
33 session->attributes.isPPRequired = SET;
34
35 return TPM_RC_SUCCESS;
36 }
37 #endif // CC_PolicyPhysicalPresence
23.13 TPM2_PolicyCpHash
General Description
This command is used to allow a policy to be bound to a specific command and command parameters.
TPM2_PolicySigned(), TPM2_PolicySecret(), and TPM2_PolicyTIcket() are designed to allow an
authorizing entity to execute an arbitrary command as the cpHashA parameter of those commands is not
included in policySession→policyDigest. TPM2_PolicyCommandCode() allows the policy to be bound to a
specific Command Code so that only certain entities may authorize specific command codes. This
command allows the policy to be restricted such that an entity may only authorize a command with a
specific set of parameters.
If policySession→cpHash is already set and not the same as cpHashA, then the TPM shall return
TPM_RC_CPHASH. If cpHashA does not have the size of the policySession→policyDigest, the TPM shall
return TPM_RC_SIZE.
NOTE 1 If a previous TPM2_PolicyCpHash() had been executed, then it is probable that the policy
expression is improperly formed but the TPM does not return an error if cpHash is the same.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyCpHash_fp.h"
3 #if CC_PolicyCpHash // Conditional expansion of this file
4 TPM_RC
5 TPM2_PolicyCpHash(
6 PolicyCpHash_In *in // IN: input parameter list
7 )
8 {
9 SESSION *session;
10 TPM_CC commandCode = TPM_CC_PolicyCpHash;
11 HASH_STATE hashState;
12
13 // Input Validation
14
15 // Get pointer to the session structure
16 session = SessionGet(in->policySession);
17
18 // A valid cpHash must have the same size as session hash digest
19 // NOTE: the size of the digest can't be zero because TPM_ALG_NULL
20 // can't be used for the authHashAlg.
21 if(in->cpHashA.t.size != CryptHashGetDigestSize(session->authHashAlg))
22 return TPM_RCS_SIZE + RC_PolicyCpHash_cpHashA;
23
24 // error if the cpHash in session context is not empty and is not the same
25 // as the input or is not a cpHash
26 if((session->u1.cpHash.t.size != 0)
27 && (!session->attributes.isCpHashDefined
28 || !MemoryEqual2B(&in->cpHashA.b, &session->u1.cpHash.b)))
29 return TPM_RC_CPHASH;
30
31 // Internal Data Update
32
33 // Update policy hash
34 // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCpHash || cpHashA)
35 // Start hash
36 CryptHashStart(&hashState, session->authHashAlg);
37
38 // add old digest
39 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
40
41 // add commandCode
42 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
43
44 // add cpHashA
45 CryptDigestUpdate2B(&hashState, &in->cpHashA.b);
46
47 // complete the digest and get the results
48 CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
49
50 // update cpHash in session context
51 session->u1.cpHash = in->cpHashA;
52 session->attributes.isCpHashDefined = SET;
53
54 return TPM_RC_SUCCESS;
55 }
56 #endif // CC_PolicyCpHash
23.14 TPM2_PolicyNameHash
General Description
This command allows a policy to be bound to a specific set of TPM entities without being bound to the
parameters of the command. This is most useful for commands such as TPM2_Duplicate() and for
TPM2_PCR_Event() when the referenced PCR requires a policy.
The nameHash parameter should contain the digest of the Names associated with the handles to be used
in the authorized command.
EXAMPLE For the TPM2_Duplicate() command, two handles are provided. One is the handle of the object
being duplicated and the other is the handle of the new parent. For that command, nameHash would
contain:
nameHash ≔ H policyAlg (objectHandle→Name || newParentHandle→Name)
If policySession→cpHash is already set, the TPM shall return TPM_RC_CPHASH. If the size of
nameHash is not the size of policySession→policyDigest, the TPM shall return TPM_RC_SIZE.
Otherwise, policySession→cpHash is set to nameHash.
If this command completes successfully, the cpHash of the authorized command will not be used for
validation. Only the digest of the Names associated with the handles in the command will be used.
NOTE 1 This allows the space normally used to hold policySession→cpHash to be used for
policySession→nameHash instead.
NOTE 2 This command can only be used with TPM2_PolicyAuthorize() or TPM2_PolicyAuthorizeNV. The
owner of the object being duplicated provides approval for their object to be migrated to a specific
new parent.
Without this approval, the Name of the Object would need to be known at the time that Object's
policy is created. However, since the Name of t he Object includes its policy, the Name is not known.
The Name can be known by the authorizing entit y.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyNameHash_fp.h"
3 #if CC_PolicyNameHash // Conditional expansion of this file
4 TPM_RC
5 TPM2_PolicyNameHash(
6 PolicyNameHash_In *in // IN: input parameter list
7 )
8 {
9 SESSION *session;
10 TPM_CC commandCode = TPM_CC_PolicyNameHash;
11 HASH_STATE hashState;
12
13 // Input Validation
14
15 // Get pointer to the session structure
16 session = SessionGet(in->policySession);
17
18 // A valid nameHash must have the same size as session hash digest
19 // Since the authHashAlg for a session cannot be TPM_ALG_NULL, the digest size
20 // is always non-zero.
21 if(in->nameHash.t.size != CryptHashGetDigestSize(session->authHashAlg))
22 return TPM_RCS_SIZE + RC_PolicyNameHash_nameHash;
23
24 // u1 in the policy session context cannot otherwise be occupied
25 if(session->u1.cpHash.b.size != 0
26 || session->attributes.isBound
27 || session->attributes.isCpHashDefined
28 || session->attributes.isTemplateSet)
29 return TPM_RC_CPHASH;
30
31 // Internal Data Update
32
33 // Update policy hash
34 // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNameHash || nameHash)
35 // Start hash
36 CryptHashStart(&hashState, session->authHashAlg);
37
38 // add old digest
39 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
40
41 // add commandCode
42 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
43
44 // add nameHash
45 CryptDigestUpdate2B(&hashState, &in->nameHash.b);
46
47 // complete the digest
48 CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
49
50 // update nameHash in session context
51 session->u1.cpHash = in->nameHash;
52
53 return TPM_RC_SUCCESS;
54 }
55 #endif // CC_PolicyNameHash
23.15 TPM2_PolicyDuplicationSelect
General Description
This command allows qualification of duplication to allow duplication to a selected new parent.
If this command not used in conjunction with a PolicyAuthorize Command, then only the new parent is
selected and includeObject should be CLEAR.
EXAMPLE When an object is created when the list of allowed duplication targets is known, the policy would be
created with includeObject CLEAR.
NOTE 1 Only the new parent may be selected because, without TPM2_PolicyAuthorize(), the Name of the
Object to be duplicated would need to be known at the time that Object's policy is created. However,
since the Name of the Object includes its policy, the Name is not known. The Name can be known
by the authorizing entity (a PolicyAuthorize Command) in which case includeObject may be SET.
If used in conjunction with TPM2_PolicyAuthorize(), then the authorizer of the new policy has the option
of selecting just the new parent or of selecting both the new parent and the duplication Object.
NOTE 2 If the authorizing entity for an TPM2_PolicyAuth orize() only specifies the new parent, then that
authorization may be applied to the duplication of any number of other Objects. If the authorizing
entity specifies both a new parent and the duplicated Object, then the authorization only applies to
that pairing of Object and new parent.
If either policySession→cpHash or policySession→nameHash has been previously set, the TPM shall
return TPM_RC_CPHASH. Otherwise, policySession→nameHash will be set to:
nameHash ≔ HpolicyAlg(objectName.name || newParentName.name) (30)
NOTE 3 It is allowed that policySesion→nameHash and policySession→cpHash share the same memory
space.
NOTE 4 The Name in these equations uses Name.name, indicating that the UINT16 size is not inclu ded in
the hash.
NOTE 5 policySession→nameHash receives the digest of both Names so that the check performed in
TPM2_Duplicate() may be the same regardless of which Names are included in
policySession→policyDigest. This means that, when TPM2_PolicyDuplicationSelect() is executed, it
is only valid for a specific pair of duplication object and new parent.
NOTE 6 The normal use of this command is before a TPM2_PolicyAuthorize(). An authorized entity would
approve a policyDigest that allowed duplication to a specific new parent. The authorizing entity may
want to limit the authorization so that the approval allows only a specific object to be duplicated to
the new parent. In that case, the authorizing entity would approve the policyDigest of equation (31).
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyDuplicationSelect_fp.h"
3 #if CC_PolicyDuplicationSelect // Conditional expansion of this file
4 TPM_RC
5 TPM2_PolicyDuplicationSelect(
6 PolicyDuplicationSelect_In *in // IN: input parameter list
7 )
8 {
9 SESSION *session;
10 HASH_STATE hashState;
11 TPM_CC commandCode = TPM_CC_PolicyDuplicationSelect;
12
13 // Input Validation
14
15 // Get pointer to the session structure
16 session = SessionGet(in->policySession);
17
18 // cpHash in session context must be empty
19 if(session->u1.cpHash.t.size != 0)
20 return TPM_RC_CPHASH;
21
22 // commandCode in session context must be empty
23 if(session->commandCode != 0)
24 return TPM_RC_COMMAND_CODE;
25
26 // Internal Data Update
27
28 // Update name hash
29 session->u1.cpHash.t.size = CryptHashStart(&hashState, session->authHashAlg);
30
31 // add objectName
32 CryptDigestUpdate2B(&hashState, &in->objectName.b);
33
34 // add new parent name
35 CryptDigestUpdate2B(&hashState, &in->newParentName.b);
36
37 // complete hash
38 CryptHashEnd2B(&hashState, &session->u1.cpHash.b);
39
40 // update policy hash
41 // Old policyDigest size should be the same as the new policyDigest size since
42 // they are using the same hash algorithm
43 session->u2.policyDigest.t.size
44 = CryptHashStart(&hashState, session->authHashAlg);
45 // add old policy
46 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
47
48 // add command code
49 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
50
51 // add objectName
52 if(in->includeObject == YES)
53 CryptDigestUpdate2B(&hashState, &in->objectName.b);
54
23.16 TPM2_PolicyAuthorize
General Description
This command allows policies to change. If a policy were static, then it would be difficult to add users to a
policy. This command lets a policy authority sign a new policy so that it may be used in an existing policy.
The authorizing entity signs a structure that contains
aHash ≔ HaHashAlg(approvedPolicy || policyRef) (33)
The aHashAlg is required to be the nameAlg of the key used to sign the aHash. The aHash value is then
signed (symmetric or asymmetric) by keySign. That signature is then checked by the TPM in 20.1
TPM2_VerifySignature() which produces a ticket by
HMAC(proof, (TPM_ST_VERIFIED || aHash || keySign→Name)) (34)
NOTE 1 The reason for the validation is because of the expectation that the policy will be used multiple times
and it is more efficient to check a ticket than to load an object each time to check a signature.
NOTE 2 The unmarshaling process requires that a proper TPMT_TK_VERIFIED be provided for checkTicket
but it may be a NULL Ticket. A NULL ticket is useful in a trial policy, where the caller uses the TPM
to perform policy calculations but does not have a valid authorization ticket.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyAuthorize_fp.h"
3 #if CC_PolicyAuthorize // Conditional expansion of this file
4 #include "Policy_spt_fp.h"
5 TPM_RC
6 TPM2_PolicyAuthorize(
7 PolicyAuthorize_In *in // IN: input parameter list
8 )
9 {
10 SESSION *session;
11 TPM2B_DIGEST authHash;
12 HASH_STATE hashState;
13 TPMT_TK_VERIFIED ticket;
14 TPM_ALG_ID hashAlg;
15 UINT16 digestSize;
16
17 // Input Validation
18
19 // Get pointer to the session structure
20 session = SessionGet(in->policySession);
21
22 // Extract from the Name of the key, the algorithm used to compute it's Name
23 hashAlg = BYTE_ARRAY_TO_UINT16(in->keySign.t.name);
24
25 // 'keySign' parameter needs to use a supported hash algorithm, otherwise
26 // can't tell how large the digest should be
27 if(!CryptHashIsValidAlg(hashAlg, FALSE))
28 return TPM_RCS_HASH + RC_PolicyAuthorize_keySign;
29
30 digestSize = CryptHashGetDigestSize(hashAlg);
31 if(digestSize != (in->keySign.t.size - 2))
32 return TPM_RCS_SIZE + RC_PolicyAuthorize_keySign;
33
34 //If this is a trial policy, skip all validations
35 if(session->attributes.isTrialPolicy == CLEAR)
36 {
37 // Check that "approvedPolicy" matches the current value of the
38 // policyDigest in policy session
39 if(!MemoryEqual2B(&session->u2.policyDigest.b,
40 &in->approvedPolicy.b))
41 return TPM_RCS_VALUE + RC_PolicyAuthorize_approvedPolicy;
42
43 // Validate ticket TPMT_TK_VERIFIED
44 // Compute aHash. The authorizing object sign a digest
45 // aHash := hash(approvedPolicy || policyRef).
46 // Start hash
47 authHash.t.size = CryptHashStart(&hashState, hashAlg);
48
49 // add approvedPolicy
50 CryptDigestUpdate2B(&hashState, &in->approvedPolicy.b);
51
52 // add policyRef
53 CryptDigestUpdate2B(&hashState, &in->policyRef.b);
54
55 // complete hash
56 CryptHashEnd2B(&hashState, &authHash.b);
57
58 // re-compute TPMT_TK_VERIFIED
59 TicketComputeVerified(in->checkTicket.hierarchy, &authHash,
60 &in->keySign, &ticket);
61
62 // Compare ticket digest. If not match, return error
63 if(!MemoryEqual2B(&in->checkTicket.digest.b, &ticket.digest.b))
64 return TPM_RCS_VALUE + RC_PolicyAuthorize_checkTicket;
65 }
66
67 // Internal Data Update
68
69 // Set policyDigest to zero digest
70 PolicyDigestClear(session);
71
72 // Update policyDigest
73 PolicyContextUpdate(TPM_CC_PolicyAuthorize, &in->keySign, &in->policyRef,
74 NULL, 0, session);
75
76 return TPM_RC_SUCCESS;
77 }
78 #endif // CC_PolicyAuthorize
23.17 TPM2_PolicyAuthValue
General Description
This command allows a policy to be bound to the authorization value of the authorized entity.
When this command completes successfully, policySession→isAuthValueNeeded is SET to indicate that
the authValue will be included in hmacKey when the authorization HMAC is computed for the command
being authorized using this session. Additionally, policySession→isPasswordNeeded will be CLEAR.
NOTE If a policy does not use this command, then the hmacKey for the authorized command would only
use sessionKey. If sessionKey is not present, then the hmacKey is an Empty Buffer and no HMAC
would be computed.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyAuthValue_fp.h"
3 #if CC_PolicyAuthValue // Conditional expansion of this file
4 #include "Policy_spt_fp.h"
5 TPM_RC
6 TPM2_PolicyAuthValue(
7 PolicyAuthValue_In *in // IN: input parameter list
8 )
9 {
10 SESSION *session;
11 TPM_CC commandCode = TPM_CC_PolicyAuthValue;
12 HASH_STATE hashState;
13
14 // Internal Data Update
15
16 // Get pointer to the session structure
17 session = SessionGet(in->policySession);
18
19 // Update policy hash
20 // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue)
21 // Start hash
22 CryptHashStart(&hashState, session->authHashAlg);
23
24 // add old digest
25 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
26
27 // add commandCode
28 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
29
30 // complete the hash and get the results
31 CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
32
33 // update isAuthValueNeeded bit in the session context
34 session->attributes.isAuthValueNeeded = SET;
35 session->attributes.isPasswordNeeded = CLEAR;
36
37 return TPM_RC_SUCCESS;
38 }
39 #endif // CC_PolicyAuthValue
23.18 TPM2_PolicyPassword
General Description
This command allows a policy to be bound to the authorization value of the authorized object.
When this command completes successfully, policySession→isPasswordNeeded is SET to indicate that
authValue of the authorized object will be checked when the session is used for authorization. The caller
will provide the authValue in clear text in the hmac parameter of the authorization. The comparison of
hmac to authValue is performed as if the authorization is a password.
NOTE 1 The parameter field in the policy session where the authorization value is provided is called hmac. If
TPM2_PolicyPassword() is part of the sequence, then the field will contain a password and not an
HMAC.
NOTE 2 This is the same extend value as used with TPM2_PolicyAuthValue so that the evaluation may be
done using either an HMAC or a password with no change to the authPolicy of the object. The
reason that two commands are present is to indicate to the TPM if the hmac field in the authorization
will contain an HMAC or a password value.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyPassword_fp.h"
3 #if CC_PolicyPassword // Conditional expansion of this file
4 #include "Policy_spt_fp.h"
5 TPM_RC
6 TPM2_PolicyPassword(
7 PolicyPassword_In *in // IN: input parameter list
8 )
9 {
10 SESSION *session;
11 TPM_CC commandCode = TPM_CC_PolicyAuthValue;
12 HASH_STATE hashState;
13
14 // Internal Data Update
15
16 // Get pointer to the session structure
17 session = SessionGet(in->policySession);
18
19 // Update policy hash
20 // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue)
21 // Start hash
22 CryptHashStart(&hashState, session->authHashAlg);
23
24 // add old digest
25 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
26
27 // add commandCode
28 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
29
30 // complete the digest
31 CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
32
33 // Update isPasswordNeeded bit
34 session->attributes.isPasswordNeeded = SET;
35 session->attributes.isAuthValueNeeded = CLEAR;
36
37 return TPM_RC_SUCCESS;
38 }
39 #endif // CC_PolicyPassword
23.19 TPM2_PolicyGetDigest
General Description
This command returns the current policyDigest of the session. This command allows the TPM to be used
to perform the actions required to pre-compute the authPolicy for an object.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyGetDigest_fp.h"
3 #if CC_PolicyGetDigest // Conditional expansion of this file
4 TPM_RC
5 TPM2_PolicyGetDigest(
6 PolicyGetDigest_In *in, // IN: input parameter list
7 PolicyGetDigest_Out *out // OUT: output parameter list
8 )
9 {
10 SESSION *session;
11
12 // Command Output
13
14 // Get pointer to the session structure
15 session = SessionGet(in->policySession);
16
17 out->policyDigest = session->u2.policyDigest;
18
19 return TPM_RC_SUCCESS;
20 }
21 #endif // CC_PolicyGetDigest
23.20 TPM2_PolicyNvWritten
General Description
This command allows a policy to be bound to the TPMA_NV_WRITTEN attributes. This is a deferred
assertion. Values are stored in the policy session context and checked when the policy is used for
authorization.
If policySession→checkNVWritten is CLEAR, it is SET and policySession→nvWrittenState is set to
writtenSet. If policySession→checkNVWritten is SET, the TPM will return TPM_RC_VALUE if
policySession→nvWrittenState and writtenSet are not the same.
If the TPM does not return an error, it will update policySession→policyDigest by
policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyNvWritten || writtenSet) (38)
When the policy session is used to authorize a command, the TPM will fail the command if
policySession→checkNVWritten is SET and nvIndex→attributes→TPMA_NV_WRITTEN does not match
policySession→nvWrittenState.
NOTE 1 A typical use case is a simple policy for the first write during manufacturing provisioning that would
require TPMA_NV_WRITTEN CLEAR and a more complex policy for later use that would require
TPMA_NV_WRITTEN SET.
NOTE 2 When an Index is written, it has a different authorization name than an Inde x that has not been
written. It is possible to use this change in the NV Index to create a write -once Index.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyNvWritten_fp.h"
3 #if CC_PolicyNvWritten // Conditional expansion of this file
Make an NV Index policy dependent on the state of the TPMA_NV_WRITTEN attribute of the index.
4 TPM_RC
5 TPM2_PolicyNvWritten(
6 PolicyNvWritten_In *in // IN: input parameter list
7 )
8 {
9 SESSION *session;
10 TPM_CC commandCode = TPM_CC_PolicyNvWritten;
11 HASH_STATE hashState;
12
13 // Input Validation
14
15 // Get pointer to the session structure
16 session = SessionGet(in->policySession);
17
18 // If already set is this a duplicate (the same setting)? If it
19 // is a conflicting setting, it is an error
20 if(session->attributes.checkNvWritten == SET)
21 {
22 if(((session->attributes.nvWrittenState == SET)
23 != (in->writtenSet == YES)))
24 return TPM_RCS_VALUE + RC_PolicyNvWritten_writtenSet;
25 }
26
27 // Internal Data Update
28
29 // Set session attributes so that the NV Index needs to be checked
30 session->attributes.checkNvWritten = SET;
31 session->attributes.nvWrittenState = (in->writtenSet == YES);
32
33 // Update policy hash
34 // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNvWritten
35 // || writtenSet)
36 // Start hash
37 CryptHashStart(&hashState, session->authHashAlg);
38
39 // add old digest
40 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
41
42 // add commandCode
43 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
44
45 // add the byte of writtenState
46 CryptDigestUpdateInt(&hashState, sizeof(TPMI_YES_NO), in->writtenSet);
47
48 // complete the digest
49 CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
50
51 return TPM_RC_SUCCESS;
52 }
53 #endif // CC_PolicyNvWritten
23.21 TPM2_PolicyTemplate
General Description
This command allows a policy to be bound to a specific creation template. This is most useful for an
object creation command such as TPM2_Create(), TPM2_CreatePrimary(), or TPM2_CreateLoaded().
The templateHash parameter should contain the digest of the template that will be required for the
inPublic parameter of an Object creation command.
If policySession→isTemplateHash is SET and policySession→cpHash is not equal to templateHash, the
TPM shall return TPM_RC_VALUE.
NOTE 1 Revision 01.38 of this specification permitted the TPM to return TPM_RC_CPHASH.
NOTE 2 Revision 01.38 of this specification permitted the TPM to return TPM_RC_VALUE.
If the size of templateHash is not the size of policySession→policyDigest, the TPM shall return
TPM_RC_SIZE. Otherwise, policySession→cpHash is set to templateHash.
NOTE 3 The digest calculation includes the TPM2B buffer but not the TPM2B size.
If this command completes successfully, the cpHash of the authorized command will not be used for
validation. Only the digest of the inPublic parameter will be used.
NOTE 4 This allows the space normally used to hold policySession→cpHash to be used for
policySession→templateHash instead.
Detailed Actions
1 #include "Tpm.h"
2 #include "PolicyTemplate_fp.h"
3 #if CC_PolicyTemplate // Conditional expansion of this file
4 TPM_RC
5 TPM2_PolicyTemplate(
6 PolicyTemplate_In *in // IN: input parameter list
7 )
8 {
9 SESSION *session;
10 TPM_CC commandCode = TPM_CC_PolicyTemplate;
11 HASH_STATE hashState;
12
13 // Input Validation
14
15 // Get pointer to the session structure
16 session = SessionGet(in->policySession);
17
18 // If the template is set, make sure that it is the same as the input value
19 if(session->attributes.isTemplateSet)
20 {
21 if(!MemoryEqual2B(&in->templateHash.b, &session->u1.cpHash.b))
22 return TPM_RCS_VALUE + RC_PolicyTemplate_templateHash;
23 }
24 // error if cpHash contains something that is not a template
25 else if(session->u1.templateHash.t.size != 0)
26 return TPM_RC_CPHASH;
27
28 // A valid templateHash must have the same size as session hash digest
29 if(in->templateHash.t.size != CryptHashGetDigestSize(session->authHashAlg))
30 return TPM_RCS_SIZE + RC_PolicyTemplate_templateHash;
31
32 // Internal Data Update
33 // Update policy hash
34 // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCpHash
35 // || cpHashA.buffer)
36 // Start hash
37 CryptHashStart(&hashState, session->authHashAlg);
38
39 // add old digest
40 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
41
42 // add commandCode
43 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
44
45 // add cpHashA
46 CryptDigestUpdate2B(&hashState, &in->templateHash.b);
47
48 // complete the digest and get the results
49 CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
50
51 // update cpHash in session context
52 session->u1.templateHash = in->templateHash;
53 session->attributes.isTemplateSet = SET;
54
55 return TPM_RC_SUCCESS;
56 }
57 #endif // CC_PolicyTemplateHash
23.22 TPM2_PolicyAuthorizeNV
General Description
This command provides a capability that is the equivalent of a revocable policy. With
TPM2_PolicyAuthorize(), the authorization ticket never expires, so the authorization may not be
withdrawn. With this command, the approved policy is kept in an NV Index location so that the policy may
be changed as needed to render the old policy unusable.
NOTE 1 This command is useful for Objects but of limited value for other policies that are persistently stored
in TPM NV, such as the OwnerPolicy.
NOTE 2 If read access is controlled by policy, the poli cy should include a branch that authorizes a
TPM2_PolicyAuthorizeNV().
If TPMA_NV_WRITTEN is not SET in the Index referenced by nvIndex, the TPM shall return
TPM_RC_NV_UNINITIALIZED. If TPMA_NV_READLOCKED of the NV Index is SET, then the TPM shall
return TPM_RC_NV_LOCKED.
The dataSize of the NV Index referenced by nvIndex is required to be at least large enough to hold a
properly formatted TPMT_HA (TPM_RC_INSUFFICIENT).
NOTE 3 A TPMT_HA contains a TPM_ALG_ID followed a digest that is consistent in size with the hash
algorithm indicated by the TPM_ALG_ID.
It is an error (TPM_RC_HASH) if the first two octets of the Index are not a TPM_ALG_ID for a hash
algorithm implemented on the TPM or if the indicated hash algorithm does not match
policySession→authHash.
NOTE 4 The TPM_ALG_ID is stored in the first two oc tets in big endian format.
The TPM will compare policySession→policyDigest to the contents of the NV Index, starting at the first
octet after the TPM_ALG_ID (the third octet) and return TPM_RC_VALUE if they are not the same.
NOTE 5 If the Index does not contain enough bytes for the compare, then TPM_RC_INSUFFICENT is
generated as indicated above.
NOTE 6 The dataSize of the Index may be larger than is required for this command. This permits the Index to
include metadata.
If the comparison is successful, the TPM will reset policySession→policyDigest to a Zero Digest. Then it
will update policySession→policyDigest with
policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_PolicyAuthorizeNV || nvIndex→Name) (40)
UINT32 commandSize
UINT32 responseSize
TPM_RC responseCode
Detailed Actions
1 #include "Tpm.h"
2 #if CC_PolicyAuthorizeNV // Conditional expansion of this file
3 #include "PolicyAuthorizeNV_fp.h"
4 #include "Policy_spt_fp.h"
5 TPM_RC
6 TPM2_PolicyAuthorizeNV(
7 PolicyAuthorizeNV_In *in
8 )
9 {
10 SESSION *session;
11 TPM_RC result;
12 NV_REF locator;
13 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
14 TPM2B_NAME name;
15 TPMT_HA policyInNv;
16 BYTE nvTemp[sizeof(TPMT_HA)];
17 BYTE *buffer = nvTemp;
18 INT32 size;
19
20 // Input Validation
21 // Get pointer to the session structure
22 session = SessionGet(in->policySession);
23
24 // Skip checks if this is a trial policy
25 if(!session->attributes.isTrialPolicy)
26 {
27 // Check the authorizations for reading
28 // Common read access checks. NvReadAccessChecks() returns
29 // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED
30 // error may be returned at this point
31 result = NvReadAccessChecks(in->authHandle, in->nvIndex,
32 nvIndex->publicArea.attributes);
33 if(result != TPM_RC_SUCCESS)
34 return result;
35
36 // Read the contents of the index into a temp buffer
37 size = MIN(nvIndex->publicArea.dataSize, sizeof(TPMT_HA));
38 NvGetIndexData(nvIndex, locator, 0, (UINT16)size, nvTemp);
39
40 // Unmarshal the contents of the buffer into the internal format of a
41 // TPMT_HA so that the hash and digest elements can be accessed from the
42 // structure rather than the byte array that is in the Index (written by
43 // user of the Index).
44 result = TPMT_HA_Unmarshal(&policyInNv, &buffer, &size, FALSE);
45 if(result != TPM_RC_SUCCESS)
46 return result;
47
48 // Verify that the hash is the same
49 if(policyInNv.hashAlg != session->authHashAlg)
50 return TPM_RC_HASH;
51
52 // See if the contents of the digest in the Index matches the value
53 // in the policy
54 if(!MemoryEqual(&policyInNv.digest, &session->u2.policyDigest.t.buffer,
55 session->u2.policyDigest.t.size))
56 return TPM_RC_VALUE;
57 }
58
59 // Internal Data Update
60
61 // Set policyDigest to zero digest
62 PolicyDigestClear(session);
63
64 // Update policyDigest
65 PolicyContextUpdate(TPM_CC_PolicyAuthorizeNV, EntityGetName(in->nvIndex, &name),
66 NULL, NULL, 0, session);
67
68 return TPM_RC_SUCCESS;
69 }
70 #endif // CC_PolicyAuthorize
24 Hierarchy Commands
24.1 TPM2_CreatePrimary
General Description
This command is used to create a Primary Object under one of the Primary Seeds or a Temporary Object
under TPM_RH_NULL. The command uses a TPM2B_PUBLIC as a template for the object to be created.
The size of the unique field shall not be checked for consistency with the other object parameters. The
command will create and load a Primary Object. The sensitive area is not returned.
NOTE 1 Since the sensitive data is not returned, the key cannot be reloaded. It can either be made
persistent or it can be recreated.
NOTE 2 For interoperability, the unique field should not be set to a value that is larger than allowed by object
parameters, so that the unmarshaling will not fail.
EXAMPLE 1 A TPM_ALG_RSA object with a keyBits of 2048 in the objects parameters should have a unique field
that is no larger than 256 bytes.
Any type of object and attributes combination that is allowed by TPM2_Create() may be created by this
command. The constraints on templates and parameters are the same as TPM2_Create() except that a
Primary Storage Key and a Temporary Storage Key are not constrained to use the algorithms of their
parents.
For setting of the attributes of the created object, fixedParent, fixedTPM, decrypt, and restricted are
implied to be SET in the parent (a Permanent Handle). The remaining attributes are implied to be CLEAR.
The TPM will derive the object from the Primary Seed indicated in primaryHandle using an approved
KDF. All of the bits of the template are used in the creation of the Primary Key. Methods for creating a
Primary Object from a Primary Seed are described in TPM 2.0 Part 1 and implemented in TPM 2.0 Part 4.
If this command is called multiple times with the same inPublic parameter, inSensitive.data, and Primary
Seed, the TPM shall produce the same Primary Object.
NOTE 4 If the Primary Seed is changed, the Primary Objects generated with the new seed shall be
statistically unique even if the parameters of the call are the same.
This command requires authorization. Authorization for a Primary Object attached to the Platform Primary
Seed (PPS) shall be provided by platformAuth or platformPolicy. Authorization for a Primary Object
attached to the Storage Primary Seed (SPS) shall be provided by ownerAuth or ownerPolicy.
Authorization for a Primary Key attached to the Endorsement Primary Seed (EPS) shall be provided by
endorsementAuth or endorsementPolicy.
TPM_RH_ENDORSEMENT, TPM_RH_OWNER,
TPM_RH_PLATFORM+{PP}, or TPM_RH_NULL
TPMI_RH_HIERARCHY+ @primaryHandle
Auth Index: 1
Auth Role: USER
TPM2B_SENSITIVE_CREATE inSensitive the sensitive data, see TPM 2.0 Part 1 Sensitive Values
TPM2B_PUBLIC inPublic the public template
data that will be included in the creation data for this
TPM2B_DATA outsideInfo object to provide permanent, verifiable linkage between
this object and some object owner data
TPML_PCR_SELECTION creationPCR PCR that will be used in creation data
Detailed Actions
1 #include "Tpm.h"
2 #include "CreatePrimary_fp.h"
3 #if CC_CreatePrimary // Conditional expansion of this file
4 TPM_RC
5 TPM2_CreatePrimary(
6 CreatePrimary_In *in, // IN: input parameter list
7 CreatePrimary_Out *out // OUT: output parameter list
8 )
9 {
10 TPM_RC result = TPM_RC_SUCCESS;
11 TPMT_PUBLIC *publicArea;
12 DRBG_STATE rand;
13 OBJECT *newObject;
14 TPM2B_NAME name;
15
16 // Input Validation
17 // Will need a place to put the result
18 newObject = FindEmptyObjectSlot(&out->objectHandle);
19 if(newObject == NULL)
20 return TPM_RC_OBJECT_MEMORY;
21 // Get the address of the public area in the new object
22 // (this is just to save typing)
23 publicArea = &newObject->publicArea;
24
25 *publicArea = in->inPublic.publicArea;
26
27 // Check attributes in input public area. CreateChecks() checks the things that
28 // are unique to creation and then validates the attributes and values that are
29 // common to create and load.
30 result = CreateChecks(NULL, publicArea,
31 in->inSensitive.sensitive.data.t.size);
32 if(result != TPM_RC_SUCCESS)
33 return RcSafeAddToResult(result, RC_CreatePrimary_inPublic);
34 // Validate the sensitive area values
35 if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth,
36 publicArea->nameAlg))
37 return TPM_RCS_SIZE + RC_CreatePrimary_inSensitive;
38 // Command output
39 // Compute the name using out->name as a scratch area (this is not the value
40 // that ultimately will be returned, then instantiate the state that will be
41 // used as a random number generator during the object creation.
42 // The caller does not know the seed values so the actual name does not have
43 // to be over the input, it can be over the unmarshaled structure.
44 result = DRBG_InstantiateSeeded(&rand,
45 &HierarchyGetPrimarySeed(in->primaryHandle)->b,
46 PRIMARY_OBJECT_CREATION,
47 (TPM2B *)PublicMarshalAndComputeName(publicArea, &name),
48 &in->inSensitive.sensitive.data.b);
49 if(result == TPM_RC_SUCCESS)
50 {
51 newObject->attributes.primary = SET;
52 if(in->primaryHandle == TPM_RH_ENDORSEMENT)
53 newObject->attributes.epsHierarchy = SET;
54
55 // Create the primary object.
56 result = CryptCreateObject(newObject, &in->inSensitive.sensitive,
57 (RAND_STATE *)&rand);
58 }
59 if(result != TPM_RC_SUCCESS)
60 return result;
61
62 // Set the publicArea and name from the computed values
63 out->outPublic.publicArea = newObject->publicArea;
64 out->name = newObject->name;
65
66 // Fill in creation data
67 FillInCreationData(in->primaryHandle, publicArea->nameAlg,
68 &in->creationPCR, &in->outsideInfo, &out->creationData,
69 &out->creationHash);
70
71 // Compute creation ticket
72 TicketComputeCreation(EntityGetHierarchy(in->primaryHandle), &out->name,
73 &out->creationHash, &out->creationTicket);
74
75 // Set the remaining attributes for a loaded object
76 ObjectSetLoadedAttributes(newObject, in->primaryHandle);
77 return result;
78 }
79 #endif // CC_CreatePrimary
24.2 TPM2_HierarchyControl
General Description
This command enables and disables use of a hierarchy and its associated NV storage. The command
allows phEnable, phEnableNV, shEnable, and ehEnable to be changed when the proper authorization is
provided.
This command may be used to CLEAR phEnable and phEnableNV if platformAuth/platformPolicy is
provided. phEnable may not be SET using this command.
This command may be used to CLEAR shEnable if either platformAuth/platformPolicy or
ownerAuth/ownerPolicy is provided. shEnable may be SET if platformAuth/platformPolicy is provided.
This command may be used to CLEAR ehEnable if either platformAuth/platformPolicy or
endorsementAuth/endorsementPolicy is provided. ehEnable may be SET if platformAuth/platformPolicy is
provided.
When this command is used to CLEAR phEnable, shEnable, or ehEnable, the TPM will disable use of
any persistent entity associated with the disabled hierarchy and will flush any transient objects associated
with the disabled hierarchy.
When this command is used to CLEAR shEnable, the TPM will disable access to any NV index that has
TPMA_NV_PLATFORMCREATE CLEAR (indicating that the NV Index was defined using Owner
Authorization). As long as shEnable is CLEAR, the TPM will return an error in response to any command
that attempts to operate upon an NV index that has TPMA_NV_PLATFORMCREATE CLEAR.
When this command is used to CLEAR phEnableNV, the TPM will disable access to any NV index that
has TPMA_NV_PLATFORMCREATE SET (indicating that the NV Index was defined using Platform
Authorization). As long as phEnableNV is CLEAR, the TPM will return an error in response to any
command that attempts to operate upon an NV index that has TPMA_NV_PLATFORMCREATE SET.
UINT32 commandSize
TPM_RH_ENDORSEMENT, TPM_RH_OWNER or
TPM_RH_PLATFORM+{PP}
TPMI_RH_HIERARCHY @authHandle
Auth Index: 1
Auth Role: USER
UINT32 responseSize
TPM_RC responseCode
Detailed Actions
1 #include "Tpm.h"
2 #include "HierarchyControl_fp.h"
3 #if CC_HierarchyControl // Conditional expansion of this file
4 TPM_RC
5 TPM2_HierarchyControl(
6 HierarchyControl_In *in // IN: input parameter list
7 )
8 {
9 BOOL select = (in->state == YES);
10 BOOL *selected = NULL;
11
12 // Input Validation
13 switch(in->enable)
14 {
15 // Platform hierarchy has to be disabled by PlatformAuth
16 // If the platform hierarchy has already been disabled, only a reboot
17 // can enable it again
18 case TPM_RH_PLATFORM:
19 case TPM_RH_PLATFORM_NV:
20 if(in->authHandle != TPM_RH_PLATFORM)
21 return TPM_RC_AUTH_TYPE;
22 break;
23
24 // ShEnable may be disabled if PlatformAuth/PlatformPolicy or
25 // OwnerAuth/OwnerPolicy is provided. If ShEnable is disabled, then it
26 // may only be enabled if PlatformAuth/PlatformPolicy is provided.
27 case TPM_RH_OWNER:
28 if(in->authHandle != TPM_RH_PLATFORM
29 && in->authHandle != TPM_RH_OWNER)
30 return TPM_RC_AUTH_TYPE;
31 if(gc.shEnable == FALSE && in->state == YES
32 && in->authHandle != TPM_RH_PLATFORM)
33 return TPM_RC_AUTH_TYPE;
34 break;
35
36 // EhEnable may be disabled if either PlatformAuth/PlatformPolicy or
37 // EndosementAuth/EndorsementPolicy is provided. If EhEnable is disabled,
38 // then it may only be enabled if PlatformAuth/PlatformPolicy is
39 // provided.
40 case TPM_RH_ENDORSEMENT:
41 if(in->authHandle != TPM_RH_PLATFORM
42 && in->authHandle != TPM_RH_ENDORSEMENT)
43 return TPM_RC_AUTH_TYPE;
44 if(gc.ehEnable == FALSE && in->state == YES
45 && in->authHandle != TPM_RH_PLATFORM)
46 return TPM_RC_AUTH_TYPE;
47 break;
48 default:
49 FAIL(FATAL_ERROR_INTERNAL);
50 break;
51 }
52
53 // Internal Data Update
54
55 // Enable or disable the selected hierarchy
56 // Note: the authorization processing for this command may keep these
24.3 TPM2_SetPrimaryPolicy
General Description
This command allows setting of the authorization policy for the lockout (lockoutPolicy), the platform
hierarchy (platformPolicy), the storage hierarchy (ownerPolicy), and the endorsement hierarchy
(endorsementPolicy). On TPMs implementing Authenticated Countdown Timers (ACT), this command
may also be used to set the authorization policy for an ACT.
The command requires an authorization session. The session shall use the current authValue or satisfy
the current authPolicy for the referenced hierarchy, or the ACT.
The policy that is changed is the policy associated with authHandle.
If the enable associated with authHandle is not SET, then the associated authorization values (authValue
or authPolicy) may not be used, and the TPM returns TPM_RC_HIERARCHY.
When hashAlg is not TPM_ALG_NULL, if the size of authPolicy is not consistent with the hash algorithm,
the TPM returns TPM_RC_SIZE.
UINT32 commandSize
TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT,
TPM_RH_OWNER, TPMI_RH_ACT or
TPMI_RH_HIERARCHY_POLICY @authHandle TPM_RH_PLATFORM+{PP}
Auth Index: 1
Auth Role: USER
UINT32 responseSize
TPM_RC responseCode
Detailed Actions
1 #include "Tpm.h"
2 #include "SetPrimaryPolicy_fp.h"
3 #if CC_SetPrimaryPolicy // Conditional expansion of this file
4 TPM_RC
5 TPM2_SetPrimaryPolicy(
6 SetPrimaryPolicy_In *in // IN: input parameter list
7 )
8 {
9 // Input Validation
10
11 // Check the authPolicy consistent with hash algorithm. If the policy size is
12 // zero, then the algorithm is required to be TPM_ALG_NULL
13 if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg))
14 return TPM_RCS_SIZE + RC_SetPrimaryPolicy_authPolicy;
15
16 // The command need NV update for OWNER and ENDORSEMENT hierarchy, and
17 // might need orderlyState update for PLATFROM hierarchy.
18 // Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE
19 // error may be returned at this point
20 RETURN_IF_NV_IS_NOT_AVAILABLE;
21
22 // Internal Data Update
23
24 // Set hierarchy policy
25 switch(in->authHandle)
26 {
27 case TPM_RH_OWNER:
28 gp.ownerAlg = in->hashAlg;
29 gp.ownerPolicy = in->authPolicy;
30 NV_SYNC_PERSISTENT(ownerAlg);
31 NV_SYNC_PERSISTENT(ownerPolicy);
32 break;
33 case TPM_RH_ENDORSEMENT:
34 gp.endorsementAlg = in->hashAlg;
35 gp.endorsementPolicy = in->authPolicy;
36 NV_SYNC_PERSISTENT(endorsementAlg);
37 NV_SYNC_PERSISTENT(endorsementPolicy);
38 break;
39 case TPM_RH_PLATFORM:
40 gc.platformAlg = in->hashAlg;
41 gc.platformPolicy = in->authPolicy;
42 // need to update orderly state
43 g_clearOrderly = TRUE;
44 break;
45 case TPM_RH_LOCKOUT:
46 gp.lockoutAlg = in->hashAlg;
47 gp.lockoutPolicy = in->authPolicy;
48 NV_SYNC_PERSISTENT(lockoutAlg);
49 NV_SYNC_PERSISTENT(lockoutPolicy);
50 break;
51
52 #define SET_ACT_POLICY(N) \
53 case TPM_RH_ACT_##N: \
54 go.ACT_##N.hashAlg = in->hashAlg; \
55 go.ACT_##N.authPolicy = in->authPolicy; \
56 g_clearOrderly = TRUE; \
57 break;
58
59 FOR_EACH_ACT(SET_ACT_POLICY)
60
61 default:
62 FAIL(FATAL_ERROR_INTERNAL);
63 break;
64 }
65
66 return TPM_RC_SUCCESS;
67 }
68 #endif // CC_SetPrimaryPolicy
24.4 TPM2_ChangePPS
General Description
This replaces the current platform primary seed (PPS) with a value from the RNG and sets platformPolicy
to the default initialization value (the Empty Buffer).
All resident transient and persistent objects in the Platform hierarchy are flushed.
Saved contexts in the Platform hierarchy that were created under the old PPS will no longer be able to be
loaded.
The policy hash algorithm for PCR is reset to TPM_ALG_NULL.
This command does not clear any NV Index values.
NOTE 3 Index values belonging to the Platform are preserved because the indexes may have configuration
information that will be the same after the PPS changes. The Platform may remove the inde xes that
are no longer needed using TPM2_NV_UndefineSpace().
TPM_RH_PLATFORM+{PP}
TPMI_RH_PLATFORM @authHandle Auth Index: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "ChangePPS_fp.h"
3 #if CC_ChangePPS // Conditional expansion of this file
4 TPM_RC
5 TPM2_ChangePPS(
6 ChangePPS_In *in // IN: input parameter list
7 )
8 {
9 UINT32 i;
10
11 // Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE
12 // error may be returned at this point
13 RETURN_IF_NV_IS_NOT_AVAILABLE;
14
15 // Input parameter is not reference in command action
16 NOT_REFERENCED(in);
17
18 // Internal Data Update
19
20 // Reset platform hierarchy seed from RNG
21 CryptRandomGenerate(sizeof(gp.PPSeed.t.buffer), gp.PPSeed.t.buffer);
22
23 // Create a new phProof value from RNG to prevent the saved platform
24 // hierarchy contexts being loaded
25 CryptRandomGenerate(sizeof(gp.phProof.t.buffer), gp.phProof.t.buffer);
26
27 // Set platform authPolicy to null
28 gc.platformAlg = TPM_ALG_NULL;
29 gc.platformPolicy.t.size = 0;
30
31 // Flush loaded object in platform hierarchy
32 ObjectFlushHierarchy(TPM_RH_PLATFORM);
33
34 // Flush platform evict object and index in NV
35 NvFlushHierarchy(TPM_RH_PLATFORM);
36
37 // Save hierarchy changes to NV
38 NV_SYNC_PERSISTENT(PPSeed);
39 NV_SYNC_PERSISTENT(phProof);
40
41 // Re-initialize PCR policies
42 #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0
43 for(i = 0; i < NUM_POLICY_PCR_GROUP; i++)
44 {
45 gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL;
46 gp.pcrPolicies.policy[i].t.size = 0;
47 }
48 NV_SYNC_PERSISTENT(pcrPolicies);
49 #endif
50
51 // orderly state should be cleared because of the update to state clear data
52 g_clearOrderly = TRUE;
53
54 return TPM_RC_SUCCESS;
55 }
56 #endif // CC_ChangePPS
24.5 TPM2_ChangeEPS
General Description
This replaces the current endorsement primary seed (EPS) with a value from the RNG and sets the
Endorsement hierarchy controls to their default initialization values: ehEnable is SET, endorsementAuth
and endorsementPolicy are both set to the Empty Buffer. It will flush any resident objects (transient or
persistent) in the Endorsement hierarchy and not allow objects in the hierarchy associated with the
previous EPS to be loaded.
NOTE In the reference implementation, ehProof is a non-volatile value from the RNG. It is allowed that the
ehProof be generated by a KDF using both the EPS and SPS as inputs. If generated with a KDF, the
ehProof can be generated on an as-needed basis or made a non-volatile value.
TPM_RH_PLATFORM+{PP}
TPMI_RH_PLATFORM @authHandle Auth Handle: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "ChangeEPS_fp.h"
3 #if CC_ChangeEPS // Conditional expansion of this file
4 TPM_RC
5 TPM2_ChangeEPS(
6 ChangeEPS_In *in // IN: input parameter list
7 )
8 {
9 // The command needs NV update. Check if NV is available.
10 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
11 // this point
12 RETURN_IF_NV_IS_NOT_AVAILABLE;
13
14 // Input parameter is not reference in command action
15 NOT_REFERENCED(in);
16
17 // Internal Data Update
18
19 // Reset endorsement hierarchy seed from RNG
20 CryptRandomGenerate(sizeof(gp.EPSeed.t.buffer), gp.EPSeed.t.buffer);
21
22 // Create new ehProof value from RNG
23 CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer);
24
25 // Enable endorsement hierarchy
26 gc.ehEnable = TRUE;
27
28 // set authValue buffer to zeros
29 MemorySet(gp.endorsementAuth.t.buffer, 0, gp.endorsementAuth.t.size);
30 // Set endorsement authValue to null
31 gp.endorsementAuth.t.size = 0;
32
33 // Set endorsement authPolicy to null
34 gp.endorsementAlg = TPM_ALG_NULL;
35 gp.endorsementPolicy.t.size = 0;
36
37 // Flush loaded object in endorsement hierarchy
38 ObjectFlushHierarchy(TPM_RH_ENDORSEMENT);
39
40 // Flush evict object of endorsement hierarchy stored in NV
41 NvFlushHierarchy(TPM_RH_ENDORSEMENT);
42
43 // Save hierarchy changes to NV
44 NV_SYNC_PERSISTENT(EPSeed);
45 NV_SYNC_PERSISTENT(ehProof);
46 NV_SYNC_PERSISTENT(endorsementAuth);
47 NV_SYNC_PERSISTENT(endorsementAlg);
48 NV_SYNC_PERSISTENT(endorsementPolicy);
49
50 // orderly state should be cleared because of the update to state clear data
51 g_clearOrderly = TRUE;
52
53 return TPM_RC_SUCCESS;
54 }
55 #endif // CC_ChangeEPS
24.6 TPM2_Clear
General Description
This command removes all TPM context associated with a specific Owner.
The clear operation will:
• flush resident objects (persistent and volatile) in the Storage and Endorsement hierarchies;
• delete any NV Index with TPMA_NV_PLATFORMCREATE == CLEAR;
• change the storage primary seed (SPS) to a new value from the TPM’s random number generator
(RNG),
• change shProof and ehProof,
NOTE 1 The proof values may be set from the RNG or derived from the associated new Primary Seed. If
derived from the Primary Seeds, the derivation of ehProof shall use both the SPS and EPS. The
computation shall use the SPS as an HMAC key and the derived value ma y then be a parameter
in a second HMAC in which the EPS is the HMAC key. The reference design uses values from
the RNG.
NOTE 2 This permits an application to create a policy session that is invalidated on TPM2_Clear. The
policy needs, ideally as the first term, TPM2_PolicyPCR(). The session is invalidated even if the
PCR selection is empty.
TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}
TPMI_RH_CLEAR @authHandle Auth Handle: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "Clear_fp.h"
3 #if CC_Clear // Conditional expansion of this file
4 TPM_RC
5 TPM2_Clear(
6 Clear_In *in // IN: input parameter list
7 )
8 {
9 // Input parameter is not reference in command action
10 NOT_REFERENCED(in);
11
12 // The command needs NV update. Check if NV is available.
13 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
14 // this point
15 RETURN_IF_NV_IS_NOT_AVAILABLE;
16
17 // Input Validation
18
19 // If Clear command is disabled, return an error
20 if(gp.disableClear)
21 return TPM_RC_DISABLED;
22
23 // Internal Data Update
24
25 // Reset storage hierarchy seed from RNG
26 CryptRandomGenerate(sizeof(gp.SPSeed.t.buffer), gp.SPSeed.t.buffer);
27
28 // Create new shProof and ehProof value from RNG
29 CryptRandomGenerate(sizeof(gp.shProof.t.buffer), gp.shProof.t.buffer);
30 CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer);
31
32 // Enable storage and endorsement hierarchy
33 gc.shEnable = gc.ehEnable = TRUE;
34
35 // set the authValue buffers to zero
36 MemorySet(&gp.ownerAuth, 0, sizeof(gp.ownerAuth));
37 MemorySet(&gp.endorsementAuth, 0, sizeof(gp.endorsementAuth));
38 MemorySet(&gp.lockoutAuth, 0, sizeof(gp.lockoutAuth));
39
40 // Set storage, endorsement, and lockout authPolicy to null
41 gp.ownerAlg = gp.endorsementAlg = gp.lockoutAlg = TPM_ALG_NULL;
42 MemorySet(&gp.ownerPolicy, 0, sizeof(gp.ownerPolicy));
43 MemorySet(&gp.endorsementPolicy, 0, sizeof(gp.endorsementPolicy));
44 MemorySet(&gp.lockoutPolicy, 0, sizeof(gp.lockoutPolicy));
45
46 // Flush loaded object in storage and endorsement hierarchy
47 ObjectFlushHierarchy(TPM_RH_OWNER);
48 ObjectFlushHierarchy(TPM_RH_ENDORSEMENT);
49
50 // Flush owner and endorsement object and owner index in NV
51 NvFlushHierarchy(TPM_RH_OWNER);
52 NvFlushHierarchy(TPM_RH_ENDORSEMENT);
53
54 // Initialize dictionary attack parameters
55 DAPreInstall_Init();
56
57 // Reset clock
58 go.clock = 0;
59 go.clockSafe = YES;
60 NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go);
61
62 // Reset counters
63 gp.resetCount = gr.restartCount = gr.clearCount = 0;
64 gp.auditCounter = 0;
65
66 // Save persistent data changes to NV
67 // Note: since there are so many changes to the persistent data structure, the
68 // entire PERSISTENT_DATA structure is written as a unit
69 NvWrite(NV_PERSISTENT_DATA, sizeof(PERSISTENT_DATA), &gp);
70
71 // Reset the PCR authValues (this does not change the PCRs)
72 PCR_ClearAuth();
73
74 // Bump the PCR counter
75 PCRChanged(0);
76
77 // orderly state should be cleared because of the update to state clear data
78 g_clearOrderly = TRUE;
79
80 return TPM_RC_SUCCESS;
81 }
82 #endif // CC_Clear
24.7 TPM2_ClearControl
General Description
NOTE This is to simplify the logic of TPM2_Clear(). TPM2_ClearControl() can be called using Platform
Authorization to CLEAR the disableClear attribute and then execute TPM2_Clear().
Lockout Authorization may be used to SET disableClear but not to CLEAR it.
Platform Authorization may be used to SET or CLEAR disableClear.
TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP}
TPMI_RH_CLEAR @auth Auth Handle: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "ClearControl_fp.h"
3 #if CC_ClearControl // Conditional expansion of this file
4 TPM_RC
5 TPM2_ClearControl(
6 ClearControl_In *in // IN: input parameter list
7 )
8 {
9 // The command needs NV update.
10 RETURN_IF_NV_IS_NOT_AVAILABLE;
11
12 // Input Validation
13
14 // LockoutAuth may be used to set disableLockoutClear to TRUE but not to FALSE
15 if(in->auth == TPM_RH_LOCKOUT && in->disable == NO)
16 return TPM_RC_AUTH_FAIL;
17
18 // Internal Data Update
19
20 if(in->disable == YES)
21 gp.disableClear = TRUE;
22 else
23 gp.disableClear = FALSE;
24
25 // Record the change to NV
26 NV_SYNC_PERSISTENT(disableClear);
27
28 return TPM_RC_SUCCESS;
29 }
30 #endif // CC_ClearControl
24.8 TPM2_HierarchyChangeAuth
General Description
This command allows the authorization secret for a hierarchy or lockout to be changed using the current
authorization value as the command authorization.
If authHandle is TPM_RH_PLATFORM, then platformAuth is changed. If authHandle is
TPM_RH_OWNER, then ownerAuth is changed. If authHandle is TPM_RH_ENDORSEMENT, then
endorsementAuth is changed. If authHandle is TPM_RH_LOCKOUT, then lockoutAuth is changed. The
HMAC in the response shall use the new authorization value when computing the response HMAC.
If authHandle is TPM_RH_PLATFORM, then Physical Presence may need to be asserted for this
command to succeed (see 26.2, TPM2_PP_Commands).
The authorization value may be no larger than the digest produced by the hash algorithm used for context
integrity.
EXAMPLE If SHA384 is used in the computation of the int egrity values for saved contexts, then the largest
authorization value is 48 octets.
TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT,
TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
TPMI_RH_HIERARCHY_AUTH @authHandle
Auth Index: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "HierarchyChangeAuth_fp.h"
3 #if CC_HierarchyChangeAuth // Conditional expansion of this file
4 #include "Object_spt_fp.h"
5 TPM_RC
6 TPM2_HierarchyChangeAuth(
7 HierarchyChangeAuth_In *in // IN: input parameter list
8 )
9 {
10 // The command needs NV update.
11 RETURN_IF_NV_IS_NOT_AVAILABLE;
12
13 // Make sure that the authorization value is a reasonable size (not larger than
14 // the size of the digest produced by the integrity hash. The integrity
15 // hash is assumed to produce the longest digest of any hash implemented
16 // on the TPM. This will also remove trailing zeros from the authValue.
17 if(MemoryRemoveTrailingZeros(&in->newAuth) > CONTEXT_INTEGRITY_HASH_SIZE)
18 return TPM_RCS_SIZE + RC_HierarchyChangeAuth_newAuth;
19
20 // Set hierarchy authValue
21 switch(in->authHandle)
22 {
23 case TPM_RH_OWNER:
24 gp.ownerAuth = in->newAuth;
25 NV_SYNC_PERSISTENT(ownerAuth);
26 break;
27 case TPM_RH_ENDORSEMENT:
28 gp.endorsementAuth = in->newAuth;
29 NV_SYNC_PERSISTENT(endorsementAuth);
30 break;
31 case TPM_RH_PLATFORM:
32 gc.platformAuth = in->newAuth;
33 // orderly state should be cleared
34 g_clearOrderly = TRUE;
35 break;
36 case TPM_RH_LOCKOUT:
37 gp.lockoutAuth = in->newAuth;
38 NV_SYNC_PERSISTENT(lockoutAuth);
39 break;
40 default:
41 FAIL(FATAL_ERROR_INTERNAL);
42 break;
43 }
44
45 return TPM_RC_SUCCESS;
46 }
47 #endif // CC_HierarchyChangeAuth
25.1 Introduction
A TPM is required to have support for logic that will help prevent a dictionary attack on an authorization
value. The protection is provided by a counter that increments when a password authorization or an
HMAC authorization fails. When the counter reaches a predefined value, the TPM will not accept, for
some time interval, further requests that require authorization and the TPM is in Lockout mode. While the
TPM is in Lockout mode, the TPM will return TPM_RC_LOCKOUT if the command requires use of an
object’s or Index’s authValue unless the authorization applies to an entry in the Platform hierarchy.
NOTE 1 Authorizations for objects and NV Index values in the Platform hierarchy are never locked out.
However, a command that requires multiple authorizations will not be accepted when the TPM is in
Lockout mode unless all of the authorizations reference objects and indexes in t he Platform
hierarchy.
If the TPM is continuously powered for the duration of newRecoveryTime and no authorization failures
occur, the authorization failure counter will be decremented by one. This property is called “self-healing.”
Self-healing shall not cause the count of failed attempts to decrement below zero.
The count of failed attempts, the lockout interval, and self-healing interval are settable using
TPM2_DictionaryAttackParameters(). The lockout parameters and the current value of the lockout
counter can be read with TPM2_GetCapability().
Dictionary attack protection does not apply to an entity associated with a permanent handle (handle type ==
TPM_HT_PERMANENT) other than TPM_RH_LOCKOUT
25.2 TPM2_DictionaryAttackLockReset
General Description
This command cancels the effect of a TPM lockout due to a number of successive authorization failures.
If this command is properly authorized, the lockout counter is set to zero.
Only one lockoutAuth authorization failure is allowed for this command during a lockoutRecovery interval
(set using TPM2_DictionaryAttackParameters().
TPM_RH_LOCKOUT
TPMI_RH_LOCKOUT @lockHandle Auth Index: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "DictionaryAttackLockReset_fp.h"
3 #if CC_DictionaryAttackLockReset // Conditional expansion of this file
4 TPM_RC
5 TPM2_DictionaryAttackLockReset(
6 DictionaryAttackLockReset_In *in // IN: input parameter list
7 )
8 {
9 // Input parameter is not reference in command action
10 NOT_REFERENCED(in);
11
12 // The command needs NV update.
13 RETURN_IF_NV_IS_NOT_AVAILABLE;
14
15 // Internal Data Update
16
17 // Set failed tries to 0
18 gp.failedTries = 0;
19
20 // Record the changes to NV
21 NV_SYNC_PERSISTENT(failedTries);
22
23 return TPM_RC_SUCCESS;
24 }
25 #endif // CC_DictionaryAttackLockReset
25.3 TPM2_DictionaryAttackParameters
General Description
NOTE Use of Time means that the TPM shall be continuously powered for the duration of a timeout.
If newRecoveryTime is zero, then DA protection is disabled. Authorizations are checked but authorization
failures will not cause the TPM to enter lockout.
If newMaxTries is zero, the TPM will be in lockout and use of DA protected entities will be disabled.
If lockoutRecovery is zero, then the recovery interval is _TPM_Init followed by TPM2_Startup().
Only one lockoutAuth authorization failure is allowed for this command during a lockoutRecovery interval.
TPM_RH_LOCKOUT
TPMI_RH_LOCKOUT @lockHandle Auth Index: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "DictionaryAttackParameters_fp.h"
3 #if CC_DictionaryAttackParameters // Conditional expansion of this file
4 TPM_RC
5 TPM2_DictionaryAttackParameters(
6 DictionaryAttackParameters_In *in // IN: input parameter list
7 )
8 {
9 // The command needs NV update.
10 RETURN_IF_NV_IS_NOT_AVAILABLE;
11
12 // Internal Data Update
13
14 // Set dictionary attack parameters
15 gp.maxTries = in->newMaxTries;
16 gp.recoveryTime = in->newRecoveryTime;
17 gp.lockoutRecovery = in->lockoutRecovery;
18
19 #if 0 // Errata eliminates this code
20 // This functionality has been disabled. The preferred implementation is now
21 // to leave failedTries unchanged when the parameters are changed. This could
22 // have the effect of putting the TPM into DA lockout if in->newMaxTries is
23 // not greater than the current value of gp.failedTries.
24 // Set failed tries to 0
25 gp.failedTries = 0;
26 #endif
27
28 // Record the changes to NV
29 NV_SYNC_PERSISTENT(failedTries);
30 NV_SYNC_PERSISTENT(maxTries);
31 NV_SYNC_PERSISTENT(recoveryTime);
32 NV_SYNC_PERSISTENT(lockoutRecovery);
33
34 return TPM_RC_SUCCESS;
35 }
36 #endif // CC_DictionaryAttackParameters
26.1 Introduction
This clause contains commands that do not logically group with any other commands.
26.2 TPM2_PP_Commands
General Description
This command is used to determine which commands require assertion of Physical Presence (PP) in
addition to platformAuth/platformPolicy.
This command requires that auth is TPM_RH_PLATFORM and that Physical Presence be asserted.
After this command executes successfully, the commands listed in setList will be added to the list of
commands that require that Physical Presence be asserted when the handle associated with the
authorization is TPM_RH_PLATFORM. The commands in clearList will no longer require assertion of
Physical Presence in order to authorize a command.
If a command is not in either list, its state is not changed. If a command is in both lists, then it will no
longer require Physical Presence (for example, setList is processed first).
Only commands with handle types of TPMI_RH_PLATFORM, TPMI_RH_PROVISION,
TPMI_RH_CLEAR, or TPMI_RH_HIERARCHY can be gated with Physical Presence. If any other
command is in either list, it is discarded.
When a command requires that Physical Presence be provided, then Physical Presence shall be
asserted for either an HMAC or a Policy authorization.
NOTE 2 If the TPM does not implement this command, the command list is vendor specific . A platform-
specific specification may require that the command list be initialized in a specific way.
TPM_RH_PLATFORM+PP
TPMI_RH_PLATFORM @auth Auth Index: 1
Auth Role: USER + Physical Presence
Detailed Actions
1 #include "Tpm.h"
2 #include "PP_Commands_fp.h"
3 #if CC_PP_Commands // Conditional expansion of this file
4 TPM_RC
5 TPM2_PP_Commands(
6 PP_Commands_In *in // IN: input parameter list
7 )
8 {
9 UINT32 i;
10
11 // The command needs NV update. Check if NV is available.
12 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
13 // this point
14 RETURN_IF_NV_IS_NOT_AVAILABLE;
15
16 // Internal Data Update
17
18 // Process set list
19 for(i = 0; i < in->setList.count; i++)
20 // If command is implemented, set it as PP required. If the input
21 // command is not a PP command, it will be ignored at
22 // PhysicalPresenceCommandSet().
23 // Note: PhysicalPresenceCommandSet() checks if the command is implemented.
24 PhysicalPresenceCommandSet(in->setList.commandCodes[i]);
25
26 // Process clear list
27 for(i = 0; i < in->clearList.count; i++)
28 // If command is implemented, clear it as PP required. If the input
29 // command is not a PP command, it will be ignored at
30 // PhysicalPresenceCommandClear(). If the input command is
31 // TPM2_PP_Commands, it will be ignored as well
32 PhysicalPresenceCommandClear(in->clearList.commandCodes[i]);
33
34 // Save the change of PP list
35 NV_SYNC_PERSISTENT(ppList);
36
37 return TPM_RC_SUCCESS;
38 }
39 #endif // CC_PP_Commands
26.3 TPM2_SetAlgorithmSet
General Description
This command allows the platform to change the set of algorithms that are used by the TPM. The
algorithmSet setting is a vendor-dependent value.
If the changing of the algorithm set results in a change of the algorithms of PCR banks, then the TPM will
need to be reset (_TPM_Init and TPM2_Startup(TPM_SU_CLEAR)) before the new PCR settings take
effect. After this command executes successfully, if startupType in the next TPM2_Startup() is not
TPM_SU_CLEAR, the TPM shall return TPM_RC_VALUE and may enter Failure mode.
Other than PCR, when an algorithm is no longer supported, the behavior of this command is vendor-
dependent.
EXAMPLE Entities may remain resident. Persistent objects, transient objects, or sessions may be flushed . NV
Indexes may be undefined. Policies may be erased.
NOTE The reference implementation does not have support for this command. In particular, it does not
support use of this command to selectively disable algorithms. Proper support would require
modification of the unmarshaling code so that each time an algorithm is unmarshaled, it would be
verified as being enabled.
TPM_RH_PLATFORM
TPMI_RH_PLATFORM @authHandle Auth Index: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "SetAlgorithmSet_fp.h"
3 #if CC_SetAlgorithmSet // Conditional expansion of this file
4 TPM_RC
5 TPM2_SetAlgorithmSet(
6 SetAlgorithmSet_In *in // IN: input parameter list
7 )
8 {
9 // The command needs NV update. Check if NV is available.
10 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
11 // this point
12 RETURN_IF_NV_IS_NOT_AVAILABLE;
13
14 // Internal Data Update
15 gp.algorithmSet = in->algorithmSet;
16
17 // Write the algorithm set changes to NV
18 NV_SYNC_PERSISTENT(algorithmSet);
19
20 return TPM_RC_SUCCESS;
21 }
22 #endif // CC_SetAlgorithmSet
27 Field Upgrade
27.1 Introduction
This clause contains the commands for managing field upgrade of the firmware in the TPM. The field
upgrade scheme may be used for replacement or augmentation of the firmware installed in the TPM.
EXAMPLE 1 If an algorithm is found to be flawed, a patch of that algorithm might be installed using the firmware
upgrade process. The patch might be a replacement of a portion of the code or a complete
replacement of the firmware.
EXAMPLE 2 If an additional set of ECC parameters is needed, the firmware process may be used to add the
parameters to the TPM data set.
NOTE 1 The platformPolicy for field upgraded is defined by the PM and may include requirements that the
upgrade be signed by the PM or the TPM owner and include any other constraints that are desired
by the PM.
If the proper authorization is given, the TPM will retain the signed digest and enter the Field Upgrade
mode (FUM). While in FUM, the TPM will accept TPM2_FieldUpgradeData() commands. It may accept
other commands if it is able to complete them using the previously installed firmware. Otherwise, it will
return TPM_RC_UPGRADE.
Each block of the field upgrade shall contain the digest of the next block of the field upgrade data. That
digest shall be included in the digest of the previous block. The digest of the first block is signed by the
TPM manufacturer. That signature and first block digest are the parameters for
TPM2_FieldUpgradeStart(). The digest is saved in the TPM as the required digest for the next field
upgrade data block and as the identifier of the field upgrade sequence.
For each field upgrade data block that is sent to the TPM by TPM2_FieldUpgradeData(), the TPM shall
validate that the digest matches the required digest and if not, shall return TPM_RC_VALUE. The TPM
shall extract the digest of the next expected block and return that value to the caller, along with the digest
of the first data block of the update sequence.
The system may attempt to abandon the firmware upgrade by using a zero-length buffer in
TPM2_FieldUpdateData(). If the TPM is able to resume operation using the firmware present when the
upgrade started, then the TPM will indicate that it has abandon the update by setting the digest of the
next block to the Empty Buffer. If the TPM cannot abandon the update, it will return the expected next
digest.
The system may also attempt to abandon the update because of a power interruption. If the TPM is able
to resume normal operations, then it will respond normally to TPM2_Startup(). If the TPM is not able to
resume normal operations, then it will respond to any command but TPM2_FieldUpgradeData() with
TPM_RC_UPGRADE.
After a _TPM_Init, system software may not be able to resume the field upgrade that was in process
when the power interruption occurred. In such case, the TPM firmware may be reset to one of two other
values:
• the original firmware that was installed at the factory (“initial firmware”); or
• the firmware that was in the TPM when the field upgrade process started (“previous firmware”).
The TPM retains the digest of the first block for these firmware images and checks to see if the first block
after _TPM_Init matches either of those digests. If so, the firmware update process restarts and the
original firmware may be loaded.
NOTE 2 The TPM is required to accept the previous firmware as either a vendor -provided update or as
recovered from the TPM using TPM2_FirmwareRead().
When the last block of the firmware upgrade is loaded into the TPM (indicated to the TPM by data in the
data block in a TPM vendor-specific manner), the TPM will complete the upgrade process. If the TPM is
able to resume normal operations without a reboot, it will set the hash algorithm of the next block to
TPM_ALG_NULL and return TPM_RC_SUCCESS. If a reboot is required, the TPM shall return
TPM_RC_REBOOT in response to the last TPM2_FieldUpgradeData() and all subsequent TPM
commands until a _TPM_Init is received.
NOTE 3 Because no additional data is allowed when the response code is not TPM_RC_SUC CESS, the TPM
returns TPM_RC_SUCCESS for all calls to TPM2_FieldUpgradeData() except the last. In this
manner, the TPM is able to indicate the digest of the next block. If a _TPM_Init occurs while the
TPM is in FUM, the next block may be the digest for the first block of the original firmware. If it is
not, then the TPM will not accept the original firmware until the next _TPM_Init when the TPM is in
FUM.
During the field upgrade process, either the one specified in this clause or a vendor proprietary field
upgrade process, the TPM should preserve:
• Primary Seeds;
• Hierarchy authValue, authPolicy, and proof values;
• Lockout authValue and authorization failure count values;
• PCR authValue and authPolicy values;
• NV Index allocations and contents;
• Persistent object allocations and contents; and
• Clock.
NOTE 4 A platform manufacturer may provide a means to change preserved data to accommodate a case
where a field upgrade fixes a flaw that might have compromised TPM secrets.
27.2 TPM2_FieldUpgradeStart
General Description
This command uses platformPolicy and a TPM Vendor Authorization Key to authorize a Field Upgrade
Manifest.
If the signature checks succeed, the authorization is valid and the TPM will accept
TPM2_FieldUpgradeData().
This signature is checked against the loaded key referenced by keyHandle. This key will have a Name
that is the same as a value that is part of the TPM firmware data. If the signature is not valid, the TPM
shall return TPM_RC_SIGNATURE.
NOTE A loaded key is used rather than a hard -coded key to reduce the amount of memory needed for this
key data in case more than one vendor key is needed.
TPM_RH_PLATFORM+{PP}
TPMI_RH_PLATFORM @authorization Auth Index:1
Auth Role: ADMIN
handle of a public area that contains the TPM Vendor
Authorization Key that will be used to validate
TPMI_DH_OBJECT keyHandle manifestSignature
Auth Index: None
TPM2B_DIGEST fuDigest digest of the first block in the field upgrade sequence
signature over fuDigest using the key associated with
TPMT_SIGNATURE manifestSignature
keyHandle (not optional)
Detailed Actions
1 #include "Tpm.h"
2 #include "FieldUpgradeStart_fp.h"
3 #if CC_FieldUpgradeStart // Conditional expansion of this file
4 TPM_RC
5 TPM2_FieldUpgradeStart(
6 FieldUpgradeStart_In *in // IN: input parameter list
7 )
8 {
9 // Not implemented
10 UNUSED_PARAMETER(in);
11 return TPM_RC_SUCCESS;
12 }
13 #endif
27.3 TPM2_FieldUpgradeData
General Description
This command will take the actual field upgrade image to be installed on the TPM. The exact format of
fuData is vendor-specific. This command is only possible following a successful
TPM2_FieldUpgradeStart(). If the TPM has not received a properly authorized
TPM2_FieldUpgradeStart(), then the TPM shall return TPM_RC_FIELDUPGRADE.
The TPM will validate that the digest of fuData matches an expected value. If so, the TPM may buffer or
immediately apply the update. If the digest of fuData does not match an expected value, the TPM shall
return TPM_RC_VALUE.
Detailed Actions
1 #include "Tpm.h"
2 #include "FieldUpgradeData_fp.h"
3 #if CC_FieldUpgradeData // Conditional expansion of this file
4 TPM_RC
5 TPM2_FieldUpgradeData(
6 FieldUpgradeData_In *in, // IN: input parameter list
7 FieldUpgradeData_Out *out // OUT: output parameter list
8 )
9 {
10 // Not implemented
11 UNUSED_PARAMETER(in);
12 UNUSED_PARAMETER(out);
13 return TPM_RC_SUCCESS;
14 }
15 #endif
27.4 TPM2_FirmwareRead
General Description
This command is used to read a copy of the current firmware installed in the TPM.
The presumption is that the data will be returned in reverse order so that the last block in the sequence
would be the first block given to the TPM in case of a failure recovery. If the TPM2_FirmwareRead
sequence completes successfully, then the data provided from the TPM will be sufficient to allow the TPM
to recover from an abandoned upgrade of this firmware.
To start the sequence of retrieving the data, the caller sets sequenceNumber to zero. When the TPM has
returned all the firmware data, the TPM will return the Empty Buffer as fuData.
The contents of fuData are opaque to the caller.
NOTE 1 The caller should retain the ordering of the update blocks so that the blocks sent to the TPM have
the same size and inverse order as the blocks returned by a sequence of calls to this command.
NOTE 2 Support for this command is optional even if the TPM implements TPM2_Field UpgradeStart() and
TPM2_FieldUpgradeData().
Detailed Actions
1 #include "Tpm.h"
2 #include "FirmwareRead_fp.h"
3 #if CC_FirmwareRead // Conditional expansion of this file
4 TPM_RC
5 TPM2_FirmwareRead(
6 FirmwareRead_In *in, // IN: input parameter list
7 FirmwareRead_Out *out // OUT: output parameter list
8 )
9 {
10 // Not implemented
11 UNUSED_PARAMETER(in);
12 UNUSED_PARAMETER(out);
13 return TPM_RC_SUCCESS;
14 }
15 #endif // CC_FirmwareRead
28 Context Management
28.1 Introduction
28.2 TPM2_ContextSave
General Description
This command saves a session context, object context, or sequence object context outside the TPM.
No authorization sessions of any type are allowed with this command and tag is required to be
TPM_ST_NO_SESSIONS.
NOTE This preclusion avoids complex issues of dealing with the same session in handle and in the session
area. While it might be possible to provide specificity, it would add unnecessary complexity to the
TPM and, because this capability would provide no application benefit, use of authorization sessions
for audit or encryption is prohibited.
The TPM shall encrypt and integrity protect the TPM2B_CONTEXT_SENSITIVE context as described in
the "Context Protections" clause in TPM 2.0 Part 1.
See the “Context Data” clause in TPM 2.0 Part 2 for a description of the context structure in the response.
TPMS_CONTEXT context
Detailed Actions
1 #include "Tpm.h"
2 #include "ContextSave_fp.h"
3 #if CC_ContextSave // Conditional expansion of this file
4 #include "Context_spt_fp.h"
5 TPM_RC
6 TPM2_ContextSave(
7 ContextSave_In *in, // IN: input parameter list
8 ContextSave_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result = TPM_RC_SUCCESS;
12 UINT16 fingerprintSize; // The size of fingerprint in context
13 // blob.
14 UINT64 contextID = 0; // session context ID
15 TPM2B_SYM_KEY symKey;
16 TPM2B_IV iv;
17
18 TPM2B_DIGEST integrity;
19 UINT16 integritySize;
20 BYTE *buffer;
21
22 // This command may cause the orderlyState to be cleared due to
23 // the update of state reset data. If the state is orderly and
24 // cannot be changed, exit early.
25 RETURN_IF_ORDERLY;
26
27 // Internal Data Update
28
29 // This implementation does not do things in quite the same way as described in
30 // Part 2 of the specification. In Part 2, it indicates that the
31 // TPMS_CONTEXT_DATA contains two TPM2B values. That is not how this is
32 // implemented. Rather, the size field of the TPM2B_CONTEXT_DATA is used to
33 // determine the amount of data in the encrypted data. That part is not
34 // independently sized. This makes the actual size 2 bytes smaller than
35 // calculated using Part 2. Since this is opaque to the caller, it is not
36 // necessary to fix. The actual size is returned by TPM2_GetCapabilties().
37
38 // Initialize output handle. At the end of command action, the output
39 // handle of an object will be replaced, while the output handle
40 // for a session will be the same as input
41 out->context.savedHandle = in->saveHandle;
42
43 // Get the size of fingerprint in context blob. The sequence value in
44 // TPMS_CONTEXT structure is used as the fingerprint
45 fingerprintSize = sizeof(out->context.sequence);
46
47 // Compute the integrity size at the beginning of context blob
48 integritySize = sizeof(integrity.t.size)
49 + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
50
51 // Perform object or session specific context save
52 switch(HandleGetType(in->saveHandle))
53 {
54 case TPM_HT_TRANSIENT:
55 {
56 OBJECT *object = HandleToObject(in->saveHandle);
57 ANY_OBJECT_BUFFER *outObject;
58 UINT16 objectSize = ObjectIsSequence(object)
59 ? sizeof(HASH_OBJECT) : sizeof(OBJECT);
60
61 outObject = (ANY_OBJECT_BUFFER *)(out->context.contextBlob.t.buffer
62 + integritySize + fingerprintSize);
63
64 // Set size of the context data. The contents of context blob is vendor
65 // defined. In this implementation, the size is size of integrity
66 // plus fingerprint plus the whole internal OBJECT structure
67 out->context.contextBlob.t.size = integritySize +
68 fingerprintSize + objectSize;
69 #if ALG_RSA
70 // For an RSA key, make sure that the key has had the private exponent
71 // computed before saving.
72 if(object->publicArea.type == TPM_ALG_RSA &&
73 !(object->attributes.publicOnly))
74 CryptRsaLoadPrivateExponent(&object->publicArea, &object->sensitive);
75 #endif
76 // Make sure things fit
77 pAssert(out->context.contextBlob.t.size
78 <= sizeof(out->context.contextBlob.t.buffer));
79 // Copy the whole internal OBJECT structure to context blob
80 MemoryCopy(outObject, object, objectSize);
81
82 // Increment object context ID
83 gr.objectContextID++;
84 // If object context ID overflows, TPM should be put in failure mode
85 if(gr.objectContextID == 0)
86 FAIL(FATAL_ERROR_INTERNAL);
87
88 // Fill in other return values for an object.
89 out->context.sequence = gr.objectContextID;
90 // For regular object, savedHandle is 0x80000000. For sequence object,
91 // savedHandle is 0x80000001. For object with stClear, savedHandle
92 // is 0x80000002
93 if(ObjectIsSequence(object))
94 {
95 out->context.savedHandle = 0x80000001;
96 SequenceDataExport((HASH_OBJECT *)object,
97 (HASH_OBJECT_BUFFER *)outObject);
98 }
99 else
100 out->context.savedHandle = (object->attributes.stClear == SET)
101 ? 0x80000002 : 0x80000000;
102 // Get object hierarchy
103 out->context.hierarchy = ObjectGetHierarchy(object);
104
105 break;
106 }
107 case TPM_HT_HMAC_SESSION:
108 case TPM_HT_POLICY_SESSION:
109 {
110 SESSION *session = SessionGet(in->saveHandle);
111
112 // Set size of the context data. The contents of context blob is vendor
113 // defined. In this implementation, the size of context blob is the
114 // size of a internal session structure plus the size of
115 // fingerprint plus the size of integrity
116 out->context.contextBlob.t.size = integritySize +
117 fingerprintSize + sizeof(*session);
118
119 // Make sure things fit
120 pAssert(out->context.contextBlob.t.size
28.3 TPM2_ContextLoad
General Description
This command is used to reload a context that has been saved by TPM2_ContextSave().
No authorization sessions of any type are allowed with this command and tag is required to be
TPM_ST_NO_SESSIONS (see note in 28.2.1).
The TPM will return TPM_RC_HIERARCHY if the context is associated with a hierarchy that is disabled.
NOTE Contexts for authorization sessions and for sequence objects belong to the NULL hierarchy, which is
never disabled.
See the “Context Data” clause in TPM 2.0 Part 2 for a description of the values in the context parameter.
If the integrity HMAC of the saved context is not valid, the TPM shall return TPM_RC_INTEGRITY.
The TPM shall perform a check on the decrypted context as described in the "Context Confidentiality
Protection" clause of TPM 2.0 Part 1 and enter failure mode if the check fails.
Detailed Actions
1 #include "Tpm.h"
2 #include "ContextLoad_fp.h"
3 #if CC_ContextLoad // Conditional expansion of this file
4 #include "Context_spt_fp.h"
5 TPM_RC
6 TPM2_ContextLoad(
7 ContextLoad_In *in, // IN: input parameter list
8 ContextLoad_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result;
12 TPM2B_DIGEST integrityToCompare;
13 TPM2B_DIGEST integrity;
14 BYTE *buffer; // defined to save some typing
15 INT32 size; // defined to save some typing
16 TPM_HT handleType;
17 TPM2B_SYM_KEY symKey;
18 TPM2B_IV iv;
19
20 // Input Validation
21
22 // See discussion about the context format in TPM2_ContextSave Detailed Actions
23
24 // IF this is a session context, make sure that the sequence number is
25 // consistent with the version in the slot
26
27 // Check context blob size
28 handleType = HandleGetType(in->context.savedHandle);
29
30 // Get integrity from context blob
31 buffer = in->context.contextBlob.t.buffer;
32 size = (INT32)in->context.contextBlob.t.size;
33 result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);
34 if(result != TPM_RC_SUCCESS)
35 return result;
36
37 // the size of the integrity value has to match the size of digest produced
38 // by the integrity hash
39 if(integrity.t.size != CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG))
40 return TPM_RCS_SIZE + RC_ContextLoad_context;
41
42 // Make sure that the context blob has enough space for the fingerprint. This
43 // is elastic pants to go with the belt and suspenders we already have to make
44 // sure that the context is complete and untampered.
111
112 // Check if input handle points to a valid saved session and that the
113 // sequence number makes sense
114 if(!SequenceNumberForSavedContextIsValid(&in->context))
115 return TPM_RCS_HANDLE + RC_ContextLoad_context;
116
117 // Restore session. A TPM_RC_SESSION_MEMORY, TPM_RC_CONTEXT_GAP error
118 // may be returned at this point
119 result = SessionContextLoad((SESSION_BUF *)buffer,
120 &in->context.savedHandle);
121 if(result != TPM_RC_SUCCESS)
122 return result;
123
124 out->loadedHandle = in->context.savedHandle;
125
126 // orderly state should be cleared because of the update of state
127 // reset and state clear data
128 g_clearOrderly = TRUE;
129
130 break;
131 }
132 default:
133 // Context blob may only have an object handle or a session handle.
134 // All the other handle type should be filtered out at unmarshal
135 FAIL(FATAL_ERROR_INTERNAL);
136 break;
137 }
138
139 return TPM_RC_SUCCESS;
140 }
141 #endif // CC_ContextLoad
28.4 TPM2_FlushContext
General Description
This command causes all context associated with a loaded object, sequence object, or session to be
removed from TPM memory.
This command may not be used to remove a persistent object from the TPM. Use TPM2_EvictControl to
remove a persistent object.
A session does not have to be loaded in TPM memory to have its context flushed. The saved session
context associated with the indicated handle is invalidated. When flushing a session, the upper byte of the
handle is ignored.
EXAMPLE A command to flush session handle 0x20000000 will flush session handle 0x03000000.
No sessions of any type are allowed with this command and tag is required to be
TPM_ST_NO_SESSIONS (see note in 28.2.1).
If the handle is for a Transient Object and the handle is not associated with a loaded object, then the TPM
shall return TPM_RC_HANDLE.
If the handle is for an authorization session and the handle does not reference a loaded or active session,
then the TPM shall return TPM_RC_HANDLE.
NOTE flushHandle is a parameter and not a handle. If it were in the handle area, the TPM wo uld validate
that the context for the referenced entity is in the TPM. When a TPM2_FlushContext references a
saved session context, it is not necessary for the context to be in the TPM. When the flushHandle is
in the parameter area, the TPM does not validate that associated context is actually in the TPM.
Detailed Actions
1 #include "Tpm.h"
2 #include "FlushContext_fp.h"
3 #if CC_FlushContext // Conditional expansion of this file
4 TPM_RC
5 TPM2_FlushContext(
6 FlushContext_In *in // IN: input parameter list
7 )
8 {
9 // Internal Data Update
10
11 // Call object or session specific routine to flush
12 switch(HandleGetType(in->flushHandle))
13 {
14 case TPM_HT_TRANSIENT:
15 if(!IsObjectPresent(in->flushHandle))
16 return TPM_RCS_HANDLE + RC_FlushContext_flushHandle;
17 // Flush object
18 FlushObject(in->flushHandle);
19 break;
20 case TPM_HT_HMAC_SESSION:
21 case TPM_HT_POLICY_SESSION:
22 if(!SessionIsLoaded(in->flushHandle)
23 && !SessionIsSaved(in->flushHandle)
24 )
25 return TPM_RCS_HANDLE + RC_FlushContext_flushHandle;
26
27 // If the session to be flushed is the exclusive audit session, then
28 // indicate that there is no exclusive audit session any longer.
29 if(in->flushHandle == g_exclusiveAuditSession)
30 g_exclusiveAuditSession = TPM_RH_UNASSIGNED;
31
32 // Flush session
33 SessionFlush(in->flushHandle);
34 break;
35 default:
36 // This command only takes object or session handle. Other handles
37 // should be filtered out at handle unmarshal
38 FAIL(FATAL_ERROR_INTERNAL);
39 break;
40 }
41
42 return TPM_RC_SUCCESS;
43 }
44 #endif // CC_FlushContext
28.5 TPM2_EvictControl
General Description
This command allows certain Transient Objects to be made persistent or a persistent object to be evicted.
NOTE 1 A transient object is one that may be removed from TPM memory using either TPM2_FlushContext
or TPM2_Startup(). A persistent object is not removed from TPM memory by TPM2_FlushContext()
or TPM2_Startup().
If objectHandle is a Transient Object, then this call makes a persistent copy of the object and assigns
persistentHandle to the persistent version of the object. If objectHandle is a persistent object, then the call
evicts the persistent object. The call does not affect the transient object.
Before execution of TPM2_EvictControl code below, the TPM verifies that objectHandle references an
object that is resident on the TPM and that persistentHandle is a valid handle for a persistent object.
NOTE 2 This requirement simplifies the unmarshaling code so that it o nly need check that persistentHandle
is always a persistent object.
NOTE 3 This is for NV space efficiency. Loading an object whose private part is empty would
unnecessarily consume NV resources.
NOTE 4 This separation permits the platform (the platform OEM) a range of indexes that will not
interfere with indexes used by the TPM owner (the OS or applications).
The TPM shall return TPM_RC_NV_DEFINED if a persistent object exists with the same handle as
persistentHandle.
The TPM shall return TPM_RC_NV_SPACE if insufficient space is available to make the object
persistent.
The TPM shall return TPM_RC_NV_SPACE if execution of this command will prevent the TPM from
being able to hold two transient objects of any kind.
NOTE 5 This requirement anticipates that a TPM may be implemented such that all TPM memory is non -
volatile and not subject to endurance issues. In such case, there is no mo vement of an object
between memory of different types and it is necessary that the TPM ensure that it is always
possible for the management software to move objects to/from TPM memory in order to ensure
that the objects required for command execution can b e context restored.
If the TPM returns TPM_RC_SUCCESS, the object referenced by objectHandle will not be flushed
and both objectHandle and persistentHandle may be used to access the object.
If objectHandle references a persistent object:
The TPM shall return TPM_RC_RANGE if objectHandle is not in the proper range as determined by
auth. If auth is TPM_RC_OWNER, objectHandle shall be in the inclusive range of 81 00 00 0016 to
81 7F FF FF16. If auth is TPM_RC_PLATFORM, objectHandle may be any valid persistent object
handle.
If objectHandle is not the same value as persistentHandle, return TPM_RC_HANDLE.
If the TPM returns TPM_RC_SUCCESS, objectHandle will be removed from persistent memory and
no longer be accessible.
NOTE 5 The persistent object is not converted to a transient object, as this would prevent the immediate
revocation of an object by removing it from persistent memory.
TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
TPMI_RH_PROVISION @auth Auth Handle: 1
Auth Role: USER
the handle of a loaded object
TPMI_DH_OBJECT objectHandle
Auth Index: None
Detailed Actions
1 #include "Tpm.h"
2 #include "EvictControl_fp.h"
3 #if CC_EvictControl // Conditional expansion of this file
4 TPM_RC
5 TPM2_EvictControl(
6 EvictControl_In *in // IN: input parameter list
7 )
8 {
9 TPM_RC result;
10 OBJECT *evictObject;
11
12 // Input Validation
13
14 // Get internal object pointer
15 evictObject = HandleToObject(in->objectHandle);
16
17 // Temporary, stClear or public only objects can not be made persistent
18 if(evictObject->attributes.temporary == SET
19 || evictObject->attributes.stClear == SET
20 || evictObject->attributes.publicOnly == SET)
21 return TPM_RCS_ATTRIBUTES + RC_EvictControl_objectHandle;
22
23 // If objectHandle refers to a persistent object, it should be the same as
24 // input persistentHandle
25 if(evictObject->attributes.evict == SET
26 && evictObject->evictHandle != in->persistentHandle)
27 return TPM_RCS_HANDLE + RC_EvictControl_objectHandle;
28
29 // Additional authorization validation
30 if(in->auth == TPM_RH_PLATFORM)
31 {
32 // To make persistent
33 if(evictObject->attributes.evict == CLEAR)
34 {
35 // PlatformAuth can not set evict object in storage or endorsement
36 // hierarchy
37 if(evictObject->attributes.ppsHierarchy == CLEAR)
38 return TPM_RCS_HIERARCHY + RC_EvictControl_objectHandle;
39 // Platform cannot use a handle outside of platform persistent range.
40 if(!NvIsPlatformPersistentHandle(in->persistentHandle))
41 return TPM_RCS_RANGE + RC_EvictControl_persistentHandle;
42 }
43 // PlatformAuth can delete any persistent object
44 }
29.1 TPM2_ReadClock
General Description
This command reads the current TPMS_TIME_INFO structure that contains the current setting of Time,
Clock, resetCount, and restartCount.
TPMS_TIME_INFO currentTime
Detailed Actions
1 #include "Tpm.h"
2 #include "ReadClock_fp.h"
3 #if CC_ReadClock // Conditional expansion of this file
4 TPM_RC
5 TPM2_ReadClock(
6 ReadClock_Out *out // OUT: output parameter list
7 )
8 {
9 // Command Output
10
11 out->currentTime.time = g_time;
12 TimeFillInfo(&out->currentTime.clockInfo);
13
14 return TPM_RC_SUCCESS;
15 }
16 #endif // CC_ReadClock
29.2 TPM2_ClockSet
General Description
This command is used to advance the value of the TPM’s Clock. The command will fail if newTime is less
than the current value of Clock or if the new time is greater than FF FF 00 00 00 00 00 0016. If both of
these checks succeed, Clock is set to newTime. If either of these checks fails, the TPM shall return
TPM_RC_VALUE and make no change to Clock.
NOTE This maximum setting would prevent Clock from rolling over to zero for approximately 8,000 years at
the real time Clock update rate. If the Clock update rate was set so that TPM time was passing 33
percent faster than real time, it would still be more than 6,000 years before Clock would roll over to
zero. Because Clock will not roll over in the lifetime of the TPM, there is no need for external
software to deal with the possibility that Clock may wrap around.
If the value of Clock after the update makes the volatile and non-volatile versions of
TPMS_CLOCK_INFO.clock differ by more than the reported update interval, then the TPM shall update
the non-volatile version of TPMS_CLOCK_INFO.clock before returning.
This command requires Platform Authorization or Owner Authorization.
TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
TPMI_RH_PROVISION @auth Auth Handle: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "ClockSet_fp.h"
3 #if CC_ClockSet // Conditional expansion of this file
4 TPM_RC
5 TPM2_ClockSet(
6 ClockSet_In *in // IN: input parameter list
7 )
8 {
9 // Input Validation
10 // new time can not be bigger than 0xFFFF000000000000 or smaller than
11 // current clock
12 if(in->newTime > 0xFFFF000000000000ULL
13 || in->newTime < go.clock)
14 return TPM_RCS_VALUE + RC_ClockSet_newTime;
15
16 // Internal Data Update
17 // Can't modify the clock if NV is not available.
18 RETURN_IF_NV_IS_NOT_AVAILABLE;
19
20 TimeClockUpdate(in->newTime);
21 return TPM_RC_SUCCESS;
22 }
23 #endif // CC_ClockSet
29.3 TPM2_ClockRateAdjust
General Description
This command adjusts the rate of advance of Clock and Time to provide a better approximation to real
time.
The rateAdjust value is relative to the current rate and not the nominal rate of advance.
EXAMPLE 1 If this command had been called three times with rateAdjust = TPM_CLOCK_COARSE_SLOWER
and once with rateAdjust = TPM_CLOCK_COARSE_FASTER, the net effect will be as if the
command had been called twice with rateAdjust = TPM_CLOCK_COARSE_SLOWER.
The range of adjustment shall be sufficient to allow Clock and Time to advance at real time but no more.
If the requested adjustment would make the rate advance faster or slower than the nominal accuracy of
the input frequency, the TPM shall return TPM_RC_VALUE.
EXAMPLE 2 If the frequency tolerance of the TPM's input clock is +/ -10 percent, then the TPM will return
TPM_RC_VALUE if the adjustment would make Clock run more than 10 percent faster or slower than
nominal. That is, if the input oscillator were nominally 100 megah ertz (MHz), then 1 millisecond (ms)
would normally take 100,000 counts. The update Clock should be adjustable so that 1 ms is between
90,000 and 110,000 counts.
NOTE If the adjustments are incorrect, it will be possible to make t he difference between advance of
Clock/Time and real time to be as much as 1.15 2 or ~1.33.
Changes to the current Clock update rate adjustment need not be persisted across TPM power cycles.
TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
TPMI_RH_PROVISION @auth Auth Handle: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "ClockRateAdjust_fp.h"
3 #if CC_ClockRateAdjust // Conditional expansion of this file
4 TPM_RC
5 TPM2_ClockRateAdjust(
6 ClockRateAdjust_In *in // IN: input parameter list
7 )
8 {
9 // Internal Data Update
10 TimeSetAdjustRate(in->rateAdjust);
11
12 return TPM_RC_SUCCESS;
13 }
14 #endif // CC_ClockRateAdjust
30 Capability Commands
30.1 Introduction
The TPM has numerous values that indicate the state, capabilities, and properties of the TPM. These
values are needed for proper management of the TPM. The TPM2_GetCapability() command is used to
access these values.
TPM2_GetCapability() allows reporting of multiple values in a single call. The values are grouped
according to type.
30.2 TPM2_GetCapability
General Description
This command returns various information regarding the TPM and its current state.
The capability parameter determines the category of data returned. The property parameter selects the
first value of the selected category to be returned. If there is no property that corresponds to the value of
property, the next higher value is returned, if it exists.
EXAMPLE 1 The list of handles of transient objects currently loaded in the TPM may be read one at a time. On
the first read, set the property to TRANSIENT_FIRST and propertyCount to one. If a transient object
is present, the lowest numbered handle is returned and moreData will be YES if transient objects
with higher handles are loaded. On the subsequent call, use returned handle value plus 1 in order to
access the next higher handle.
The propertyCount parameter indicates the number of capabilities in the indicated group that are
requested. The TPM will return no more than the number of requested values (propertyCount) or until the
last property of the requested type has been returned.
NOTE 1 The type of the capability is derived from a combination of capability and property.
NOTE 2 If the property selects an unimplemented property, the next higher implemented property is returned.
When all of the properties of the requested type have been returned, the moreData parameter in the
response will be set to NO. Otherwise, it will be set to YES.
NOTE 3 The moreData parameter will be YES if there are more properties even if the requested number of
capabilities has been returned.
The TPM is not required to return more than one value at a time. It is not required to provide the same
number of values in response to subsequent requests.
When the TPM is in Failure mode, a TPM is required to allow use of this command for access of the
following capabilities:
• TPM_PT_MANUFACTURER
• TPM_PT_VENDOR_STRING_1
• TPM_PT_VENDOR_STRING_2 (NOTE 4)
• TPM_PT_VENDOR_STRING_3 (NOTE 4)
• TPM_PT_VENDOR_STRING_4 (NOTE 4)
• TPM_PT_VENDOR_TPM_TYPE
• TPM_PT_FIRMWARE_VERSION_1
• TPM_PT_FIRMWARE_VERSION_2
NOTE 4 If the vendor string does not require one of these va lues, the property type does not need to exist.
EXAMPLE 3 Assume the TPM is in Failure mode and the TPM only supports reporting of the minimum required
set of properties (the limited subset of TPML_TAGGED_TPM_PROPERTY values). If a
TPM2_GetCapability is received requesting a capability that has a property type value greater than
TPM_PT_FIRMWARE_VERSION_2, the TPM may return a zero length list with the moreData
parameter set to NO or return the property TPM_PT_FIRMWARE_VERSION_2. If the property type
is less than TPM_PT_MANUFACTURER, the TPM will return properties beginning with
TPM_PT_MANUFACTURER.
EXAMPLE 4 If the MSO of property is TPM_HT_NV_INDEX, then the TPM will return a list of NV Index
values.
EXAMPLE 5 If the MSO of property is TPM_HT_PCR, then the TPM will return a list of PCR.
• TPM_CAP_COMMANDS – Returns a list of the command attributes for all of the commands
implemented in the TPM, starting with the TPM_CC indicated by the property parameter. If vendor
specific commands are implemented, the vendor-specific command attribute with the lowest
commandIndex, is returned after the non-vendor-specific (base) command.
NOTE 6 The type of the property parameter is a TPM_CC while the type of the returned list is
TPML_CCA.
NOTE 7 A PCR index in all banks (all hash algorithms) has the same properties, so the hash algorithm is
not specified here.
• TPM_CAP_TPM_ECC_CURVES – Returns a list of ECC curve identifiers currently available for use
in the TPM.
• TPM_CAP_AUTH_POLICIES - Returns a list of tagged policies reporting the authorization policies for
the permanent handles.
• TPM_CAP_ACT – Returns a list of TPMS_ACT_DATA, each of which contains the handle for the
ACT, the remaining time before it expires, and the ACT attributes.
The moreData parameter will have a value of YES if there are more values of the requested type that
were not returned.
If no next capability exists, the TPM will return a zero-length list and moreData will have a value of NO.
TPMI_YES_NO moreData flag to indicate if there are more values of this type
TPMS_CAPABILITY_DATA capabilityData the capability data
Detailed Actions
1 #include "Tpm.h"
2 #include "GetCapability_fp.h"
3 #if CC_GetCapability // Conditional expansion of this file
4 TPM_RC
5 TPM2_GetCapability(
6 GetCapability_In *in, // IN: input parameter list
7 GetCapability_Out *out // OUT: output parameter list
8 )
9 {
10 TPMU_CAPABILITIES *data = &out->capabilityData.data;
11 // Command Output
12
13 // Set output capability type the same as input type
14 out->capabilityData.capability = in->capability;
15
16 switch(in->capability)
17 {
18 case TPM_CAP_ALGS:
19 out->moreData = AlgorithmCapGetImplemented((TPM_ALG_ID)in->property,
20 in->propertyCount,
21 &data->algorithms);
22 break;
23 case TPM_CAP_HANDLES:
24 switch(HandleGetType((TPM_HANDLE)in->property))
25 {
26 case TPM_HT_TRANSIENT:
27 // Get list of handles of loaded transient objects
28 out->moreData = ObjectCapGetLoaded((TPM_HANDLE)in->property,
29 in->propertyCount,
30 &data->handles);
31 break;
32 case TPM_HT_PERSISTENT:
33 // Get list of handles of persistent objects
34 out->moreData = NvCapGetPersistent((TPM_HANDLE)in->property,
35 in->propertyCount,
36 &data->handles);
37 break;
38 case TPM_HT_NV_INDEX:
39 // Get list of defined NV index
40 out->moreData = NvCapGetIndex((TPM_HANDLE)in->property,
41 in->propertyCount,
42 &data->handles);
43 break;
44 case TPM_HT_LOADED_SESSION:
45 // Get list of handles of loaded sessions
46 out->moreData = SessionCapGetLoaded((TPM_HANDLE)in->property,
47 in->propertyCount,
48 &data->handles);
49 break;
50 #ifdef TPM_HT_SAVED_SESSION
51 case TPM_HT_SAVED_SESSION:
52 #else
53 case TPM_HT_ACTIVE_SESSION:
54 #endif
55 // Get list of handles of
56 out->moreData = SessionCapGetSaved((TPM_HANDLE)in->property,
57 in->propertyCount,
58 &data->handles);
59 break;
60 case TPM_HT_PCR:
61 // Get list of handles of PCR
62 out->moreData = PCRCapGetHandles((TPM_HANDLE)in->property,
63 in->propertyCount,
64 &data->handles);
65 break;
66 case TPM_HT_PERMANENT:
67 // Get list of permanent handles
68 out->moreData = PermanentCapGetHandles((TPM_HANDLE)in->property,
69 in->propertyCount,
70 &data->handles);
71 break;
72 default:
73 // Unsupported input handle type
74 return TPM_RCS_HANDLE + RC_GetCapability_property;
75 break;
76 }
77 break;
78 case TPM_CAP_COMMANDS:
79 out->moreData = CommandCapGetCCList((TPM_CC)in->property,
80 in->propertyCount,
81 &data->command);
82 break;
83 case TPM_CAP_PP_COMMANDS:
84 out->moreData = PhysicalPresenceCapGetCCList((TPM_CC)in->property,
85 in->propertyCount,
86 &data->ppCommands);
87 break;
88 case TPM_CAP_AUDIT_COMMANDS:
89 out->moreData = CommandAuditCapGetCCList((TPM_CC)in->property,
90 in->propertyCount,
91 &data->auditCommands);
92 break;
93 case TPM_CAP_PCRS:
94 // Input property must be 0
95 if(in->property != 0)
96 return TPM_RCS_VALUE + RC_GetCapability_property;
97 out->moreData = PCRCapGetAllocation(in->propertyCount,
98 &data->assignedPCR);
99 break;
100 case TPM_CAP_PCR_PROPERTIES:
101 out->moreData = PCRCapGetProperties((TPM_PT_PCR)in->property,
102 in->propertyCount,
103 &data->pcrProperties);
104 break;
105 case TPM_CAP_TPM_PROPERTIES:
106 out->moreData = TPMCapGetProperties((TPM_PT)in->property,
107 in->propertyCount,
108 &data->tpmProperties);
109 break;
110 #if ALG_ECC
111 case TPM_CAP_ECC_CURVES:
112 out->moreData = CryptCapGetECCCurve((TPM_ECC_CURVE)in->property,
113 in->propertyCount,
114 &data->eccCurves);
115 break;
116 #endif // ALG_ECC
117 case TPM_CAP_AUTH_POLICIES:
118 if(HandleGetType((TPM_HANDLE)in->property) != TPM_HT_PERMANENT)
30.3 TPM2_TestParms
General Description
This command is used to check to see if specific combinations of algorithm parameters are supported.
The TPM will unmarshal the provided TPMT_PUBLIC_PARMS. If the parameters unmarshal correctly,
then the TPM will return TPM_RC_SUCCESS, indicating that the parameters are valid for the TPM. The
TPM will return the appropriate unmarshaling error if a parameter is not valid.
Detailed Actions
1 #include "Tpm.h"
2 #include "TestParms_fp.h"
3 #if CC_TestParms // Conditional expansion of this file
4 TPM_RC
5 TPM2_TestParms(
6 TestParms_In *in // IN: input parameter list
7 )
8 {
9 // Input parameter is not reference in command action
10 NOT_REFERENCED(in);
11
12 // The parameters are tested at unmarshal process. We do nothing in command
13 // action
14 return TPM_RC_SUCCESS;
15 }
16 #endif // CC_TestParms
31 Non-volatile Storage
31.1 Introduction
The NV commands are used to create, update, read, and delete allocations of space in NV memory.
Before an Index may be used, it must be defined (TPM2_NV_DefineSpace()).
An Index may be modified if the proper write authorization is provided or read if the proper read
authorization is provided. Different controls are available for reading and writing.
An Index may have an Index-specific authValue and authPolicy. The authValue may be used to authorize
reading if TPMA_NV_AUTHREAD is SET and writing if TPMA_NV_AUTHWRITE is SET. The authPolicy
may be used to authorize reading if TPMA_NV_POLICYREAD is SET and writing if
TPMA_NV_POLICYWRITE is SET.
For commands that have both authHandle and nvIndex parameters, authHandle can be an NV Index,
Platform Authorization, or Owner Authorization. If authHandle is an NV Index, it must be the same as
nvIndex (TPM_RC_NV_AUTHORIZATION).
TPMA_NV_PPREAD and TPMA_NV_PPWRITE indicate if reading or writing of the NV Index may be
authorized by platformAuth or platformPolicy.
TPMA_NV_OWNERREAD and TPMA_NV_OWNERWRITE indicate if reading or writing of the NV Index
may be authorized by ownerAuth or ownerPolicy.
If an operation on an NV index requires authorization, and the authHandle parameter is the handle of an
NV Index, then the nvIndex parameter must have the same value or the TPM will return
TPM_RC_NV_AUTHORIZATION.
NOTE 1 This check ensures that the authorization that was provide d is associated with the NV Index being
authorized.
For creating an Index, Owner Authorization may not be used if shEnable is CLEAR and Platform
Authorization may not be used if phEnableNV is CLEAR.
If an Index was defined using Platform Authorization, then that Index is not accessible when phEnableNV
is CLEAR. If an Index was defined using Owner Authorization, then that Index is not accessible when
shEnable is CLEAR.
For read access control, any combination of TPMA_NV_PPREAD, TPMA_NV_OWNERREAD,
TPMA_NV_AUTHREAD, or TPMA_NV_POLICYREAD is allowed as long as at least one is SET.
For write access control, any combination of TPMA_NV_PPWRITE, TPMA_NV_OWNERWRITE,
TPMA_NV_AUTHWRITE, or TPMA_NV_POLICYWRITE is allowed as long as at least one is SET.
If an Index has been defined and not written, then any operation on the NV Index that requires read
authorization will fail (TPM_RC_NV_INITIALIZED). This check may be made before or after other
authorization checks but shall be performed before checking the NV Index authValue. An authorization
failure due to the NV Index not having been written shall not be logged by the dictionary attack logic.
If TPMA_NV_CLEAR_STCLEAR is SET, then the TPMA_NV_WRITTEN will be CLEAR on each
TPM2_Startup(TPM_SU_CLEAR). TPMA_NV_CLEAR_STCLEAR shall not be SET if the nvIndexType is
TPM_NT_COUNTER.
The code in the “Detailed Actions” clause of each command is written to interface with an implementation-
dependent library that allows access to NV memory. The actions assume no specific layout of the
structure of the NV data.
Only one NV Index may be directly referenced in a command.
NOTE 2 This means that, if authHandle references an NV Index, then nvIndex will have the same value.
However, this does not limit the number of changes that may occur as side effects. For example, any
number of NV Indexes might be relocated as a result of deleting or adding a NV Index.
31.2 NV Counters
When an Index has the TPM_NT_COUNTER attribute, it behaves as a monotonic counter and may only
be updated using TPM2_NV_Increment().
When an NV counter is created, the TPM shall initialize the 8-octet counter value with a number that is
greater than any count value for any NV counter on the TPM since the time of TPM manufacture.
An NV counter may be defined with the TPMA_NV_ORDERLY attribute to indicate that the NV Index is
expected to be modified at a high frequency and that the data is only required to persist when the TPM
goes through an orderly shutdown process. The TPM may update the counter value in RAM and
occasionally update the non-volatile version of the counter. An orderly shutdown is one occasion to
update the non-volatile count. If the difference between the volatile and non-volatile version of the counter
becomes as large as MAX_ORDERLY_COUNT, this shall be another occasion for updating the non-
volatile count.
Before an NV counter can be used, the TPM shall validate that the count is not less than a previously
reported value. If the TPMA_NV_ORDERLY attribute is not SET, or if the TPM experienced an orderly
shutdown, then the count is assumed to be correct. If the TPMA_NV_ORDERLY attribute is SET, and the
TPM shutdown was not orderly, then the TPM shall OR MAX_ORDERLY_COUNT to the contents of the
non-volatile counter and set that as the current count.
NOTE 1 Because the TPM would have updated the NV Index if the difference between the count values was
equal to MAX_ORDERLY_COUNT + 1, the highest value that could have been in the NV Index is
MAX_ORDERLY_COUNT so it is safe to restore that value.
NOTE 2 The TPM may implement the RAM portion of the counter such that the effective value of the NV
counter is the sum of both the volatile and non-volatile parts. If so, then the TPM may initialize the
RAM version of the counter to MAX_ORDERLY_COUNT and no update of NV is necessary.
NOTE 3 When a new NV counter is created, the TPM may search all the counters to determine which has the
highest value. In this search, the TPM would use the sum of the non -volatile and RAM portions of
the counter. The RAM portion of the counter shall be properly initialized to reflect shutdown process
(orderly or not) of the TPM.
31.3 TPM2_NV_DefineSpace
General Description
This command defines the attributes of an NV Index and causes the TPM to reserve space to hold the
data associated with the NV Index. If a definition already exists at the NV Index, the TPM will return
TPM_RC_NV_DEFINED.
The TPM will return TPM_RC_ATTRIBUTES if nvIndexType has a reserved value in publicInfo.
NOTE 2 TPM_RC_ATTRIBUTES could be returned by a TPM that is based on the reference code of older
versions of the specification but the correct response for this error is TPM_RC_SIZE.
If the NV Index is an ordinary Index and publicInfo→dataSize is larger than supported by the TPM
implementation then the TPM shall return TPM_RC_SIZE.
NOTE 3 The limit for the data size may vary according to the type of the index. For example, if the index has
TPMA_NV_ORDERLY SET, then the maximum size of an ordinary NV Index may be less than the
size of an ordinary NV Index that has TPMA_NV_ORDERLY CLEAR.
NOTE 4 The intent of a PIN Fail index is that its DA protection is on a per -index basis, not based on the
global DA protection. This avoids conflict ov er which type of dictionary attack protection is in use.
NOTE 5 If TPMA_NV_AUTHWRITE was SET for a PIN Pass index, a user knowing the authorization value
could decrease pinCount or increase pinLimit, defeating the purpose of a PIN Pass index. The
requirement is also enforced for a PIN Fail index for consistency.
If the implementation does not support TPM2_NV_Increment(), the TPM shall return
TPM_RC_ATTRIBUTES if nvIndexType is TPM_NT_COUNTER.
If the implementation does not support TPM2_NV_SetBits(), the TPM shall return
TPM_RC_ATTRIBUTES if nvIndexType is TPM_NT_BITS.
If the implementation does not support TPM2_NV_Extend(), the TPM shall return
TPM_RC_ATTRIBUTES if nvIndexType is TPM_NT_EXTEND.
If the implementation does not support TPM2_NV_UndefineSpaceSpecial(), the TPM shall return
TPM_RC_ATTRIBUTES if TPMA_NV_POLICY_DELETE is SET.
After the successful completion of this command, the NV Index exists but TPMA_NV_WRITTEN will be
CLEAR. Any access of the NV data will return TPM_RC_NV_UNINITIALIZED.
In some implementations, an NV Index with the TPM_NT_COUNTER attribute may require special TPM
resources that provide higher endurance than regular NV. For those implementations, if this command
fails because of lack of resources, the TPM will return TPM_RC_NV_SPACE.
The value of auth is saved in the created structure. The size of auth is limited to be no larger than the size
of the digest produced by the NV Index's nameAlg (TPM_RC_SIZE).
TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
TPMI_RH_PROVISION @authHandle Auth Index: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_DefineSpace_fp.h"
3 #if CC_NV_DefineSpace // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_DefineSpace(
6 NV_DefineSpace_In *in // IN: input parameter list
7 )
8 {
9 TPMA_NV attributes = in->publicInfo.nvPublic.attributes;
10 UINT16 nameSize;
11
12 nameSize = CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg);
13
14 // Input Validation
15
16 // Checks not specific to type
17
18 // If the UndefineSpaceSpecial command is not implemented, then can't have
19 // an index that can only be deleted with policy
20 #if CC_NV_UndefineSpaceSpecial == NO
21 if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICY_DELETE))
22 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
23 #endif
24
25 // check that the authPolicy consistent with hash algorithm
26
27 if(in->publicInfo.nvPublic.authPolicy.t.size != 0
28 && in->publicInfo.nvPublic.authPolicy.t.size != nameSize)
29 return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
30
31 // make sure that the authValue is not too large
32 if(MemoryRemoveTrailingZeros(&in->auth)
33 > CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg))
34 return TPM_RCS_SIZE + RC_NV_DefineSpace_auth;
35
36 // If an index is being created by the owner and shEnable is
37 // clear, then we would not reach this point because ownerAuth
38 // can't be given when shEnable is CLEAR. However, if phEnable
39 // is SET but phEnableNV is CLEAR, we have to check here
40 if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR)
41 return TPM_RCS_HIERARCHY + RC_NV_DefineSpace_authHandle;
42
43 // Attribute checks
44 // Eliminate the unsupported types
45 switch(GET_TPM_NT(attributes))
46 {
47 #if CC_NV_Increment == YES
48 case TPM_NT_COUNTER:
49 #endif
50 #if CC_NV_SetBits == YES
51 case TPM_NT_BITS:
52 #endif
53 #if CC_NV_Extend == YES
54 case TPM_NT_EXTEND:
55 #endif
56 #if CC_PolicySecret == YES && defined TPM_NT_PIN_PASS
57 case TPM_NT_PIN_PASS:
58 case TPM_NT_PIN_FAIL:
59 #endif
60 case TPM_NT_ORDINARY:
61 break;
62 default:
63 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
64 break;
65 }
66 // Check that the sizes are OK based on the type
67 switch(GET_TPM_NT(attributes))
68 {
69 case TPM_NT_ORDINARY:
70 // Can't exceed the allowed size for the implementation
71 if(in->publicInfo.nvPublic.dataSize > MAX_NV_INDEX_SIZE)
72 return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
73 break;
74 case TPM_NT_EXTEND:
75 if(in->publicInfo.nvPublic.dataSize != nameSize)
76 return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
77 break;
78 default:
79 // Everything else needs a size of 8
80 if(in->publicInfo.nvPublic.dataSize != 8)
81 return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
82 break;
83 }
84 // Handle other specifics
85 switch(GET_TPM_NT(attributes))
86 {
87 case TPM_NT_COUNTER:
88 // Counter can't have TPMA_NV_CLEAR_STCLEAR SET (don't clear counters)
89 if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR))
90 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
91 break;
92 #ifdef TPM_NT_PIN_FAIL
93 case TPM_NT_PIN_FAIL:
94 // NV_NO_DA must be SET and AUTHWRITE must be CLEAR
95 // NOTE: As with a PIN_PASS index, the authValue of the index is not
96 // available until the index is written. If AUTHWRITE is the only way to
97 // write then index, it could never be written. Rather than go through
98 // all of the other possible ways to write the Index, it is simply
99 // prohibited to write the index with the authValue. Other checks
100 // below will insure that there seems to be a way to write the index
101 // (i.e., with platform authorization , owner authorization,
102 // or with policyAuth.)
103 // It is not allowed to create a PIN Index that can't be modified.
104 if(!IS_ATTRIBUTE(attributes, TPMA_NV, NO_DA))
105 return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
106 #endif
107 #ifdef TPM_NT_PIN_PASS
108 case TPM_NT_PIN_PASS:
109 // AUTHWRITE must be CLEAR (see note above to TPM_NT_PIN_FAIL)
110 if(IS_ATTRIBUTE(attributes, TPMA_NV, AUTHWRITE)
31.4 TPM2_NV_UndefineSpace
General Description
NOTE An Index with TPMA_NV_PLATFORMCREATE CLEAR may be deleted with Platform Authorization
as long as shEnable is SET. If shEnable is CLEAR, indexes created using Owner Authorization are
not accessible even for deletion by the platform.
TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
TPMI_RH_PROVISION @authHandle Auth Index: 1
Auth Role: USER
the NV Index to remove from NV space
TPMI_RH_NV_INDEX nvIndex
Auth Index: None
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_UndefineSpace_fp.h"
3 #if CC_NV_UndefineSpace // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_UndefineSpace(
6 NV_UndefineSpace_In *in // IN: input parameter list
7 )
8 {
9 NV_REF locator;
10 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
11
12 // Input Validation
13 // This command can't be used to delete an index with TPMA_NV_POLICY_DELETE SET
14 if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE))
15 return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex;
16
17 // The owner may only delete an index that was defined with ownerAuth. The
18 // platform may delete an index that was created with either authorization.
19 if(in->authHandle == TPM_RH_OWNER
20 && IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE))
21 return TPM_RC_NV_AUTHORIZATION;
22
23 // Internal Data Update
24
25 // Call implementation dependent internal routine to delete NV index
26 return NvDeleteIndex(nvIndex, locator);
27 }
28 #endif // CC_NV_UndefineSpace
31.5 TPM2_NV_UndefineSpaceSpecial
General Description
Index to be deleted
TPMI_RH_NV_INDEX @nvIndex Auth Index: 1
Auth Role: ADMIN
TPM_RH_PLATFORM + {PP}
TPMI_RH_PLATFORM @platform Auth Index: 2
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_UndefineSpaceSpecial_fp.h"
3 #include "SessionProcess_fp.h"
4 #if CC_NV_UndefineSpaceSpecial // Conditional expansion of this file
5 TPM_RC
6 TPM2_NV_UndefineSpaceSpecial(
7 NV_UndefineSpaceSpecial_In *in // IN: input parameter list
8 )
9 {
10 TPM_RC result;
11 NV_REF locator;
12 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
13 // Input Validation
14 // This operation only applies when the TPMA_NV_POLICY_DELETE attribute is SET
15 if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE))
16 return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpaceSpecial_nvIndex;
17 // Internal Data Update
18 // Call implementation dependent internal routine to delete NV index
19 result = NvDeleteIndex(nvIndex, locator);
20
21 // If we just removed the index providing the authorization, make sure that the
22 // authorization session computation is modified so that it doesn't try to
23 // access the authValue of the just deleted index
24 if(result == TPM_RC_SUCCESS)
25 SessionRemoveAssociationToHandle(in->nvIndex);
26 return result;
27 }
28 #endif // CC_NV_UndefineSpaceSpecial
31.6 TPM2_NV_ReadPublic
General Description
This command is used to read the public area and Name of an NV Index. The public area of an Index is
not privacy-sensitive and no authorization is required to read this data.
the NV Index
TPMI_RH_NV_INDEX nvIndex
Auth Index: None
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_ReadPublic_fp.h"
3 #if CC_NV_ReadPublic // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_ReadPublic(
6 NV_ReadPublic_In *in, // IN: input parameter list
7 NV_ReadPublic_Out *out // OUT: output parameter list
8 )
9 {
10 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, NULL);
11
12 // Command Output
13
14 // Copy index public data to output
15 out->nvPublic.nvPublic = nvIndex->publicArea;
16
17 // Compute NV name
18 NvGetIndexName(nvIndex, &out->nvName);
19
20 return TPM_RC_SUCCESS;
21 }
22 #endif // CC_NV_ReadPublic
31.7 TPM2_NV_Write
General Description
This command writes a value to an area in NV memory that was previously defined by
TPM2_NV_DefineSpace().
Proper authorizations are required for this command as determined by TPMA_NV_PPWRITE;
TPMA_NV_OWNERWRITE; TPMA_NV_AUTHWRITE; and, if TPMA_NV_POLICY_WRITE is SET, the
authPolicy of the NV Index.
If the TPMA_NV_WRITELOCKED attribute of the NV Index is SET, then the TPM shall return
TPM_RC_NV_LOCKED.
NOTE 1 If authorization sessions are present, they are checked before checks to see if writes to the NV
Index are locked.
NOTE 2 Once SET, TPMA_NV_WRITTEN remains SET until the NV Index is undefined or the NV Index is
cleared.
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_Write_fp.h"
3 #if CC_NV_Write // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_Write(
6 NV_Write_In *in // IN: input parameter list
7 )
8 {
9 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, NULL);
10 TPMA_NV attributes = nvIndex->publicArea.attributes;
11 TPM_RC result;
12
13 // Input Validation
14
15 // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION
16 // or TPM_RC_NV_LOCKED
17 result = NvWriteAccessChecks(in->authHandle,
18 in->nvIndex,
19 attributes);
20 if(result != TPM_RC_SUCCESS)
21 return result;
22
23 // Bits index, extend index or counter index may not be updated by
24 // TPM2_NV_Write
25 if(IsNvCounterIndex(attributes)
26 || IsNvBitsIndex(attributes)
27 || IsNvExtendIndex(attributes))
28 return TPM_RC_ATTRIBUTES;
29
30 // Make sure that the offset is not too large
31 if(in->offset > nvIndex->publicArea.dataSize)
32 return TPM_RCS_VALUE + RC_NV_Write_offset;
33
34 // Make sure that the selection is within the range of the Index
35 if(in->data.t.size > (nvIndex->publicArea.dataSize - in->offset))
36 return TPM_RC_NV_RANGE;
37
38 // If this index requires a full sized write, make sure that input range is
39 // full sized.
40 // Note: if the requested size is the same as the Index data size, then offset
41 // will have to be zero. Otherwise, the range check above would have failed.
42 if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITEALL)
43 && in->data.t.size < nvIndex->publicArea.dataSize)
44 return TPM_RC_NV_RANGE;
45
46 // Internal Data Update
47
48 // Perform the write. This called routine will SET the TPMA_NV_WRITTEN
49 // attribute if it has not already been SET. If NV isn't available, an error
50 // will be returned.
51 return NvWriteIndexData(nvIndex, in->offset, in->data.t.size,
52 in->data.t.buffer);
53 }
54 #endif // CC_NV_Write
31.8 TPM2_NV_Increment
General Description
This command is used to increment the value in an NV Index that has the TPM_NT_COUNTER attribute.
The data value of the NV Index is incremented by one.
If nvIndexType is not TPM_NT_COUNTER in the indicated NV Index, the TPM shall return
TPM_RC_ATTRIBUTES.
If TPMA_NV_WRITELOCKED is SET, the TPM shall return TPM_RC_NV_LOCKED.
If TPMA_NV_WRITTEN is CLEAR, it will be SET.
If TPMA_NV_ORDERLY is SET, and the difference between the volatile and non-volatile versions of this
field is greater than MAX_ORDERLY_COUNT, then the non-volatile version of the counter is updated.
NOTE 2 If a TPM implements TPMA_NV_ORDERLY and an Index is defined with TPMA_NV_ORDERLY and
TPM_NT_COUNTER both SET, then in the Event of a non -orderly shutdown, the non-volatile value
for the counter Index will be advanced by MAX_ORDERLY_COUNT at the next TPM2_Startup().
NOTE 3 An allowed implementation would keep a counter value in NV and a resettable counter in RAM. The
reported value of the NV Index would be the sum of the two values. When the RAM count increments
past the maximum allowed value (MAX_ORDERLY_COUNT), the non -volatile version of the count is
updated with the sum of the values and the RAM count is reset to zero.
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_Increment_fp.h"
3 #if CC_NV_Increment // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_Increment(
6 NV_Increment_In *in // IN: input parameter list
7 )
8 {
9 TPM_RC result;
10 NV_REF locator;
11 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
12 UINT64 countValue;
13
14 // Input Validation
15
16 // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION
17 // or TPM_RC_NV_LOCKED
18 result = NvWriteAccessChecks(in->authHandle,
19 in->nvIndex,
20 nvIndex->publicArea.attributes);
21 if(result != TPM_RC_SUCCESS)
22 return result;
23
24 // Make sure that this is a counter
25 if(!IsNvCounterIndex(nvIndex->publicArea.attributes))
26 return TPM_RCS_ATTRIBUTES + RC_NV_Increment_nvIndex;
27
28 // Internal Data Update
29
30 // If counter index is not been written, initialize it
31 if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
32 countValue = NvReadMaxCount();
33 else
34 // Read NV data in native format for TPM CPU.
35 countValue = NvGetUINT64Data(nvIndex, locator);
36
37 // Do the increment
38 countValue++;
39
40 // Write NV data back. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may
41 // be returned at this point. If necessary, this function will set the
42 // TPMA_NV_WRITTEN attribute
43 result = NvWriteUINT64Data(nvIndex, countValue);
44 if(result == TPM_RC_SUCCESS)
45 {
46 // If a counter just rolled over, then force the NV update.
47 // Note, if this is an orderly counter, then the write-back needs to be
48 // forced, for other counters, the write-back will happen anyway
49 if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)
50 && (countValue & MAX_ORDERLY_COUNT) == 0 )
51 {
52 // Need to force an NV update of orderly data
53 SET_NV_UPDATE(UT_ORDERLY);
54 }
55 }
56 return result;
57 }
58 #endif // CC_NV_Increment
31.9 TPM2_NV_Extend
General Description
This command extends a value to an area in NV memory that was previously defined by
TPM2_NV_DefineSpace.
If nvIndexType is not TPM_NT_EXTEND, then the TPM shall return TPM_RC_ATTRIBUTES.
Proper write authorizations are required for this command as determined by TPMA_NV_PPWRITE,
TPMA_NV_OWNERWRITE, TPMA_NV_AUTHWRITE, and the authPolicy of the NV Index.
After successful completion of this command, TPMA_NV_WRITTEN for the NV Index will be SET.
NOTE 1 Once SET, TPMA_NV_WRITTEN remains SET until the NV Index is undefined, un less the
TPMA_NV_CLEAR_STCLEAR attribute is SET and a TPM Reset or TPM Restart occurs.
If the TPMA_NV_WRITELOCKED attribute of the NV Index is SET, then the TPM shall return
TPM_RC_NV_LOCKED.
NOTE 2 If authorization sessions are present, they are checked b efore checks to see if writes to the NV
Index are locked.
The data.buffer parameter may be larger than the defined size of the NV Index.
The Index will be updated by:
nvIndex→datanew ≔ HnameAkg(nvIndex→dataold || data.buffer) (41)
where
nvIndex→datanew the value of the data field in the NV Index after the command
returns
HnameAkg() the hash algorithm indicated in nvIndex→nameAlg
nvIndex→dataold the value of the data field in the NV Index before the command is
called
data.buffer the data buffer of the command parameter
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_Extend_fp.h"
3 #if CC_NV_Extend // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_Extend(
6 NV_Extend_In *in // IN: input parameter list
7 )
8 {
9 TPM_RC result;
10 NV_REF locator;
11 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
12
13 TPM2B_DIGEST oldDigest;
14 TPM2B_DIGEST newDigest;
15 HASH_STATE hashState;
16
17 // Input Validation
18
19 // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION
20 // or TPM_RC_NV_LOCKED
21 result = NvWriteAccessChecks(in->authHandle,
22 in->nvIndex,
23 nvIndex->publicArea.attributes);
24 if(result != TPM_RC_SUCCESS)
25 return result;
26
27 // Make sure that this is an extend index
28 if(!IsNvExtendIndex(nvIndex->publicArea.attributes))
29 return TPM_RCS_ATTRIBUTES + RC_NV_Extend_nvIndex;
30
31 // Internal Data Update
32
33 // Perform the write.
34 oldDigest.t.size = CryptHashGetDigestSize(nvIndex->publicArea.nameAlg);
35 pAssert(oldDigest.t.size <= sizeof(oldDigest.t.buffer));
36 if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
37 {
38 NvGetIndexData(nvIndex, locator, 0, oldDigest.t.size, oldDigest.t.buffer);
39 }
40 else
41 {
42 MemorySet(oldDigest.t.buffer, 0, oldDigest.t.size);
43 }
44 // Start hash
45 newDigest.t.size = CryptHashStart(&hashState, nvIndex->publicArea.nameAlg);
46
47 // Adding old digest
48 CryptDigestUpdate2B(&hashState, &oldDigest.b);
49
50 // Adding new data
51 CryptDigestUpdate2B(&hashState, &in->data.b);
52
53 // Complete hash
54 CryptHashEnd2B(&hashState, &newDigest.b);
55
56 // Write extended hash back.
57 // Note, this routine will SET the TPMA_NV_WRITTEN attribute if necessary
58 return NvWriteIndexData(nvIndex, 0, newDigest.t.size, newDigest.t.buffer);
59 }
60 #endif // CC_NV_Extend
31.10 TPM2_NV_SetBits
General Description
This command is used to SET bits in an NV Index that was created as a bit field. Any number of bits from
0 to 64 may be SET. The contents of bits are ORed with the current contents of the NV Index.
If TPMA_NV_WRITTEN is not SET, then, for the purposes of this command, the NV Index is considered
to contain all zero bits and data is ORed with that value.
If TPM_NT_BITS is not SET, then the TPM shall return TPM_RC_ATTRIBUTES.
After successful completion of this command, TPMA_NV_WRITTEN for the NV Index will be SET.
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_SetBits_fp.h"
3 #if CC_NV_SetBits // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_SetBits(
6 NV_SetBits_In *in // IN: input parameter list
7 )
8 {
9 TPM_RC result;
10 NV_REF locator;
11 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
12 UINT64 oldValue;
13 UINT64 newValue;
14
15 // Input Validation
16
17 // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION
18 // or TPM_RC_NV_LOCKED
19 result = NvWriteAccessChecks(in->authHandle,
20 in->nvIndex,
21 nvIndex->publicArea.attributes);
22 if(result != TPM_RC_SUCCESS)
23 return result;
24
25 // Make sure that this is a bit field
26 if(!IsNvBitsIndex(nvIndex->publicArea.attributes))
27 return TPM_RCS_ATTRIBUTES + RC_NV_SetBits_nvIndex;
28
29 // If index is not been written, initialize it
30 if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
31 oldValue = 0;
32 else
33 // Read index data
34 oldValue = NvGetUINT64Data(nvIndex, locator);
35
36 // Figure out what the new value is going to be
37 newValue = oldValue | in->bits;
38
39 // Internal Data Update
40 return NvWriteUINT64Data(nvIndex, newValue);
41 }
42 #endif // CC_NV_SetBits
31.11 TPM2_NV_WriteLock
General Description
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_WriteLock_fp.h"
3 #if CC_NV_WriteLock // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_WriteLock(
6 NV_WriteLock_In *in // IN: input parameter list
7 )
8 {
9 TPM_RC result;
10 NV_REF locator;
11 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
12 TPMA_NV nvAttributes = nvIndex->publicArea.attributes;
13
14 // Input Validation:
15
16 // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION
17 // or TPM_RC_NV_LOCKED
18 result = NvWriteAccessChecks(in->authHandle, in->nvIndex, nvAttributes);
19 if(result != TPM_RC_SUCCESS)
20 {
21 if(result == TPM_RC_NV_AUTHORIZATION)
22 return result;
23 // If write access failed because the index is already locked, then it is
24 // no error.
25 return TPM_RC_SUCCESS;
26 }
27 // if neither TPMA_NV_WRITEDEFINE nor TPMA_NV_WRITE_STCLEAR is set, the index
28 // can not be write-locked
29 if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITEDEFINE)
30 && !IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITE_STCLEAR))
31 return TPM_RCS_ATTRIBUTES + RC_NV_WriteLock_nvIndex;
32 // Internal Data Update
33 // Set the WRITELOCK attribute.
34 // Note: if TPMA_NV_WRITELOCKED were already SET, then the write access check
35 // above would have failed and this code isn't executed.
36 SET_ATTRIBUTE(nvAttributes, TPMA_NV, WRITELOCKED);
37
38 // Write index info back
39 return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex, locator,
40 nvAttributes);
41 }
42 #endif // CC_NV_WriteLock
31.12 TPM2_NV_GlobalWriteLock
General Description
The command will SET TPMA_NV_WRITELOCKED for all indexes that have their
TPMA_NV_GLOBALLOCK attribute SET.
If an Index has both TPMA_NV_GLOBALLOCK and TPMA_NV_WRITEDEFINE SET, then this command
will permanently lock the NV Index for writing unless TPMA_NV_WRITTEN is CLEAR.
NOTE If an Index is defined with TPMA_NV_GLOBALLO CK SET, then the global lock does not apply until
the next time this command is executed.
TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}
TPMI_RH_PROVISION @authHandle Auth Index: 1
Auth Role: USER
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_GlobalWriteLock_fp.h"
3 #if CC_NV_GlobalWriteLock // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_GlobalWriteLock(
6 NV_GlobalWriteLock_In *in // IN: input parameter list
7 )
8 {
9 // Input parameter (the authorization handle) is not reference in command action.
10 NOT_REFERENCED(in);
11
12 // Internal Data Update
13
14 // Implementation dependent method of setting the global lock
15 return NvSetGlobalLock();
16 }
17 #endif // CC_NV_GlobalWriteLock
31.13 TPM2_NV_Read
General Description
NOTE 1 If authorization sessions are present, they are checked before the read -lock status of the NV Index
is checked.
If the NV Index has been defined but the TPMA_NV_WRITTEN attribute is CLEAR, then this command
shall return TPM_RC_NV_UNINITIALIZED even if size is zero.
The data parameter in the response may be encrypted using parameter encryption.
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_Read_fp.h"
3 #if CC_NV_Read // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_Read(
6 NV_Read_In *in, // IN: input parameter list
7 NV_Read_Out *out // OUT: output parameter list
8 )
9 {
10 NV_REF locator;
11 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
12 TPM_RC result;
13
14 // Input Validation
15 // Common read access checks. NvReadAccessChecks() may return
16 // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED
17 result = NvReadAccessChecks(in->authHandle, in->nvIndex,
18 nvIndex->publicArea.attributes);
19 if(result != TPM_RC_SUCCESS)
20 return result;
21
22 // Make sure the data will fit the return buffer
23 if(in->size > MAX_NV_BUFFER_SIZE)
24 return TPM_RCS_VALUE + RC_NV_Read_size;
25
26 // Verify that the offset is not too large
27 if(in->offset > nvIndex->publicArea.dataSize)
28 return TPM_RCS_VALUE + RC_NV_Read_offset;
29
30 // Make sure that the selection is within the range of the Index
31 if(in->size > (nvIndex->publicArea.dataSize - in->offset))
32 return TPM_RC_NV_RANGE;
33
34 // Command Output
35 // Set the return size
36 out->data.t.size = in->size;
37
38 // Perform the read
39 NvGetIndexData(nvIndex, locator, in->offset, in->size, out->data.t.buffer);
40
41 return TPM_RC_SUCCESS;
42 }
43 #endif // CC_NV_Read
31.14 TPM2_NV_ReadLock
General Description
If TPMA_NV_READ_STCLEAR is SET in an Index, then this command may be used to prevent further
reads of the NV Index until the next TPM2_Startup (TPM_SU_CLEAR).
Proper authorizations are required for this command as determined by TPMA_NV_PPREAD,
TPMA_NV_OWNERREAD, TPMA_NV_AUTHREAD, and the authPolicy of the NV Index.
NOTE Only an entity that may read an Index is allowed to lock the NV Index for read.
If the command is properly authorized and TPMA_NV_READ_STCLEAR of the NV Index is SET, then the
TPM shall SET TPMA_NV_READLOCKED for the NV Index. If TPMA_NV_READ_STCLEAR of the NV
Index is CLEAR, then the TPM shall return TPM_RC_ATTRIBUTES. TPMA_NV_READLOCKED will be
CLEAR by the next TPM2_Startup(TPM_SU_CLEAR).
It is not an error to use this command for an Index that is already locked for reading.
An Index that had not been written may be locked for reading.
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_ReadLock_fp.h"
3 #if CC_NV_ReadLock // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_ReadLock(
6 NV_ReadLock_In *in // IN: input parameter list
7 )
8 {
9 TPM_RC result;
10 NV_REF locator;
11 // The referenced index has been checked multiple times before this is called
12 // so it must be present and will be loaded into cache
13 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
14 TPMA_NV nvAttributes = nvIndex->publicArea.attributes;
15
16 // Input Validation
17 // Common read access checks. NvReadAccessChecks() may return
18 // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED
19 result = NvReadAccessChecks(in->authHandle,
20 in->nvIndex,
21 nvAttributes);
22 if(result == TPM_RC_NV_AUTHORIZATION)
23 return TPM_RC_NV_AUTHORIZATION;
24 // Index is already locked for write
25 else if(result == TPM_RC_NV_LOCKED)
26 return TPM_RC_SUCCESS;
27
28 // If NvReadAccessChecks return TPM_RC_NV_UNINITALIZED, then continue.
29 // It is not an error to read lock an uninitialized Index.
30
31 // if TPMA_NV_READ_STCLEAR is not set, the index can not be read-locked
32 if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, READ_STCLEAR))
33 return TPM_RCS_ATTRIBUTES + RC_NV_ReadLock_nvIndex;
34
35 // Internal Data Update
36
37 // Set the READLOCK attribute
38 SET_ATTRIBUTE(nvAttributes, TPMA_NV, READLOCKED);
39
40 // Write NV info back
41 return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex,
42 locator,
43 nvAttributes);
44 }
45 #endif // CC_NV_ReadLock
31.15 TPM2_NV_ChangeAuth
General Description
NOTE The reason for this restriction is to ensure that the administrative actions on nvIndex require explicit
approval while other commands may use policy that is not command -dependent.
The size of the newAuth value may be no larger than the size of the digest produced by the nameAlg of
the NV Index.
Since the NV Index authorization is changed before the response HMAC is calculated, the newAuth value
is used when generating the response HMAC key if required. See TPM 2.0 Part 4
ComputeResponseHMAC().
Detailed Actions
1 #include "Tpm.h"
2 #include "NV_ChangeAuth_fp.h"
3 #if CC_NV_ChangeAuth // Conditional expansion of this file
4 TPM_RC
5 TPM2_NV_ChangeAuth(
6 NV_ChangeAuth_In *in // IN: input parameter list
7 )
8 {
9 NV_REF locator;
10 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
11
12 // Input Validation
13
14 // Remove trailing zeros and make sure that the result is not larger than the
15 // digest of the nameAlg.
16 if(MemoryRemoveTrailingZeros(&in->newAuth)
17 > CryptHashGetDigestSize(nvIndex->publicArea.nameAlg))
18 return TPM_RCS_SIZE + RC_NV_ChangeAuth_newAuth;
19
20 // Internal Data Update
21 // Change authValue
22 return NvWriteIndexAuth(locator, &in->newAuth);
23 }
24 #endif // CC_NV_ChangeAuth
31.16 TPM2_NV_Certify
General Description
The purpose of this command is to certify the contents of an NV Index or portion of an NV Index.
If the sign attribute is not SET in the key referenced by signHandle then the TPM shall return
TPM_RC_KEY.
If the NV Index has been defined but the TPMA_NV_WRITTEN attribute is CLEAR, then this command
shall return TPM_RC_NV_UNINITIALIZED even if size is zero.
If proper authorization for reading the NV Index is provided, the portion of the NV Index selected by size
and offset are included in an attestation block and signed using the key indicated by signHandle. The
attestation includes size and offset so that the range of the data can be determined. It also includes the
NV index Name.
For an NV Index with the TPM_NT_COUNTER or TPM_NT_BITS attribute SET, the TPM may ignore the
offset parameter and use an offset of 0. Therefore, it is recommended that the caller set the offset
parameter to 0 for interoperability.
If offset and size add to a value that is greater than the dataSize field of the NV Index referenced by
nvIndex, the TPM shall return an error (TPM_RC_NV_RANGE). The implementation may return an error
(TPM_RC_VALUE) if it performs an additional check and determines that offset is greater than the
dataSize field of the NV Index, or if size is greater than MAX_NV_BUFFER_SIZE.
NOTE 1 See 18.1 for description of how the signing scheme is selected.
NOTE 2 If signHandle is TPM_RH_NULL, the TPMS_ATTEST structure is returned and signature is a NULL
Signature.
If size and offset are both zero (0), then certifyInfo in the response will contain a
TPMS_NV_DIGEST_CERTIFY_INFO, otherwise, it will contain a TPMS_NV_CERTIFY_INFO. The digest
in the TPMS_NV_DIGEST_CERTIFY_INFO is created using the digest of the selected signing scheme.
Detailed Actions
1 #include "Tpm.h"
2 #include "Attest_spt_fp.h"
3 #include "NV_Certify_fp.h"
4 #if CC_NV_Certify // Conditional expansion of this file
5 TPM_RC
6 TPM2_NV_Certify(
7 NV_Certify_In *in, // IN: input parameter list
8 NV_Certify_Out *out // OUT: output parameter list
9 )
10 {
11 TPM_RC result;
12 NV_REF locator;
13 NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
14 TPMS_ATTEST certifyInfo;
15 OBJECT *signObject = HandleToObject(in->signHandle);
16 // Input Validation
17 if(!IsSigningObject(signObject))
18 return TPM_RCS_KEY + RC_NV_Certify_signHandle;
19 if(!CryptSelectSignScheme(signObject, &in->inScheme))
20 return TPM_RCS_SCHEME + RC_NV_Certify_inScheme;
21
22 // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION
23 // or TPM_RC_NV_LOCKED
24 result = NvReadAccessChecks(in->authHandle, in->nvIndex,
25 nvIndex->publicArea.attributes);
26 if(result != TPM_RC_SUCCESS)
27 return result;
28
29 // make sure that the selection is within the range of the Index (cast to avoid
30 // any wrap issues with addition)
31 if((UINT32)in->size + (UINT32)in->offset > (UINT32)nvIndex->publicArea.dataSize)
32 return TPM_RC_NV_RANGE;
33 // Make sure the data will fit the return buffer.
34 // NOTE: This check may be modified if the output buffer will not hold the
35 // maximum sized NV buffer as part of the certified data. The difference in
36 // size could be substantial if the signature scheme was produced a large
37 // signature (e.g., RSA 4096).
38 if(in->size > MAX_NV_BUFFER_SIZE)
39 return TPM_RCS_VALUE + RC_NV_Certify_size;
40
41 // Command Output
42
43 // Fill in attest information common fields
44 FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData,
45 &certifyInfo);
46
47 // Get the name of the index
48 NvGetIndexName(nvIndex, &certifyInfo.attested.nv.indexName);
49
50 // See if this is old format or new format
51 if ((in->size != 0) || (in->offset != 0))
52 {
53 // NV certify specific fields
54 // Attestation type
55 certifyInfo.type = TPM_ST_ATTEST_NV;
56
57 // Set the return size
58 certifyInfo.attested.nv.nvContents.t.size = in->size;
59
60 // Set the offset
61 certifyInfo.attested.nv.offset = in->offset;
62
63 // Perform the read
64 NvGetIndexData(nvIndex, locator, in->offset, in->size,
65 certifyInfo.attested.nv.nvContents.t.buffer);
66 }
67 else
68 {
69 HASH_STATE hashState;
70 // This is to sign a digest of the data
71 certifyInfo.type = TPM_ST_ATTEST_NV_DIGEST;
72 // Initialize the hash before calling the function to add the Index data to
73 // the hash.
74 certifyInfo.attested.nvDigest.nvDigest.t.size =
75 CryptHashStart(&hashState, in->inScheme.details.any.hashAlg);
76 NvHashIndexData(&hashState, nvIndex, locator, 0,
77 nvIndex->publicArea.dataSize);
78 CryptHashEnd2B(&hashState, &certifyInfo.attested.nvDigest.nvDigest.b);
79 }
80 // Sign attestation structure. A NULL signature will be returned if
81 // signObject is NULL.
82 return SignAttestInfo(signObject, &in->inScheme, &certifyInfo,
83 &in->qualifyingData, &out->certifyInfo, &out->signature);
84 }
85 #endif // CC_NV_Certify
32 Attached Components
32.1 Introduction
This section contains commands that allow interaction with an Attached Component (AC).
32.2 TPM2_AC_GetCapability
General Description
The purpose of this command is to obtain information about an Attached Component referenced by an
AC handle.
The returned list contains 0 or more values starting at the first tagged value that is equal to or greater
than capability.
The list returned in capabilitiesData contains tagged values that indicate the type of the value.
The TPM will return the lesser of a) the available values, b) the number requested in count, or c) the
number that will fit within the available response buffer. If additional values with higher capability numbers
are available, moreData will be YES.
Detailed Actions
1 #include "Tpm.h"
2 #include "AC_GetCapability_fp.h"
3 #include "AC_spt_fp.h"
4 #if CC_AC_GetCapability // Conditional expansion of this file
5 TPM_RC
6 TPM2_AC_GetCapability(
7 AC_GetCapability_In *in, // IN: input parameter list
8 AC_GetCapability_Out *out // OUT: output parameter list
9 )
10 {
11 // Command Output
12 out->moreData = AcCapabilitiesGet(in->ac, in->count, &out->capabilitiesData);
13
14 return TPM_RC_SUCCESS;
15 }
16 #endif // CC_AC_GetCapability
32.3 TPM2_AC_Send
General Description
The purpose of this command is to send (copy) a loaded object from the TPM to an Attached Component.
The Object referenced by sendObject is required to have fixedTpm, fixedParent, and
encryptedDuplication attributes CLEAR (TPM_RC_ATTRIBUTES). Authorization for sendObject is
required to be a policy session. The policySession→commandCode of the policy session context is
required to be TPM_CC_AC_Send (TPM_RC_POLICY_FAIL) to demonstrate that the policy is specific for
this command.
Authorization to send to the ac is provided by the session associated with authHandle.
If an NV Alias is not defined for ac, then authHandle is required to be either TPM_RH_OWNER or
TPM_RH_PLATFORM (TPM_RC_HANDLE).
If an NV Alias is defined for ac, then the authorization for authHandle is required to be compatible with the
write authorization attributes (TPMA_NV_PPWRITE, TPMA_NV_OWNERWRITE
TPMA_NV_AUTHWRITE, and TPMA_NV_POLICYWRITE) in the NV Alias
(TPM_RC_NV_AUTHORIZATION).
NOTE 1 If authorization for authHandle is the handle of an NV Index, then it is required to be the NV Alias
value for ac (TPM_RC_NV_AUTHORIZATION).
If authorization succeeds, the TPM will attempt to send acDataIn and relevant portions of sendObject to
the AC referenced by ac.
The TPM will return TPM_RC_SUCCESS if it succeeds in performing all the required authorizations and
validations. If problems occur in the process of sending the object from the TPM to the AC, the response
code will be TPM_RC_SUCCESS with the AC-dependent error reported in acDataOut.
Detailed Actions
1 #include "Tpm.h"
2 #include "AC_Send_fp.h"
3 #include "AC_spt_fp.h"
4 #if CC_AC_Send // Conditional expansion of this file
5 TPM_RC
6 TPM2_AC_Send(
7 AC_Send_In *in, // IN: input parameter list
8 AC_Send_Out *out // OUT: output parameter list
9 )
10 {
11 NV_REF locator;
12 TPM_HANDLE nvAlias = ((in->ac - AC_FIRST) + NV_AC_FIRST);
13 NV_INDEX *nvIndex = NvGetIndexInfo(nvAlias, &locator);
14 OBJECT *object = HandleToObject(in->sendObject);
15 TPM_RC result;
16 // Input validation
17 // If there is an NV alias, then the index must allow the authorization provided
18 if(nvIndex != NULL)
19 {
20 // Common access checks, NvWriteAccessCheck() may return
21 // TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED
22 result = NvWriteAccessChecks(in->authHandle, nvAlias,
23 nvIndex->publicArea.attributes);
24 if(result != TPM_RC_SUCCESS)
25 return result;
26 }
27 // If 'ac' did not have an alias then the authorization had to be with either
28 // platform or owner authorization. The type of TPMI_RH_NV_AUTH only allows
29 // owner or platform or an NV index. If it was a valid index, it would have had
30 // an alias and be processed above, so only success here is if this is a
31 // permanent handle.
32 else if(HandleGetType(in->authHandle) != TPM_HT_PERMANENT)
33 return TPM_RCS_HANDLE + RC_AC_Send_authHandle;
34 // Make sure that the object to be duplicated has the right attributes
35 if(IS_ATTRIBUTE(object->publicArea.objectAttributes,
36 TPMA_OBJECT, encryptedDuplication)
37 || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT,
38 fixedParent)
32.4 TPM2_Policy_AC_SendSelect
General Description
This command allows qualification of the sending (copying) of an Object to an Attached Component (AC).
Qualification includes selection of the receiving AC and the method of authentication for the AC, and, in
certain circumstances, the Object to be sent may be specified.
If this command is not used in conjunction with TPM2_PolicyAuthorize(), then only the authHandleName
and acName are selected and includeObject should be CLEAR.
NOTE 1 In the absence of TPM2_PolicyAuthorize(), a policy session cannot create a policyDigest that
simultaneously equals the authPolicy in an Object and names that Object. This is because the
authPolicy recorded in an Object is unable to include the Name of the Object as the Name of an
Object depends on the Object’s authPolicy.
NOTE 2 An object’s authPolicy can incorporate the use of TPM2_PolicyAuthorize(). If the authorizing entity
for the TPM2_PolicyAuthorize() command specifies only the ac and the authHandle, then the
resultant policyDigest may be applied to the sending of any number of Objects. If the aut horizing
entity for the TPM2_PolicyAuthorize() specifies also the Name of the Object to be sent, then the
resultant policyDigest applies only to that specific Object.
If the command succeeds, policySession→policyDigest will be updated according to the setting of the
input parameter includeObject. If includeObject is SET, policySession→policyDigest is updated by:
policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_Policy_AC_SendSelect ||
objectName || authHandleName || acName || includeObject) (43)
but if includeObject is CLEAR, policySession→policyDigest is updated by:
policyDigestnew ≔ HpolicyAlg(policyDigestold || TPM_CC_Policy_AC_SendSelect ||
authHandleName || acName || includeObject) (44)
NOTE 4 policySession→nameHash receives the digest of all Names so that the check performed in
TPM2_AC_Send() may be the same regardless of which Names are included in
policySession→policyDigest. This means that, when TPM2_Policy_AC_SendSelect() is executed, it
is only valid for a specific triple of objectName, authHandleName, and acName.
Detailed Actions
1 #include "Tpm.h"
2 #include "Policy_AC_SendSelect_fp.h"
3 #if CC_Policy_AC_SendSelect // Conditional expansion of this file
4 TPM_RC
5 TPM2_Policy_AC_SendSelect(
6 Policy_AC_SendSelect_In *in // IN: input parameter list
7 )
8 {
9 SESSION *session;
10 HASH_STATE hashState;
11 TPM_CC commandCode = TPM_CC_Policy_AC_SendSelect;
12
13 // Input Validation
14
15 // Get pointer to the session structure
16 session = SessionGet(in->policySession);
17
18 // cpHash in session context must be empty
19 if(session->u1.cpHash.t.size != 0)
20 return TPM_RC_CPHASH;
21 // commandCode in session context must be empty
22 if(session->commandCode != 0)
23 return TPM_RC_COMMAND_CODE;
24 // Internal Data Update
25 // Update name hash
26 session->u1.cpHash.t.size = CryptHashStart(&hashState, session->authHashAlg);
27
28 // add objectName
29 CryptDigestUpdate2B(&hashState, &in->objectName.b);
30
31 // add authHandleName
32 CryptDigestUpdate2B(&hashState, &in->authHandleName.b);
33
34 // add ac name
35 CryptDigestUpdate2B(&hashState, &in->acName.b);
36
37 // complete hash
38 CryptHashEnd2B(&hashState, &session->u1.cpHash.b);
39
40 // update policy hash
41 // Old policyDigest size should be the same as the new policyDigest size since
42 // they are using the same hash algorithm
43 session->u2.policyDigest.t.size
44 = CryptHashStart(&hashState, session->authHashAlg);
45 // add old policy
46 CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
47
48 // add command code
49 CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode);
50
51 // add objectName
52 if(in->includeObject == YES)
53 CryptDigestUpdate2B(&hashState, &in->objectName.b);
54
55 // add authHandleName
56 CryptDigestUpdate2B(&hashState, &in->authHandleName.b);
57
58 // add acName
59 CryptDigestUpdate2B(&hashState, &in->acName.b);
60
61 // add includeObject
62 CryptDigestUpdateInt(&hashState, sizeof(TPMI_YES_NO), in->includeObject);
63
64 // complete digest
65 CryptHashEnd2B(&hashState, &session->u2.policyDigest.b);
66
67 // set commandCode in session context
68 session->commandCode = TPM_CC_AC_Send;
69
70 return TPM_RC_SUCCESS;
71 }
72 #endif // CC_Policy_AC_SendSelect
33.1 Introduction
This section contains commands that allow interaction with an Authenticated Countdown Timer (ACT).
33.2 TPM2_ACT_SetTimeout
General Description
This command is used to set the time remaining before an Authenticated Countdown Timer (ACT)
expires.
This command sets TPMS_ACT_DATA.timeout (ACT Timeout) to startTimeout. The startTimeout value is
an integer number of seconds and may be zero. The startTimeout parameter may be greater, equal, or
less than the current value of ACT Timeout.
When ACT Timeout is non-zero, it will count down, once per second until it reaches zero, at which time
the signaled attribute of the TPMA_ACT associated with actHandle is SET.
When ACT Timeout is zero and the signaled attribute is SET, writing a startTimeout of FF FF FF FF16 will
clear signaled and stop the counting.
There are four states for ACT Timeout and startTimeout. The signaled attribute will be set as follows:
1) If ACT Timeout is zero and startTimeout is non-zero, then signaled will be CLEAR.
2) If ACT Timeout is non-zero and startTimeout is non-zero, then signaled will be CLEAR.
3) If ACT Timeout is zero and startTimeout is zero, then signaled will be unchanged.
4) If ACT Timeout is non-zero and startTimeout is zero, then signaled will be SET.
NOTE 1 The ACT signals on a transition from non-zero to zero. The transition can occur either due to
TPM2_ACT_SetTimeout() or a decrement. The effect of signaled is platform dependent.
NOTE 2 It may take up to one second until ACT Timeout will be set and signaled will be CLEAR or SET by
TPM2_ACT_SetTimeout() or TPM2_Startup(STATE). This allows the counting and signaling to take
place synchronously with the hardware clock tick.
UINT32 startTimeout the start timeout value for the ACT in seconds
Detailed Actions
1 #include "Tpm.h"
2 #include "ACT_SetTimeout_fp.h"
3 #if CC_ACT_SetTimeout // Conditional expansion of this file
4 TPM_RC
5 TPM2_ACT_SetTimeout(
6 ACT_SetTimeout_In *in // IN: input parameter list
7 )
8 {
9 // If 'startTimeout' is UINT32_MAX, then this is an attempt to disable the ACT
10 // and turn off the signaling for the ACT. This is only valid if the ACT
11 // is signaling.
12 if((in->startTimeout == UINT32_MAX) && !ActGetSignaled(in->actHandle))
13 return TPM_RC_VALUE + RC_ACT_SetTimeout_startTimeout;
14 return ActCounterUpdate(in->actHandle, in->startTimeout);
15 }
16 #endif // CC_ACT_SetTimeout
34 Vendor Specific
34.1 Introduction
This section contains commands that are vendor specific but made public in order to prevent proliferation.
This specification does define TPM2_Vendor_TCG_Test() in order to have at least one command that
can be used to ensure the proper operation of the command dispatch code when processing a vendor-
specific command.
34.2 TPM2_Vendor_TCG_Test
General Description
Detailed Actions
1 #include "Tpm.h"
2 #if CC_Vendor_TCG_Test // Conditional expansion of this file
3 #include "Vendor_TCG_Test_fp.h"
4 TPM_RC
5 TPM2_Vendor_TCG_Test(
6 Vendor_TCG_Test_In *in, // IN: input parameter list
7 Vendor_TCG_Test_Out *out // OUT: output parameter list
8 )
9 {
10 out->outputData = in->inputData;
11 return TPM_RC_SUCCESS;
12 }
13 #endif // CC_Vendor_TCG_Test