| <?xml version="1.0"?> |
| <!DOCTYPE rfc SYSTEM "rfc2629.dtd" [ |
| <!-- One method to get references from the online citation libraries. |
| There has to be one entity for each item to be referenced. |
| An alternate method (rfc include) is described in the references. |
| --> |
| <!ENTITY RFC2119 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml"> |
| <!ENTITY RFC8017 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.8017.xml"> |
| ]> |
| <?rfc toc="yes" ?> |
| <rfc ipr="trust200902" category="info" docName="draft-bottomley-tpm-keys-00"> |
| <front> |
| <title abbrev="TPM 2 Key Format">ASN.1 Specification for TPM 2.0 Key Files</title> |
| <author initials="J." surname="Bottomley" fullname="James E.J. Bottomley"> |
| <organization>Linux Kernel</organization> |
| <address> |
| <postal> |
| <street/> |
| <city/> |
| <region/> |
| <country>USA</country> |
| </postal> |
| <email>James.Bottomley@HansenPartnership.com</email> |
| </address> |
| </author> |
| <date month="December" year="2023"/> |
| <area>Security</area> |
| <keyword>I-D</keyword> |
| <keyword>Internet-Draft</keyword> |
| <keyword>X.509</keyword> |
| <abstract> |
| <t> |
| This specification is designed to be an extension to the ASN.1 |
| (defined in <xref target="X.680"/>) specification of PKCS #1 |
| <xref target="RFC8017"/> to define the file format of private |
| keys that need to be loaded into a TPM 2 device to operate. |
| </t> |
| </abstract> |
| </front> |
| <middle> |
| <section anchor="intro" title="Introduction"> |
| <t> |
| The Security of private keys has long been a concern and the |
| ability of ubiquitous devices like TPMs has made it useful to |
| use them for secure private key storage. With the advent of |
| TPM 2.0, private key storage inside the TPM (acting as a token |
| which could be referred to by PKCS #11) has been discouraged, |
| and instead key files which are loaded and evicted as |
| necessary is the encouraged format. This standard defines an |
| interoperable ASN.1 representation for such key files, so that |
| a key created by one tool should be loadable by a different |
| one. |
| </t> |
| </section> |
| <section anchor="terms" title="Terminology"> |
| <t> |
| The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL |
| NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and |
| "OPTIONAL" in this document are to be interpreted as described in |
| <xref target="RFC2119"/>. |
| </t> |
| <section title="Notation"> |
| <dl> |
| <dt>ASN.1</dt> |
| <dd>Abstract Syntax Notation defined in |
| <xref target="X.680"/></dd> |
| <dt>DER</dt> |
| <dd>Distinguished Encoding Rules. Basically a defined binary |
| representation for ASN.1</dd> |
| <dt>MSO</dt> |
| <dd>Most Significant Octet (the highest order |
| byte of an integer)</dd> |
| <dt>PEM</dt> |
| <dd>Privacy enhanced Electronic Mail. An ASCII compatible |
| representation of DER</dd> |
| <dt>TCG</dt> |
| <dd>Trusted Computing Group</dd> |
| <dt>TPM</dt> |
| <dd>Trusted Platform Module</dd> |
| </dl> |
| </section> |
| </section> |
| <section anchor="keyrep" title="Key Representation"> |
| <t> |
| All TPM 2.0 keys consist of two binary pieces, a public part, |
| which can be parsed according to the TPM specification for |
| TPM2B_PUBLIC <xref target="TPM2.0"/> and a private part, which |
| is cryptographically sealed in such a way as to be only |
| readable on the TPM that created it. The purpose of this |
| specification is to specify a format by which the public and |
| private pieces of a TPM key can be loaded. |
| </t> |
| <t> |
| The design of the TPMkey ASN.1 format is that it should have a |
| distinguishing OID at the beginning so the DER form of the |
| key can be easily recognized. In PEM form, the key MUST have |
| "-----BEGIN TSS2 PRIVATE KEY-----" and "-----END TSS2 PRIVATE |
| KEY-----" as the PEM guards. All additional information that |
| may be needed to load the key is specified as optional |
| explicit elements, which can be extended by later |
| specifications, which is why the TPMkey is not versioned. |
| </t> |
| <section anchor="tpmkey" title="TPMkey Syntax"> |
| <sourcecode type="asn.1"> |
| TPMKey ::= SEQUENCE { |
| type OBJECT IDENTIFIER, |
| emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL, |
| policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL, |
| secret [2] EXPLICIT OCTET STRING OPTIONAL, |
| authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL, |
| description [4] EXPLICIT UTF8String OPTIONAL, |
| rsaParent [5] EXPLICIT BOOLEAN OPTIONAL, |
| parent INTEGER, |
| pubkey OCTET STRING, |
| privkey OCTET STRING |
| } |
| </sourcecode> |
| <t> |
| The fields of type TPMKey have the following meanings: |
| </t> |
| <section title="type"> |
| <t> |
| A unique OID specifying the key type. This standard |
| currently defines three types of keys: a loadable key, |
| specified by id-loadablekey, (to be loaded with |
| TPM2_Load), an importable key, specified by |
| id-importablekey, (to be loaded with TPM2_Import) and a |
| sealed data key, specified by id-sealedkey, (to be |
| extracted with TPM2_Unseal). The TCG has reserved the |
| following OID prefix for this: |
| </t> |
| <sourcecode type="asn.1"> |
| id-tpmkey OBJECT IDENTIFIER ::= |
| {joint-iso-itu-t(2) international-organizations(23) 133 10 1} |
| </sourcecode> |
| <t> |
| And the three key types are: |
| </t> |
| <sourcecode type="asn.1"> |
| id-loadablekey OBJECT IDENTIFIER ::= |
| {id-tpmkey 3} |
| </sourcecode> |
| <sourcecode type="asn.1"> |
| id-importablekey OBJECT IDENTIFIER ::= |
| {id-tpmkey 4} |
| </sourcecode> |
| <sourcecode type="asn.1"> |
| id-sealedkey OBJECT IDENTIFIER ::= |
| {id-tpmkey 5} |
| </sourcecode> |
| </section> |
| <section title="emptyAuth"> |
| <t> |
| An implementation needs to know as it formulates the |
| TPM2_Load/Import/Unseal command whether it must also send |
| down an authorization, so this parameter gives that |
| indication. emptyAuth MUST be true if authorization is |
| NOT required and MUST BE either false or absent if |
| authorization is required. Since this element has |
| three states (one representing true and two representing |
| false) it is RECOMMENDED that implementations emitting |
| TPMkey representations use absence of the tag to represent |
| false. However, implementations reading TPMKey MUST |
| be able to process all three possible states. |
| </t> |
| </section> |
| <section title="policy"> |
| <t> |
| This MUST be present if the TPM key has a policy hash |
| because it describes to the implementation how to |
| construct the policy. The forms of the policy statement |
| are described in <xref target="policy"/>. |
| </t> |
| </section> |
| <section title="secret"> |
| <t> |
| This section describes the additional cryptographic |
| secret used to specify the outer wrapping of an |
| importable key. It MUST be present for key type |
| id-importablekey and MUST NOT be present for any other |
| key type. |
| </t> |
| <t> |
| Importable keys (designed to be processed by TPM2_Import) |
| MUST have an unencrypted inner wrapper (symmetricAlg MUST |
| be TPM_ALG_NULL and encryptionKey MUST be empty) and an |
| outer wrapper encrypted to the parent key using |
| inSymSeed. The secret parameter is the fully marshalled |
| TPM2B_ENCRYPTED_SECRET form of inSymSeed. |
| </t> |
| </section> |
| <section title="authPolicy"> |
| <t> |
| This SHOULD be present if the TPMkey policy contains a |
| TPM2_PolicyAuthorize statement because it contains signed |
| policies that could be used to satisfy the TPM key policy. |
| The forms of the authPolicy statement are described in |
| <xref target="signed-policy"/>. If the TPM key |
| has no policy hash then this MUST NOT be present. |
| </t> |
| </section> |
| <section title="description"> |
| <t> |
| An optional string description for the key which is |
| only used for display purposes, MAY be used as a user |
| visible mnemonic for the key. |
| </t> |
| </section> |
| <section title="rsaParent"> |
| <t> |
| This MUST be present and true if the parent is a permanent |
| handle (MSO 0x40) and RSA 2048 is used for the primary key. |
| If the parent is not a permanent handle then this MUST NOT |
| be present. If the parent is a permanent handle and if |
| P-256 is used for the primary then this MUST NOT be present. |
| Given that P-256 primary keys are easier to generate, |
| implementations SHOULD NOT set this flag. |
| </t> |
| </section> |
| <section title="parent"> |
| <t> |
| This MUST be present for all keys and specifies the handle |
| of the parent key. The parent key SHOULD be either a |
| persistent handle (MSO 0x81) or a permanent handle (MSO |
| 0x40). Since volatile handle numbering can change |
| unexpectedly depending on key load order, the parent |
| SHOULD NOT be a volatile handle (MSO 0x80). The parent MUST |
| NOT have any other MSO. |
| </t> |
| <t> |
| If a permanent handle (MSO 0x40) is specified then the |
| implementation MUST run TPM2_CreatePrimary on the handle |
| using the TCG specified Elliptic Curve template <xref |
| target="TCG-Provision"/> (section 7.5.1 for the Storage |
| and other seeds or 7.4.1 for the endorsement seed) for |
| the NIST P-256 curve if rsaParent is absent or the RSA |
| template with a key length of 2048 if rsaParent is |
| present and true and use the primary key so generated |
| as the parent. |
| </t> |
| </section> |
| <section title="pubkey"> |
| <t> |
| This MUST be present and MUST correspond to the fully |
| marshalled TPM2B_PUBLIC structure of the TPM Key. |
| </t> |
| </section> |
| <section title="privkey"> |
| <t> |
| This MUST be present and MUST correspond to the fully |
| marshalled TPM2B_PRIVATE structure of the TPM Key. For |
| importable keys, this must be the duplicate parameter that |
| would be input to TPM2_Import. |
| </t> |
| </section> |
| </section> |
| </section> |
| <section anchor="policy" title="Key Policy Specification"> |
| <t> |
| Policy is constructed on a TPM by executing a sequence of |
| policy statements. This specification currently only defines |
| a limited subset of the allowed policy statements. The policy |
| is specified by a hash, which the execution of the policy |
| statements must reach in order for the policy to be validated |
| (See <xref target="TPM2.0"/> Part 1 for a detailed description. |
| </t> |
| <t> |
| The TPMPolicy ASN.1 MUST be a sequence of policy statements |
| which correspond exactly to TPM policy instructions in the |
| order they should be executed and additionally from which the |
| ultimate policy hash can be constructed. |
| </t> |
| <t> |
| The current policy specification is strictly for AND based |
| policy only and may be extended at a later date with OR |
| policy. However, the ASN.1 for policy is formulated as CONS |
| elements, leaving the possibility of adding additional but |
| optional elements for policy statements which are not |
| supported by this standard (such as TPM2_PolicyAuthorize). |
| </t> |
| <section anchor="TPMPolicy" title="TPMPolicy Syntax"> |
| <sourcecode type="asn.1"> |
| TPMPolicy ::= SEQUENCE { |
| commandCode [0] EXPLICIT INTEGER, |
| commandPolicy [1] EXPLICIT OCTET STRING |
| } |
| </sourcecode> |
| <t> |
| The Fields of type TPMPolicy have the following meanings: |
| </t> |
| <section title="CommandCode"> |
| <t> |
| This is the integer representation of the TPM command code |
| for the policy statement. |
| </t> |
| </section> |
| <section title="CommandPolicy"> |
| <t> |
| This is a binary string representing a fully marshalled, |
| TPM ordered, command body for the TPM policy command. |
| Therefore to send the command, the implementation simply |
| marshals the command code and appends this octet string |
| as the body. |
| </t> |
| <t> |
| Commands which have no body, such as TPM2_AuthVal, MUST be |
| specified as a zero length OCTET STRING |
| </t> |
| <t> |
| Note that there are some commands for which the simple |
| body of the TPM policy command does not provide enough |
| information to execute the policy command. A classic |
| example is TPM2_PolicyAuthorize, whose body consists of a |
| key name, a policyRef nonce and a signature. However, the |
| implementation needs to know the actual key, not just the |
| name, to implement the policy. Commands whose |
| CommandPolicy must be marshalled differently are noted in |
| <xref target="policy-exceptions"/>. |
| </t> |
| </section> |
| </section> |
| <section anchor="policy-exceptions" title="PolicyCommand Exceptions"> |
| <t> |
| For some TPM2_Policy... commands, the information required |
| to formulate the policy cannot be extracted from the body of |
| the command and so additional information must be supplied, |
| meaning these commands deviate from the <xref |
| target="TPM2.0"/> policy body specifications. The |
| CommandPolicy format for these exceptional commands is |
| documented below. |
| </t> |
| <section title="TPM2_PolicyAuthorize"> |
| <t> |
| According to <xref target="TPM2.0"/> the body of this |
| command consists of TPM2B_DIGEST approvedPolicy, |
| TPM2B_NONCE policyRef, TPM2B_NAME keySign and |
| TPM_TK_VERIFIED checkTicket. However, implementations |
| must construct checkTicket at the time of policy execution |
| from the public key of keySign and the signed policy hash. |
| Additionally, implementations constructing a signed policy |
| need to know the sequence of policy steps they must |
| execute to produce approvedPolicy, but do not need to know |
| its value because the construction steps will either fail |
| or the end policy session will have the required hash. |
| The implementation must know this end policyHash to |
| construct the signature over it, but this information does |
| not need to be stored in CommandPolicy. |
| </t> |
| <t> |
| The format of CommandPolicy for TPM2_PolicyAuthorize MUST |
| be TPM2B_PUBLIC keySign, TPM2B_DIGEST policyRef, TPMT_SIGNATURE |
| policySignature. |
| </t> |
| </section> |
| <section title="TPM2_PolicySecret"> |
| <t> |
| According to <xref target="TPM2.0"/> the body of this |
| command consists of the handle of the authorizing object, |
| TPM2B_NONCE nonceTPM, TPM2B_DIGEST cpHashA, TPM2B_NONCE |
| policyRef and INT32 expiration. However, the policyHash |
| only uses policyRef and the name of the authorizing |
| object. Since the usual authorizing object for |
| TPM2_PolicySecret is a permanent handle or NV Index, and |
| those are hard to find by name, the handle is also given |
| as an optional hint in addition to the name. |
| </t> |
| <t> |
| The format of CommandPolicy for TPM2_PolicySecret MUST be |
| TPM_HANDLE objectHandleHint, TPM2B_NAME objectName, |
| TPM2B_DIGEST policyRef. Where objectHandleHint MAY be |
| zero to indicate no hint. |
| </t> |
| </section> |
| </section> |
| <section title="Policy Implementation Considerations"> |
| <t> |
| The policy hash for AND based policies is constructed by |
| extension of the prior policy hash |
| </t> |
| <figure><artwork> |
| newHash = HASH ( oldHash || policyHash ) |
| </artwork></figure> |
| <t> |
| where policyHash is usually simply the hash of the fully |
| marshalled policy command (including the CommandCode). |
| However, this isn't true for TPM2_PolicyCounterTimer so |
| always consult the <xref target="TPM2.0"/> specifications |
| for how to construct the policyHash. |
| </t> |
| <t> |
| The implementation should fail fast for policy problems, so |
| if an individual policy command returns a failure (which |
| usually indicates a particular policy requirement cannot be |
| met), that failure should be reported in as much detail as |
| possible and processing of the key should fail at that |
| point. |
| </t> |
| <t> |
| If signed policies are present, the first policy statement |
| MUST be TPM2_PolicyAuthorize giving the public key, the |
| nonce and and having an empty signature. |
| TPM_PolicyAuthorize() MAY NOT appear in any subsequent |
| position. |
| </t> |
| <section title="Authorization Policy"> |
| <t> |
| When Authorization (Passing in a password) is required, |
| the emptyAuth parameter MUST be absent or set to false and |
| additionally TPM_CC_PolicyAuthValue or TPM_CC_PolicySecret |
| MUST be specified as the command code for one entry in the |
| TPMPolicy sequence. However, when TPM2_PolicyAuthValue is |
| specified, the implementation MAY choose to execute either |
| TPM2_PolicyPassword for TPM_RS_PW or TPM2_PolicyAuthValue |
| for HMAC based authorization depending on whether the |
| command being authorized is using sessions or not. If the |
| policy does not require an authorization then the |
| emptyAuth parameter MUST be set to true. |
| </t> |
| <t> |
| Implementations should bear in mind that most crypto |
| systems with key management expect to consume only one |
| password per key, so implementations SHOULD avoid policy |
| chains which would require more than one password as would |
| happen when TPM2_PolicySecret and TPM2_PolicyAuthValue |
| both appear in the same policy chain. Implementations MAY |
| detect and emit an error in this case. |
| </t> |
| </section> |
| </section> |
| </section> |
| <section anchor="signed-policy" title="Signed Policy Specification"> |
| <t> |
| One feature of TPM policy execution is the command |
| TPM2_PolicyAuthorize does not operate by extending the |
| current policy hash, it completely replaces it with a hash of |
| the signing key and a nonce called the policyRef. In order |
| for this replacement to happen, TPM2_PolicyAuthorize must be |
| presented with a ticket confirming verification of a signature |
| over the old policy hash and the nonce. Since anyone |
| possessing the private key named in the policy hash can sign a |
| new policy to present, the key can have multiple signed |
| policies, any or all of which might succeed, so a new |
| structure had to be introduced to store current signed |
| policies. |
| </t> |
| <section title="TPMAuthPolicy Syntax"> |
| <sourcecode type="asn.1"> |
| TPMAuthPolicy ::= SEQUENCE { |
| name [0] EXPLICIT UTF8String OPTIONAL, |
| policy [1] EXPLICIT SEQUENCE OF TPMPolicy |
| } |
| </sourcecode> |
| <t> |
| The Fields of type TPMAuthPolicy have the following meanings: |
| </t> |
| <section title="Name"> |
| <t> |
| An optional string name for the current policy which is |
| only used for display purposes, MAY be used as a user |
| visible mnemonic for the actual policy. |
| </t> |
| </section> |
| <section title="Policy"> |
| <t> |
| A sequence of TPMPolicy statements (see <xref |
| target="TPMPolicy"/>) which MUST end with a |
| PolicyAuthorize statement whose signature is over the hash |
| of the current policy excluding the PolicyAuthorize |
| statement and the nonce specified at the beginning of the |
| TPMKey policy. There MUST be no other |
| TPM2_PolicyAuthorize statements in the intermediate policy |
| steps. There MAY be an initial TPM2_PolicyAuthorize |
| statement containing a different public key (because this |
| causes complexity building signed policy chains, |
| implementations MAY choose to allow only a single policy |
| signing key, in which case there MAY NOT be an initial |
| TPM2_PolicyAuthorize statement). |
| </t> |
| </section> |
| </section> |
| <section title="Signed Policy Implementation Considerations"> |
| <t> |
| The key can only be used if one of the policies in TPMKey |
| authPolicy actually succeeds. The implementation SHOULD try |
| each policy in authPolicy sequentially. If the policy fails |
| to match the implementation SHOULD try the next policy. If |
| all statement succeed, the implementation should then |
| execute the final TPM2_PolicyAuthorize statement and then |
| begin executing the policy statements in TPMKeyPolicy |
| excluding the initial TPM2_PolicyAuthorize one (if there |
| are any subsequent statements). |
| </t> |
| <t> |
| Because policies are tried sequentially, implementations |
| SHOULD order the policies such that the most likely to |
| succeed appears first. For instance, if the key is used to |
| unlock a disk and is tied by policy to the hash of the OS |
| kernel, then the policy tied to the current kernel should |
| appear first followed by subsequent policies tied to older |
| kernels because the most likely kernel to be booted is the |
| current one. |
| </t> |
| <t> |
| Since the policy order will likely change when a new policy |
| is added (in the kernel example, when a kernel is updated, |
| the newly added kernel becomes current and the signed policy |
| tied to this kernel should become the first one in the |
| TPMkey), users should keep track of policies using the |
| optional mnemonic name and not rely on position in the |
| TPMAuthPolicy sequence. |
| </t> |
| <section title="Authorization Policy"> |
| <t> |
| There may now be multiple possible policies which |
| authorize the key, some of which might contain |
| TPM2_PolicyAuthValue requirements (passing in a password) and |
| others of which might not, emptyAuth MUST not be set if |
| the TPMKey contains an Authorization Secret (password), |
| even if testing knowledge of such a secret may not be |
| required by signed policy. Implementations MAY choose to |
| scan the likely policies to see whether to prompt for a |
| password or MAY choose to prompt based on emptyAuth. The |
| latter is more likely to be successful, because most |
| implementations will have a password prompt at key load |
| time which may be some time before the key is actually |
| used, by which time the list of successful policies may be |
| different due to changes on the system. |
| </t> |
| <t> |
| The most common use for TPM2_PolicyAuthValue is as a |
| backup policy when all other policies tied to system |
| configuration fail. For this use case, a password |
| prompted for is almost never used, except in the rare |
| event the system gets into a state where none of the other |
| policies apply. If an implementation always prompts for a |
| password based on emptyAuth, then most of the time the |
| prompted for password will not be used. For this use |
| case, consumers may safely pass in an empty password when |
| the implementation asks and only provide the real password |
| if all other policies fail. In the kernel boot example |
| this would mean that the entity that unlocks the disk |
| should first try the key with an empty password, assuming |
| one non-password based policy will succeed and only go |
| back and ask the user for a password if the disk unlock |
| fails. |
| </t> |
| </section> |
| <section title="Signed Policy Revocation"> |
| <t> |
| The signature in a TPM2_PolicyAuthorize statement has no |
| expiry or revocation capabilities. Consumers should |
| remember that simply removing a signed policy from the key |
| does not guarantee that the removed policy will never be |
| used. Any subsequent consumer who obtains the policy |
| signature could potentially add the removed policy back to |
| the key. Therefore, use cases which may need to expire or |
| revoke the policy SHOULD build into the policy specific |
| expiration or revocation criteria using TPM policy |
| statements. |
| </t> |
| <t> |
| The easiest policy statement for expiration is to use |
| TPM2_PolicyCounterTimer. Users should remember that the |
| TPM time is guaranteed to be monotonic, but the TPM timer |
| does not tick while the machine is powered down and any |
| user may arbitrarily increase (but never decrease) the TPM |
| clock count. It is recommended that policies tied to |
| booting a system (as in the kernel boot disk unlock above) |
| should base their expiration on reboot count rather than |
| the TPM clock. |
| </t> |
| </section> |
| <section title="Policy Signing Keys and policyRef values"> |
| <t> |
| There is a high likelihood that a consumer would use the |
| same policy signing key for multiple TPM objects with |
| signed policy. This gives rise to the risk that a |
| malicious user could extract signed policy meant for key1 |
| and use it instead with key2 (policy swapping). To |
| mitigate this risk, the implementation SHOULD place a high |
| entropy nonce in policyRef to ensure that each key has a |
| different policyRef which prevents this policy swapping. |
| </t> |
| <t> |
| The TCG specifies that policyRef could have an |
| implementation defined meaning in which case |
| implementations MAY use implementation meaningful values |
| instead of nonces for policyRef but SHOULD take other |
| measures to prevent policy swapping. |
| </t> |
| </section> |
| </section> |
| </section> |
| <section anchor="implementation" title="Implementation Considerations"> |
| <t> |
| Implementations SHOULD support all TCG mandated algorithms, |
| but MAY omit those deemed insecure, such as the SHA1 hash. |
| </t> |
| <t> |
| TPM2_Import transforms the privKey into a TPM2B_PRIVATE which |
| can then be used as a source to TPM2_Load, making the loading |
| of importable keys is necessarily a two stage process, which |
| can be time consuming on some TPMs. Since the TPM2B_PRIVATE |
| structure emitted by TPM2_Import is fully secure, |
| Implementations SHOULD minimize the number of TPM2_Import |
| operations by caching the emitted TPM2B_PRIVATE. |
| </t> |
| </section> |
| <section anchor="security" title="Security Considerations"> |
| <t> |
| The TPM 2.0 supports a variety of algorithms, the most common |
| being SHA1 and SHA256 for hashing and RSA2048 and NIST P-256 |
| for asymmetric keys. Implementors SHOULD NOT use deprecated |
| algorithms, such as SHA1, for any TPM operation. In |
| particular, the algorithm used for the policy hash SHOULD NOT |
| be SHA1 and this means that SHA1 SHOULD NOT be used as the |
| name algorithm hash for any TPM key. |
| </t> |
| <t> |
| TPM 2.0 supports a session mode (TPM_RS_PW) where |
| authorizations are passed to the TPM in clear text over the |
| TPM connection. Implementations SHOULD consider the |
| possibility of snooping on the wire between the implementation |
| and the TPM, such as <xref target="TPM GENIE"/>, and SHOULD |
| use HMAC session authorizations as best practice for all TPM |
| keys. |
| </t> |
| <t> |
| In addition to snooping authorizations, snooping may also |
| occur when key material is being exchanged between the TPM and |
| the implementation, such as wrapping of private keys and the |
| sealing and unsealing operations for sealed keys. |
| Implementations SHOULD always use HMAC sessions with |
| TPMA_SESSION_DECRYPT when sensitive information is passed in |
| to the TPM and HMAC sessions with TPMA_SESSION_ENCRYPT when |
| sensitive information is received from the TPM. |
| </t> |
| <t> |
| The easiest way to get the TPM to wrap an external private key |
| is to use TPM2_Import. However, since TPMA_SESSION_DECRYPT |
| only protects the first parameter (which is encryptionKey), |
| the duplicate should use inner symmetric encryption with a |
| randomly generated ephemeral key, which is then presented to |
| the TPM via the protected encryptionKey parameter. |
| </t> |
| <t> |
| The TPM has a mode where it can generate private key material |
| internally (using TPM2_Create) such that the private part of |
| the key can never leave the TPM. Implementations SHOULD |
| support this mode but should be aware that while keys created |
| like this may be more secure than wrapped keys, they can also |
| be used only while access to the TPM that created them is |
| available, so implementations SHOULD also support wrapping for |
| keys that are expected to outlive the TPM that's using them. |
| Clients can then develop best practices around TPM wrapped |
| identity keys, possibly with TPM created sub keys, which can |
| only be used on the device they were wrapped for. |
| </t> |
| <t> |
| Since TPM keys can only be used by the specific TPM that |
| created them, which is usually embedded in a piece of |
| hardware, they are secure against exfiltration attacks. |
| However, consideration should be given to an attacker gaining |
| access to the system containing the TPM. TPM keys are most |
| secure when used as part of an operating system that has |
| guaranteed trust properties, such as secure and measured boot. |
| Implementations SHOULD assist users in constructing key |
| policies that ensure the key can be used only when the |
| operating system is within its trusted parameters to minimize |
| threats from co-located attackers. |
| </t> |
| </section> |
| <section anchor="IANA" title="IANA Considerations"> |
| <t> |
| None. |
| </t> |
| </section> |
| <section anchor="comments" title="Comments on and Enhancements to this Document"> |
| <t> |
| Comments on this document should be addressed to the author |
| (James.Bottomley@HansenPartnership.com) but should also CC the |
| email lists of the two projects implementing this |
| specification: |
| </t> |
| <t> |
| The OpenSSL engine: openssl_tpm2_engine@groups.io |
| </t> |
| <t> |
| The Linux Kernel: linux-integrity@vger.kernel.org |
| </t> |
| <t> |
| The OpenSSL TPM2 engine <xref target="OPENSSL TPM2 ENGINE"/> |
| is currently the only implementation of this full |
| specification, so enhancements should be proposed after |
| patches implementing the enhancement have been accepted by |
| openssl_tpm2_engine or another full specification |
| implementation. |
| </t> |
| </section> |
| </middle> |
| <back> |
| <references title="Normative References"> |
| &RFC2119; |
| &RFC8017; |
| <reference anchor="TPM2.0" target="https://trustedcomputinggroup.org/resource/tpm-library-specification/"> |
| <front> |
| <title>TPM 2.0 Library Specification</title> |
| <author> |
| <organization>Trusted Computing Group</organization> |
| </author> |
| <date year="2013" month="March" day="15"/> |
| </front> |
| </reference> |
| <reference anchor="X.680" target="https://itu.int/rec/T-REC-X.680-201508-I/en"> |
| <front> |
| <title>ITU-T Recommendation X.680, |
| Information technology - Abstract Syntax Notation One |
| (ASN.1): Specification of basic notation.</title> |
| <author><organization>International Telecommunication Union</organization></author> |
| <date year="2015" month="August"/> |
| </front> |
| </reference> |
| <reference anchor="TCG-Provision" target="https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance/"> |
| <front> |
| <title>TCG TPM v2.0 Provisioning Guidance</title> |
| <author> |
| <organization>Trusted Computing Group</organization> |
| </author> |
| <date year="2017" month="March" day="15"/> |
| </front> |
| </reference> |
| </references> |
| <references title="Informative References"> |
| <reference anchor="TPM GENIE" target="https://www.nccgroup.com/globalassets/about-us/us/documents/tpm-genie.pdf"> |
| <front> |
| <title>TPM Genie: Interposer Attacks Against the Trusted |
| Platform Module Serial Bus</title> |
| <author initials="J." surname="Boone" fullname="J. Boone"> |
| <organization>NCC Group</organization> |
| </author> |
| <date year="2018" month="March" day="9"/> |
| </front> |
| </reference> |
| <reference anchor="OPENSSL TPM2 ENGINE" target="https://git.kernel.org/pub/scm/linux/kernel/git/jejb/openssl_tpm2_engine.git/"> |
| <front> |
| <title>OpenSSL TPM2 Engine</title> |
| <author><organization>Open Source Project</organization></author> |
| </front> |
| </reference> |
| </references> |
| <section anchor="asn1-module" title="ASN.1 Module"> |
| <sourcecode type="asn.1"> |
| TPM-Key-Module |
| |
| DEFINITIONS IMPLICIT TAGS ::= |
| BEGIN |
| |
| -- |
| -- Should import this but TCG hasn't yet published it or .10 |
| -- |
| id-tpmkey OBJECT IDENTIFIER ::= |
| {joint-iso-itu-t(2) international-organizations(23) 133 10 1} |
| |
| -- |
| -- OIDs defined by this RFC |
| -- |
| id-loadablekey OBJECT IDENTIFIER ::= {id-tpmkey 3} |
| id-importablekey OBJECT IDENTIFIER ::= {id-tpmkey 4} |
| id-sealedkey OBJECT IDENTIFIER ::= {id-tpmkey 5} |
| |
| TPMPolicy ::= SEQUENCE { |
| commandCode [0] EXPLICIT INTEGER, |
| commandPolicy [1] EXPLICIT OCTET STRING |
| } |
| |
| TPMAuthPolicy ::= SEQUENCE { |
| name [0] EXPLICIT UTF8String OPTIONAL, |
| policy [1] EXPLICIT SEQUENCE OF TPMPolicy |
| } |
| |
| TPMKeyType ::= OBJECT IDENTIFIER ( |
| id-loadablekey | |
| id-importablekey | |
| id-sealedkey |
| ) |
| |
| TPMKey ::= SEQUENCE { |
| type TPMKeyType, |
| emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL, |
| policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL, |
| secret [2] EXPLICIT OCTET STRING OPTIONAL, |
| authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL, |
| description [4] EXPLICIT UTF8String OPTIONAL, |
| rsaParent [5] EXPLICIT BOOLEAN OPTIONAL, |
| parent INTEGER, |
| pubkey OCTET STRING, |
| privkey OCTET STRING |
| } |
| |
| END |
| </sourcecode> |
| </section> |
| </back> |
| </rfc> |