Adds the xml file for the draft RFC and builds text and html versions if the xml2rfc program is found. Signed-off-by: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> --- v2: Add missing sections plus minor updates --- Makefile.am | 2 +- configure.ac | 4 +- doc/Makefile.am | 15 + doc/draft-bottomley-tpm2-keys.xml | 465 ++++++++++++++++++++++++++++++ 4 files changed, 484 insertions(+), 2 deletions(-) create mode 100644 doc/Makefile.am create mode 100644 doc/draft-bottomley-tpm2-keys.xml diff --git a/Makefile.am b/Makefile.am index 33de0d9..787ba29 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,4 +41,4 @@ $(builddir)/%.1: $(srcdir)/%.1.in $(top_builddir)/% install-data-hook: cd $(DESTDIR)$(openssl_enginedir) && $(LN_S) -f libtpm2@SHREXT@ tpm2@SHREXT@ -SUBDIRS = tests +SUBDIRS = tests doc diff --git a/configure.ac b/configure.ac index 6efa7a5..e102dd2 100644 --- a/configure.ac +++ b/configure.ac @@ -128,6 +128,8 @@ fi AC_PATH_PROG(TPMSERVER, tpm_server,,/bin:/usr/bin:/usr/lib/ibmtss:/usr/libexec/ibmtss) AC_PATH_PROG(SWTPM, swtpm,,/bin:/usr/bin:/usr/lib/ibmtss:/usr/libexec/ibmtss) AC_PATH_PROG(SWTPM_IOCTL, swtpm_ioctl,,/bin:/usr/bin:/usr/lib/ibmtss:/usr/libexec/ibmtss) +AC_CHECK_PROG(XML2RFC, xml2rfc, xml2rfc) +AM_CONDITIONAL(HAVE_XML2RFC, test -n "${XML2RFC}") CFLAGS="$CFLAGS -Wall" SHREXT=$shrext_cmds AC_SUBST(CFLAGS) @@ -147,7 +149,7 @@ fi AC_SUBST(testtpm) -AC_OUTPUT([Makefile tests/Makefile]) +AC_OUTPUT([Makefile tests/Makefile doc/Makefile]) cat <<EOF diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..0c24ce0 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,15 @@ +XML2RFC_TARGETS = draft-bottomley-tpm2-keys.txt \ + draft-bottomley-tpm2-keys.html + +if HAVE_XML2RFC +all: $(XML2RFC_TARGETS) + +clean-local: + rm -fr $(XML2RFC_TARGETS) +endif + +$(builddir)/%.txt: $(srcdir)/%.xml + $(XML2RFC) --text -o $@ $< + +$(builddir)/%.html: $(srcdir)/%.xml + $(XML2RFC) --html -o $@ $< diff --git a/doc/draft-bottomley-tpm2-keys.xml b/doc/draft-bottomley-tpm2-keys.xml new file mode 100644 index 0000000..d2e9235 --- /dev/null +++ b/doc/draft-bottomley-tpm2-keys.xml @@ -0,0 +1,465 @@ +<?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@xxxxxxxxxxxxxxxxxxxxx</email> + </address> + </author> + <date month="May" year="2021"/> + <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"> + <figure><artwork> + TPMKey ::= SEQUENCE { + type OBJECT IDENTIFIER + emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL + policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL + secret [2] EXPLICIT OCTET STRING OPTIONAL + parent INTEGER + pubkey OCTET STRING + privkey OCTET STRING + } + </artwork></figure> + <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> + <figure><artwork> + id-tpmkey OBJECT IDENTIFIER ::= + {joint-iso-itu-t(2) international-organizations(23) 133 10} + </artwork></figure> + <t> + And the three key types are: + </t> + <figure><artwork> + id-loadablekey OBJECT IDENTIFIER ::= + {id-tpmkey 3} + </artwork></figure> + <figure><artwork> + id-importablekey OBJECT IDENTIFIER ::= + {id-tpmkey 4} + </artwork></figure> + <figure><artwork> + id-sealedkey OBJECT IDENTIFIER ::= + {id-tpmkey 5} + </artwork></figure> + </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 section <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="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 for the + NIST P-256 curve 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 title="TPMPolicy Syntax"> + <figure><artwork> + TPMPolicy ::= SEQUENCE { + CommandCode [0] EXPLICIT INTEGER + CommandPolicy [1] EXPLICIT OCTET STRING + } + </artwork></figure> + <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 + marshalls 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> + </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> + <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 the TPM_CC_PolicyAuthValue MUST be + specified as the command code for one entry in the + TPMPolicy sequence. However, 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> + </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@xxxxxxxxxxxxxxxxxxxxx) but should also CC the + email lists of the two projects implementing this + specification: + </t> + <t> + The OpenSSL engine: openssl_tpm2_engine@xxxxxxxxx + </t> + <t> + The Linux Kernel: linux-integrity@xxxxxxxxxxxxxxx + </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> + </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> + </back> +</rfc> -- 2.26.2