TPM 2.0 trusted key rework
Subsystems (7)
James Bottomley
maintainerv14 cover TPM 2.0 trusted key rework
v14: add tested by flags and fix one more 0day select problem
General cover letter minus policy bit:
This patch updates the trusted key code to export keys in the ASN.1 format used by current TPM key tools (openssl_tpm2_engine and openconnect). The current code will try to load keys containing policy, but being unable to formulate the policy commands necessary to load them, the unseal will always fail unless the policy is executed in user space and a pre-formed policy session passed in.
The key format is designed to be compatible with our two openssl engine implementations as well as with the format used by openconnect. I've added seal/unseal to my engine so I can use it for interoperability testing and I'll later use this for sealed symmetric keys via engine:
https://git.kernel.org/pub/scm/linux/kernel/git/jejb/openssl_tpm2_engine.git/
James
---
James Bottomley (5):
lib: add ASN.1 encoder
oid_registry: Add TCG defined OIDS for TPM keys
security: keys: trusted: fix TPM2 authorizations
security: keys: trusted: use ASN.1 TPM2 key format for the blobs
security: keys: trusted: Make sealed key properly interoperable
.../security/keys/trusted-encrypted.rst | 58 +++ include/keys/trusted-type.h | 2 + include/linux/asn1_encoder.h | 32 ++ include/linux/oid_registry.h | 5 + include/linux/tpm.h | 2 + lib/Kconfig | 3 + lib/Makefile | 1 + lib/asn1_encoder.c | 454 ++++++++++++++++++ security/keys/Kconfig | 3 + security/keys/trusted-keys/Makefile | 4 +- security/keys/trusted-keys/tpm2key.asn1 | 11 + security/keys/trusted-keys/trusted_tpm1.c | 34 +- security/keys/trusted-keys/trusted_tpm2.c | 266 +++++++++- 13 files changed, 844 insertions(+), 31 deletions(-) create mode 100644 include/linux/asn1_encoder.h create mode 100644 lib/asn1_encoder.c create mode 100644 security/keys/trusted-keys/tpm2key.asn1
Signature · 1 line
2.26.2
James Bottomley
maintainerPATCH v14 1/5 lib: add ASN.1 encoder
We have a need in the TPM2 trusted keys to return the ASN.1 form of the TPM key blob so it can be operated on by tools outside of the kernel. The specific tools are the openssl_tpm2_engine, openconnect and the Intel tpm2-tss-engine. To do that, we have to be able to read and write the same binary key format the tools use. The current ASN.1 decoder does fine for reading, but we need pieces of an ASN.1 encoder to write the key blob in binary compatible form.
For backwards compatibility, the trusted key reader code will still accept the two TPM2B quantities that it uses today, but the writer will only output the ASN.1 form.
The current implementation only encodes the ASN.1 bits we actually need.
---
v2: updated API to use indefinite length, and made symbol exports gpl
v3: add data length error handling
v4: use end_data instead of data_len pointer
v5: mention tools and space out code
v7: reverse christmas tree variable definitions and better spacing
v9: update comments, remove indefinite length, make encoder config dependent
--- include/linux/asn1_encoder.h | 32 +++ lib/Kconfig | 3 + lib/Makefile | 1 + lib/asn1_encoder.c | 454 +++++++++++++++++++++++++++++++++++ 4 files changed, 490 insertions(+) create mode 100644 include/linux/asn1_encoder.h create mode 100644 lib/asn1_encoder.c
include/linux/asn1_encoder.h new file +32 -0
@@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _LINUX_ASN1_ENCODER_H +#define _LINUX_ASN1_ENCODER_H + +#include <linux/types.h> +#include <linux/asn1.h> +#include <linux/asn1_ber_bytecode.h> +#include <linux/bug.h> + +#define asn1_oid_len (oid) (sizeof(oid)/sizeof(u32)) +unsigned char * +asn1_encode_integer (unsigned char *data,const unsigned char *end_data, +s64 integer); +unsigned char * +asn1_encode_oid (unsigned char *data,const unsigned char *end_data, +u32 oid[],int oid_len); +unsigned char * +asn1_encode_tag (unsigned char *data,const unsigned char *end_data, +u32 tag,const unsigned char *string,int len); +unsigned char * +asn1_encode_octet_string (unsigned char *data, +const unsigned char *end_data, +const unsigned char *string,u32 len); +unsigned char * +asn1_encode_sequence (unsigned char *data,const unsigned char *end_data, +const unsigned char *seq,int len); +unsigned char * +asn1_encode_boolean (unsigned char *data,const unsigned char *end_data, +bool val); + +#endif
lib/Kconfig +3 -0
@@ -689,3 +689,6 @@ config GENERIC_LIB_UCMPDI2 config PLDMFW bool default n + +config ASN1_ENCODER + tristate
lib/Makefile +1 -0
@@ -281,6 +281,7 @@ obj-$(CONFIG_INTERVAL_TREE_TEST) += interval_tree_test.o obj-$(CONFIG_PERCPU_TEST) += percpu_test.o obj-$(CONFIG_ASN1) += asn1_decoder.o +obj-$(CONFIG_ASN1_ENCODER) += asn1_encoder.o obj-$(CONFIG_FONT_SUPPORT) += fonts/
lib/asn1_encoder.c new file +454 -0
454 lines not on this page · raw message
Signature · 1 line
2.26.2
Re: [PATCH v14 1/5] lib: add ASN.1 encoder
Quoted 8 lines · James Bottomley
We have a need in the TPM2 trusted keys to return the ASN.1 form of the TPM key blob so it can be operated on by tools outside of the kernel. The specific tools are the
openssl_tpm2_engine, openconnect and the Intel tpm2-tss-engine. To do that, we have to be able to read and write the same binary key format the tools use. The current ASN.1 decoder does fine for reading, but we need pieces of an ASN.1 encoder to write the key blob in binary compatible form.
Quoted 8 lines
For backwards compatibility, the trusted key reader code will still accept the two TPM2B quantities that it uses today, but the writer will only output the ASN.1 form.
The current implementation only encodes the ASN.1 bits we actually need.
Signed-off-by James Bottomley <[email protected]>Reviewed-by Jarkko Sakkinen <[email protected]>
Also:
I've successfully used this multiple times already.
/Jarkko
Re: [PATCH v14 1/5] lib: add ASN.1 encoder
Quoted 15 lines · Jarkko Sakkinen
Quoted 14 lines · James Bottomley
We have a need in the TPM2 trusted keys to return the ASN.1 form of the TPM key blob so it can be operated on by tools outside of the kernel. The specific tools are the
openssl_tpm2_engine, openconnect and the Intel tpm2-tss-engine. To do that, we have to be able to read and write the same binary key format the tools use. The current ASN.1 decoder does fine for reading, but we need pieces of an ASN.1 encoder to write the key blob in binary compatible form.For backwards compatibility, the trusted key reader code will still accept the two TPM2B quantities that it uses today, but the writer will only output the ASN.1 form.
The current implementation only encodes the ASN.1 bits we actually need.
Quoted 8 lines
Quoted 2 lines
Signed-off-by James Bottomley <[email protected]>Reviewed-by Jarkko Sakkinen <[email protected]>Also:
Tested-by Jarkko Sakkinen <[email protected]>I've successfully used this multiple times already.
Hmm... Does this need ack from anyone outside of TPM space?
/Jarkko
Re: [PATCH v14 1/5] lib: add ASN.1 encoder
In reply to James Bottomleylib/asn1_encoder.c line 301
Quoted 1 line · James Bottomley
lib/asn1_encoder.c new file +1
-0+ *(data++) =_tagn (CONT ,CONS , tag);
You might want to move the _tag() and _tagn() macros into linux/asn1.h so that you don't need to include asn1_ber_bytecode.h.
But apart from that:
James Bottomley
maintainerPATCH v14 2/5 oid_registry: Add TCG defined OIDS for TPM keys
In reply to James BottomleyThe TCG has defined an OID prefix "2.23.133.10.1" for the various TPM key uses. We've defined three of the available numbers:
2.23.133.10.1.3 TPM Loadable key. This is an asymmetric key (Usually
RSA2048 or Elliptic Curve) which can be imported by a TPM2_Load() operation.
2.23.133.10.1.4 TPM Importable Key. This is an asymmetric key (Usually
RSA2048 or Elliptic Curve) which can be imported by a TPM2_Import() operation.
Both loadable and importable keys are specific to a given TPM, the difference is that a loadable key is wrapped with the symmetric secret, so must have been created by the TPM itself. An importable key is wrapped with a DH shared secret, and may be created without access to the TPM provided you know the public part of the parent key.
2.23.133.10.1.5 TPM Sealed Data. This is a set of data (up to 128
bytes) which is sealed by the TPM. It usually represents a symmetric key and must be unsealed before use.
The ASN.1 binary key form starts of with this OID as the first element of a sequence, giving the binary form a unique recognizable identity marker regardless of encoding.
---
v3: correct OID_TPMImportableKey name
v7: add ack
v9: add review
--- include/linux/oid_registry.h | 5 +++++ 1 file changed, 5 insertions(+)
include/linux/oid_registry.h +5 -0
@@ -113,6 +113,11 @@ enum OID { OID_SM2_with_SM3,/* 1.2.156.10197.1.501 */ OID_sm3WithRSAEncryption,/* 1.2.156.10197.1.504 */ +/* TCG defined OIDS for TPM based keys */ + OID_TPMLoadableKey,/* 2.23.133.10.1.3 */ + OID_TPMImportableKey,/* 2.23.133.10.1.4 */ + OID_TPMSealedData,/* 2.23.133.10.1.5 */ + OID__NR };
Signature · 1 line
2.26.2
David Howells
maintainerRe: [PATCH v14 2/5] oid_registry: Add TCG defined OIDS for TPM keys
Quoted 2 lines · James Bottomley
The TCG has defined an OID prefix "2.23.133.10.1" for the various TPM key uses.
Is this registered? I've checked a couple of OID registry sites (eg. www.oid-info.com) and it seems to be unknown.
David
James Bottomley
maintainerRe: [PATCH v14 2/5] oid_registry: Add TCG defined OIDS for TPM keys
Quoted 7 lines · David Howells
Quoted 2 lines · James Bottomley
The TCG has defined an OID prefix "2.23.133.10.1" for the various TPM key uses.
Is this registered? I've checked a couple of OID registry sites (eg. www.oid-info.com) and it seems to be unknown.
Yes, TCG owns 2.23.133, although I still don't think Monty has published it yet:
James
James Bottomley
maintainerPATCH v14 3/5 security: keys: trusted: fix TPM2 authorizations
In reply to James BottomleyIn TPM 1.2 an authorization was a 20 byte number. The spec actually recommended you to hash variable length passwords and use the sha1 hash as the authorization. Because the spec doesn't require this hashing, the current authorization for trusted keys is a 40 digit hex number. For TPM 2.0 the spec allows the passing in of variable length passwords and passphrases directly, so we should allow that in trusted keys for ease of use. Update the 'blobauth' parameter to take this into account, so we can now use plain text passwords for the keys.
so before
keyctl add trusted kmk "new 32 blobauth=f572d396fae9206628714fb2ce00f72e94f2258fkeyhandle=81000001" @u
after we will accept both the old hex sha1 form as well as a new directly supplied password:
keyctl add trusted kmk "new 32 blobauth=hello keyhandle=81000001" @u
Since a sha1 hex code must be exactly 40 bytes long and a direct password must be 20 or less, we use the length as the discriminator for which form is input.
Note this is both and enhancement and a potential bug fix. The TPM 2.0 spec requires us to strip leading zeros, meaning empyty authorization is a zero length HMAC whereas we're currently passing in 20 bytes of zeros. A lot of TPMs simply accept this as OK, but the Microsoft TPM emulator rejects it with TPM_RC_BAD_AUTH, so this patch makes the Microsoft TPM emulator work with trusted keys.
---
v6: change comment, eliminate else clauses and add fixes tag
v7: fixes before signoff
v12: fix mismerge from v6 to make processing continue after blobauth
v14: add tested by
Merge with auth fix
--- include/keys/trusted-type.h | 1 + security/keys/trusted-keys/trusted_tpm1.c | 32 ++++++++++++++++++----- security/keys/trusted-keys/trusted_tpm2.c | 10 ++++--- 3 files changed, 33 insertions(+), 10 deletions(-)
include/keys/trusted-type.h +1 -0
@@ -30,6 +30,7 @@ struct trusted_key_options {uint16_t keytype;uint32_t keyhandle;unsigned char keyauth[TPM_DIGEST_SIZE ]; +uint32_t blobauth_len;unsigned char blobauth[TPM_DIGEST_SIZE ];uint32_t pcrinfo_len;unsigned char pcrinfo[MAX_PCRINFO_SIZE ];
security/keys/trusted-keys/trusted_tpm1.c +26 -6
@@ -781,13 +781,33 @@ static int getoptions(char *c, struct trusted_key_payload *pay,return -EINVAL ;break ;case Opt_blobauth: -if (strlen (args[0 ].from) !=2 *SHA1_DIGEST_SIZE ) -return -EINVAL ; - res =hex2bin (opt->blobauth, args[0 ].from, -SHA1_DIGEST_SIZE ); -if (res <0 ) -return -EINVAL ; +/* +* TPM 1.2 authorizations are sha1 hashes passed in as +* hex strings. TPM 2.0 authorizations are simple +* passwords (although it can take a hash as well) +*/ + opt->blobauth_len =strlen (args[0 ].from); + +if (opt->blobauth_len ==2 *TPM_DIGEST_SIZE ) { + res =hex2bin (opt->blobauth, args[0 ].from, +TPM_DIGEST_SIZE ); +if (res <0 ) +return -EINVAL ; + + opt->blobauth_len =TPM_DIGEST_SIZE ; +break ; + } + +if (tpm2 && opt->blobauth_len <=sizeof (opt->blobauth)) { +memcpy (opt->blobauth, args[0 ].from, + opt->blobauth_len); +break ; + } + +return -EINVAL ; +break ; +case Opt_migratable:if (*args[0 ].from =='0' ) pay->migratable =0 ;
security/keys/trusted-keys/trusted_tpm2.c +6 -4
@@ -91,10 +91,12 @@ int tpm2_seal_trusted(struct tpm_chip *chip, TPM_DIGEST_SIZE);/* sensitive */ -tpm_buf_append_u16 (&buf,4 +TPM_DIGEST_SIZE + payload->key_len +1 ); +tpm_buf_append_u16 (&buf,4 + options->blobauth_len + payload->key_len +1 ); + +tpm_buf_append_u16 (&buf, options->blobauth_len); +if (options->blobauth_len) +tpm_buf_append (&buf, options->blobauth, options->blobauth_len); -tpm_buf_append_u16 (&buf,TPM_DIGEST_SIZE ); -tpm_buf_append (&buf, options->blobauth,TPM_DIGEST_SIZE );tpm_buf_append_u16 (&buf, payload->key_len +1 );tpm_buf_append (&buf, payload->key, payload->key_len);tpm_buf_append_u8 (&buf, payload->migratable);
@@ -258,7 +260,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,NULL /* nonce */ ,0 ,TPM2_SA_CONTINUE_SESSION , options->blobauth/* hmac */ , - TPM_DIGEST_SIZE); + options->blobauth_len); rc =tpm_send (chip, buf.data,tpm_buf_length (&buf));if (rc >0 )
Signature · 1 line
2.26.2
Re: [PATCH v14 3/5] security: keys: trusted: fix TPM2 authorizations
Quoted 7 lines · James Bottomley
Note this is both and enhancement and a potential bug fix. The TPM 2.0 spec requires us to strip leading zeros, meaning empyty authorization is a zero length HMAC whereas we're currently passing in 20 bytes of zeros. A lot of TPMs simply accept this as OK, but the Microsoft TPM emulator rejects it with
TPM_RC_BAD_AUTH, so this patch makes the Microsoft TPM emulator work with trusted keys.
1 - To be precise, it strips trailing zeros, but 20 bytes of zero results in an empty buffer either way.
"
Part 1 19.6.4.3 Authorization Size Convention
Trailing octets of zero are to be removed from any string before it is used as an authValue. "
2 - If you have a test case for the MS simulator, post it and I'll give it a try.
I did a quick test, power cycle to set platform auth to empty, than create primary with a parent password 20 bytes of zero, and the SW TPM accepted it.
This was a password session, not an HMAC session.
James Bottomley
maintainerRe: [PATCH v14 3/5] security: keys: trusted: fix TPM2 authorizations
Quoted 19 lines · Ken Goldman
Quoted 6 lines · James Bottomley
Note this is both and enhancement and a potential bug fix. The TPM 2.0 spec requires us to strip leading zeros, meaning empyty authorization is a zero length HMAC whereas we're currently passing in 20 bytes of zeros. A lot of TPMs simply accept this as OK, but the Microsoft TPM emulator rejects it with
TPM_RC_BAD_AUTH, so this patch makes the Microsoft TPM emulator work with trusted keys.1 - To be precise, it strips trailing zeros, but 20 bytes of zero results in an empty buffer either way.
"
Part 1 19.6.4.3 Authorization Size ConventionTrailing octets of zero are to be removed from any string before it is used as an authValue.
"
Quoted 8 lines
2 - If you have a test case for the MS simulator, post it and I'll give it a try.
I did a quick test, power cycle to set platform auth to empty, than create primary with a parent password 20 bytes of zero, and the SW TPM accepted it.
This was a password session, not an HMAC session.
I reported it to Microsoft as soon as I found the problem, so, since this patch set has been languishing for years, I'd hope it would be fixed by now. It is still, however, possible there still exist TPM implementations based on the unfixed Microsoft reference platform.
James
Re: [PATCH v14 3/5] security: keys: trusted: fix TPM2 authorizations
Quoted 27 lines · James Bottomley
Quoted 26 lines · Ken Goldman
Quoted 6 lines · James Bottomley
Note this is both and enhancement and a potential bug fix. The TPM 2.0 spec requires us to strip leading zeros, meaning empyty authorization is a zero length HMAC whereas we're currently passing in 20 bytes of zeros. A lot of TPMs simply accept this as OK, but the Microsoft TPM emulator rejects it with
TPM_RC_BAD_AUTH, so this patch makes the Microsoft TPM emulator work with trusted keys.1 - To be precise, it strips trailing zeros, but 20 bytes of zero results in an empty buffer either way.
"
Part 1 19.6.4.3 Authorization Size ConventionTrailing octets of zero are to be removed from any string before it is used as an authValue.
"2 - If you have a test case for the MS simulator, post it and I'll give it a try.
I did a quick test, power cycle to set platform auth to empty, than create primary with a parent password 20 bytes of zero, and the SW TPM accepted it.
Quoted 8 lines
Quoted 1 line
This was a password session, not an HMAC session.
I reported it to Microsoft as soon as I found the problem, so, since this patch set has been languishing for years, I'd hope it would be fixed by now. It is still, however, possible there still exist TPM implementations based on the unfixed Microsoft reference platform.
James
One year :-) A bit over but by all practical means... [*]
BTW, can you use my kernel org address for v15?
[*] https://lore.kernel.org/linux-integrity/[email protected]/
/Jarkko
James Bottomley
maintainerPATCH v14 4/5 security: keys: trusted: use ASN.1 TPM2 key format for the blobs
In reply to James BottomleyModify the TPM2 key format blob output to export and import in the ASN.1 form for TPM2 sealed object keys. For compatibility with prior trusted keys, the importer will also accept two TPM2B quantities representing the public and private parts of the key. However, the export via keyctl pipe will only output the ASN.1 format.
The benefit of the ASN.1 format is that it's a standard and thus the exported key can be used by userspace tools (openssl_tpm2_engine, openconnect and tpm2-tss-engine). The format includes policy specifications, thus it gets us out of having to construct policy handles in userspace and the format includes the parent meaning you don't have to keep passing it in each time.
This patch only implements basic handling for the ASN.1 format, so keys with passwords but no policy.
---
v2: Updated encode API, added length checks
v5: correct export format after doing interoperability checks
v7: use prefix tpm2_key_ instead of tpmkey_ for functions
v8: resplit commit
v9: select ASN1_ENCODER
v11: add ASN.1 format description
v13: fix ASN.1 compiler dependency
v14: select OID_REGISTRY add tested by
--- .../security/keys/trusted-encrypted.rst | 58 +++++ include/keys/trusted-type.h | 1 + security/keys/Kconfig | 3 + security/keys/trusted-keys/Makefile | 4 +- security/keys/trusted-keys/tpm2key.asn1 | 11 + security/keys/trusted-keys/trusted_tpm1.c | 2 +- security/keys/trusted-keys/trusted_tpm2.c | 207 +++++++++++++++++- 7 files changed, 278 insertions(+), 8 deletions(-) create mode 100644 security/keys/trusted-keys/tpm2key.asn1
Documentation/security/keys/trusted-encrypted.rst +58 -0
@@ -207,3 +207,61 @@ about the usage can be found in the file Another new format 'enc32' has been defined in order to support encrypted keys with payload size of 32 bytes. This will initially be used for nvdimm security but may expand to other usages that require 32 bytes payload. + + +TPM 2.0 ASN.1 Key Format +------------------------ + +The TPM 2.0 ASN.1 key format is designed to be easily recognisable, +even in binary form (fixing a problem we had with the TPM 1.2 ASN.1 +format) and to be extensible for additions like importable keys and +policy:: + + TPMKey ::= SEQUENCE { + type OBJECT IDENTIFIER + emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL + parent INTEGER + pubkey OCTET STRING + privkey OCTET STRING + } + +type is what distinguishes the key even in binary form since the OID +is provided by the TCG to be unique and thus forms a recognizable +binary pattern at offset 3 in the key. The OIDs currently made +available are:: + + 2.23.133.10.1.3 TPM Loadable key. This is an asymmetric key (Usually + RSA2048 or Elliptic Curve) which can be imported by a + TPM2_Load() operation. + + 2.23.133.10.1.4 TPM Importable Key. This is an asymmetric key (Usually + RSA2048 or Elliptic Curve) which can be imported by a + TPM2_Import() operation. + + 2.23.133.10.1.5 TPM Sealed Data. This is a set of data (up to 128 + bytes) which is sealed by the TPM. It usually + represents a symmetric key and must be unsealed before + use. + +The trusted key code only uses the TPM Sealed Data OID. + +emptyAuth is true if the key has well known authorization "". If it +is false or not present, the key requires an explicit authorization +phrase. This is used by most user space consumers to decide whether +to prompt for a password. + +parent represents the parent key handle, either in the 0x81 MSO space, +like 0x81000001 for the RSA primary storage key. Userspace programmes +also support specifying the primary handle in the 0x40 MSO space. If +this happens the Elliptic Curve variant of the primary key using the +TCG defined template will be generated on the fly into a volatile +object and used as the parent. The current kernel code only supports +the 0x81 MSO form. + +pubkey is the binary representation of TPM2B_PRIVATE excluding the +initial TPM2B header, which can be reconstructed from the ASN.1 octet +string length. + +privkey is the binary representation of TPM2B_PUBLIC excluding the +initial TPM2B header which can be reconstructed from the ASN.1 octed +string length.
include/keys/trusted-type.h +1 -0
@@ -22,6 +22,7 @@ struct trusted_key_payload {unsigned int key_len;unsigned int blob_len;unsigned char migratable; +unsigned char old_format;unsigned char key[MAX_KEY_SIZE +1 ];unsigned char blob[MAX_BLOB_SIZE ]; };
security/keys/Kconfig +3 -0
@@ -75,6 +75,9 @@ config TRUSTED_KEYS select CRYPTO_HMAC select CRYPTO_SHA1 select CRYPTO_HASH_INFO + select ASN1_ENCODER + select OID_REGISTRY + select ASN1 help This option provides support for creating, sealing, and unsealing keys in the kernel. Trusted keys are random number symmetric keys,
security/keys/trusted-keys/Makefile +3 -1
@@ -5,4 +5,6 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o trusted-y += trusted_tpm1.o -trusted-y += trusted_tpm2.o + +$(obj)/trusted_tpm2.o: $(obj)/tpm2key.asn1.h +trusted-y += trusted_tpm2.o tpm2key.asn1.o
security/keys/trusted-keys/tpm2key.asn1 new file +11 -0
@@ -0,0 +1,11 @@ +--- +--- ASN.1 for for TPM 2.0 keys +--- + +TPMKey ::= SEQUENCE { + type OBJECT IDENTIFIER ({tpm2_key_type}), + emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL, + parent INTEGER ({tpm2_key_parent}), + pubkey OCTET STRING ({tpm2_key_pub}), + privkey OCTET STRING ({tpm2_key_priv}) + }
security/keys/trusted-keys/trusted_tpm1.c +1 -1
@@ -1011,7 +1011,7 @@ static int trusted_instantiate(struct key *key, goto out; } -if (!options->keyhandle) { +if (!options->keyhandle && !tpm2) { ret = -EINVAL ; goto out; }
security/keys/trusted-keys/trusted_tpm2.c +201 -6
265 lines not on this page · raw message
Signature · 1 line
2.26.2
kernel test robot
build botRe: [PATCH v14 4/5] security: keys: trusted: use ASN.1 TPM2 key format for the blobs
I love your patch! Perhaps something to improve:
Hi James,
I love your patch! Perhaps something to improve:
[auto build test WARNING on integrity/next-integrity]
[also build test WARNING on linus/master v5.10-rc5 next-20201127] [cannot apply to security/next-testing dhowells-fs/fscache-next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/James-Bottomley/TPM-2-0-trusted-key-rework/20201130-063029 base: https://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git next-integrity config: x86_64-randconfig-m001-20201130 (attached as .config) compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
If you fix the issue, kindly add following tag as appropriate
smatch warnings:security/keys/trusted-keys/trusted_tpm2.c:331 tpm2_seal_trusted() warn: unsigned 'payload->blob_len' is never less than zero.
vim +331 security/keys/trusted-keys/trusted_tpm2.c
217
218 /**
219 * tpm2_seal_trusted() - seal the payload of a trusted key
220 *
221 * @chip: TPM chip to use
222 * @payload: the key data in clear and encrypted form
223 * @options: authentication values and other options
224 *
225 * Return: < 0 on error and 0 on success.
226 */
227 int tpm2_seal_trusted(struct tpm_chip *chip,
228 struct trusted_key_payload *payload,
229 struct trusted_key_options *options)
230 {
231 unsigned int blob_len;
232 struct tpm_buf buf;
233 u32 hash;
234 int i;
235 int rc;
236
237 for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
238 if (options->hash == tpm2_hash_map[i].crypto_id) {
239 hash = tpm2_hash_map[i].tpm_id;
240 break;
241 }
242 }
243
244 if (i == ARRAY_SIZE(tpm2_hash_map))
245 return -EINVAL;
246
247 if (!options->keyhandle)
248 return -EINVAL;
249
250 rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
251 if (rc)
252 return rc;
253
254 tpm_buf_append_u32(&buf, options->keyhandle);
255 tpm2_buf_append_auth(&buf, TPM2_RS_PW,
256 NULL /* nonce */, 0,
257 0 /* session_attributes */,
258 options->keyauth /* hmac */,
259 TPM_DIGEST_SIZE);
260
261 /* sensitive */
262 tpm_buf_append_u16(&buf, 4 + options->blobauth_len + payload->key_len + 1);
263
264 tpm_buf_append_u16(&buf, options->blobauth_len);
265 if (options->blobauth_len)
266 tpm_buf_append(&buf, options->blobauth, options->blobauth_len);
267
268 tpm_buf_append_u16(&buf, payload->key_len + 1);
269 tpm_buf_append(&buf, payload->key, payload->key_len);
270 tpm_buf_append_u8(&buf, payload->migratable);
271
272 /* public */
273 tpm_buf_append_u16(&buf, 14 + options->policydigest_len);
274 tpm_buf_append_u16(&buf, TPM_ALG_KEYEDHASH);
275 tpm_buf_append_u16(&buf, hash);
276
277 /* policy */
278 if (options->policydigest_len) {
279 tpm_buf_append_u32(&buf, 0);
280 tpm_buf_append_u16(&buf, options->policydigest_len);
281 tpm_buf_append(&buf, options->policydigest,
282 options->policydigest_len);
283 } else {
284 tpm_buf_append_u32(&buf, TPM2_OA_USER_WITH_AUTH);
285 tpm_buf_append_u16(&buf, 0);
286 }
287
288 /* public parameters */
289 tpm_buf_append_u16(&buf, TPM_ALG_NULL);
290 tpm_buf_append_u16(&buf, 0);
291
292 /* outside info */
293 tpm_buf_append_u16(&buf, 0);
294
295 /* creation PCR */
296 tpm_buf_append_u32(&buf, 0);
297
298 if (buf.flags & TPM_BUF_OVERFLOW) {
299 rc = -E2BIG;
300 goto out;
301 }
302
303 rc = tpm_send(chip, buf.data, tpm_buf_length(&buf));
304 if (rc)
305 goto out;
306
307 blob_len = be32_to_cpup((__be32 *) &buf.data[TPM_HEADER_SIZE]);
308 if (blob_len > MAX_BLOB_SIZE) {
309 rc = -E2BIG;
310 goto out;
311 }
312 if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 4 + blob_len) {
313 rc = -EFAULT;
314 goto out;
315 }
316
317 payload->blob_len =
318 tpm2_key_encode(payload, options,
319 &buf.data[TPM_HEADER_SIZE + 4],
320 blob_len);
321
322 out:
323 tpm_buf_destroy(&buf);
324
325 if (rc > 0) {
326 if (tpm2_rc_value(rc) == TPM2_RC_HASH)
327 rc = -EINVAL;
328 else
329 rc = -EPERM;
330 }
> 331 if (payload->blob_len < 0) 332 return payload->blob_len;
333
334 return rc;
335 }
336
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
James Bottomley
maintainerRe: [PATCH v14 4/5] security: keys: trusted: use ASN.1 TPM2 key format for the blobs
On Mon, 2020-11-30 at 10:10 +0800, kernel test robot wrote:
[...]
Quoted 2 lines
Quoted 1 line
331 if (
payload->blob_len< 0)332 return
payload->blob_len;
OK, I can rework this to use the signed version of blob len as below.
James
---
security/keys/trusted-keys/trusted_tpm2.c +8 -7
@@ -242,7 +242,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,struct trusted_key_payload *payload, struct trusted_key_options *options) { - unsigned int blob_len; + int blob_len = 0;struct tpm_buf buf;u32 hash;u32 flags;
@@ -400,10 +400,9 @@ int tpm2_seal_trusted(struct tpm_chip *chip, goto out; } - payload->blob_len = -tpm2_key_encode (payload, options, - &buf.data[TPM_HEADER_SIZE +4 ], - blob_len); + blob_len =tpm2_key_encode (payload, options, + &buf.data[TPM_HEADER_SIZE +4 ], + blob_len); out:tpm_buf_destroy (&buf);
@@ -414,8 +413,10 @@ int tpm2_seal_trusted(struct tpm_chip *chip,else rc = -EPERM ; } -if (payload->blob_len <0 ) -return payload->blob_len; +if (blob_len <0 ) +return blob_len; + + payload->blob_len = blob_len;return rc; }
Re: [PATCH v14 4/5] security: keys: trusted: use ASN.1 TPM2 key format for the blobs
Quoted 8 lines · James Bottomley
On Mon, 2020-11-30 at 10:10 +0800, kernel test robot wrote:
[...]Quoted 2 lines
Quoted 1 line
331 if (
payload->blob_len< 0)332 return
payload->blob_len;OK, I can rework this to use the signed version of blob len as below.
James
Do you have the patches in a git branch somewhere with this fixed?
I can take from there and apply.
/Jarkko
Re: [PATCH v14 4/5] security: keys: trusted: use ASN.1 TPM2 key format for the blobs
Quoted 6 lines · Jarkko Sakkinen
Quoted 5 lines · James Bottomley
On Mon, 2020-11-30 at 10:10 +0800, kernel test robot wrote:
[...]Quoted 2 lines
Quoted 1 line
331 if (
payload->blob_len< 0)332 return
payload->blob_len;
Quoted 7 lines
Quoted 3 lines
OK, I can rework this to use the signed version of blob len as below.
James
Do you have the patches in a git branch somewhere with this fixed?
I can take from there and apply.
CC my korg address. Sorry for the latency, I have this LKML migration going on (MAINTAINERS is already updated). Sometimes forgot to check this inbox.
/Jarkko
Re: [PATCH v14 4/5] security: keys: trusted: use ASN.1 TPM2 key format for the blobs
Quoted 12 lines · Jarkko Sakkinen
Quoted 11 lines · Jarkko Sakkinen
Quoted 9 lines · James Bottomley
On Mon, 2020-11-30 at 10:10 +0800, kernel test robot wrote:
[...]Quoted 2 lines
Quoted 1 line
331 if (
payload->blob_len< 0)332 return
payload->blob_len;OK, I can rework this to use the signed version of blob len as below.
James
Quoted 7 lines
Quoted 3 lines
Do you have the patches in a git branch somewhere with this fixed?
I can take from there and apply.
CC my korg address. Sorry for the latency, I have this LKML migration going on (
MAINTAINERSis already updated). Sometimes forgot to check this inbox.
I'm preparing a v15 but this is basically the only code change.
James
---8>8>8><8<8<8---
From: James Bottomley <[email protected]>
Subject: [PATCH] security: keys: trusted: use ASN.1 TPM2 key format for the
blobs
Modify the TPM2 key format blob output to export and import in the ASN.1 form for TPM2 sealed object keys. For compatibility with prior trusted keys, the importer will also accept two TPM2B quantities representing the public and private parts of the key. However, the export via keyctl pipe will only output the ASN.1 format.
The benefit of the ASN.1 format is that it's a standard and thus the exported key can be used by userspace tools (openssl_tpm2_engine, openconnect and tpm2-tss-engine). The format includes policy specifications, thus it gets us out of having to construct policy handles in userspace and the format includes the parent meaning you don't have to keep passing it in each time.
This patch only implements basic handling for the ASN.1 format, so keys with passwords but no policy.
---
v2: Updated encode API, added length checks
v5: correct export format after doing interoperability checks
v7: use prefix tpm2_key_ instead of tpmkey_ for functions
v8: resplit commit
v9: select ASN1_ENCODER
v11: add ASN.1 format description
v13: fix ASN.1 compiler dependency
v14: select OID_REGISTRY add tested by
v15: signed blob len
--- .../security/keys/trusted-encrypted.rst | 58 +++++ include/keys/trusted-type.h | 1 + security/keys/Kconfig | 3 + security/keys/trusted-keys/Makefile | 4 +- security/keys/trusted-keys/tpm2key.asn1 | 11 + security/keys/trusted-keys/trusted_tpm1.c | 2 +- security/keys/trusted-keys/trusted_tpm2.c | 210 +++++++++++++++++- 7 files changed, 280 insertions(+), 9 deletions(-) create mode 100644 security/keys/trusted-keys/tpm2key.asn1
Documentation/security/keys/trusted-encrypted.rst +58 -0
@@ -207,3 +207,61 @@ about the usage can be found in the file Another new format 'enc32' has been defined in order to support encrypted keys with payload size of 32 bytes. This will initially be used for nvdimm security but may expand to other usages that require 32 bytes payload. + + +TPM 2.0 ASN.1 Key Format +------------------------ + +The TPM 2.0 ASN.1 key format is designed to be easily recognisable, +even in binary form (fixing a problem we had with the TPM 1.2 ASN.1 +format) and to be extensible for additions like importable keys and +policy:: + + TPMKey ::= SEQUENCE { + type OBJECT IDENTIFIER + emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL + parent INTEGER + pubkey OCTET STRING + privkey OCTET STRING + } + +type is what distinguishes the key even in binary form since the OID +is provided by the TCG to be unique and thus forms a recognizable +binary pattern at offset 3 in the key. The OIDs currently made +available are:: + + 2.23.133.10.1.3 TPM Loadable key. This is an asymmetric key (Usually + RSA2048 or Elliptic Curve) which can be imported by a + TPM2_Load() operation. + + 2.23.133.10.1.4 TPM Importable Key. This is an asymmetric key (Usually + RSA2048 or Elliptic Curve) which can be imported by a + TPM2_Import() operation. + + 2.23.133.10.1.5 TPM Sealed Data. This is a set of data (up to 128 + bytes) which is sealed by the TPM. It usually + represents a symmetric key and must be unsealed before + use. + +The trusted key code only uses the TPM Sealed Data OID. + +emptyAuth is true if the key has well known authorization "". If it +is false or not present, the key requires an explicit authorization +phrase. This is used by most user space consumers to decide whether +to prompt for a password. + +parent represents the parent key handle, either in the 0x81 MSO space, +like 0x81000001 for the RSA primary storage key. Userspace programmes +also support specifying the primary handle in the 0x40 MSO space. If +this happens the Elliptic Curve variant of the primary key using the +TCG defined template will be generated on the fly into a volatile +object and used as the parent. The current kernel code only supports +the 0x81 MSO form. + +pubkey is the binary representation of TPM2B_PRIVATE excluding the +initial TPM2B header, which can be reconstructed from the ASN.1 octet +string length. + +privkey is the binary representation of TPM2B_PUBLIC excluding the +initial TPM2B header which can be reconstructed from the ASN.1 octed +string length.
include/keys/trusted-type.h +1 -0
@@ -22,6 +22,7 @@ struct trusted_key_payload {unsigned int key_len;unsigned int blob_len;unsigned char migratable; +unsigned char old_format;unsigned char key[MAX_KEY_SIZE +1 ];unsigned char blob[MAX_BLOB_SIZE ]; };
security/keys/Kconfig +3 -0
@@ -75,6 +75,9 @@ config TRUSTED_KEYS select CRYPTO_HMAC select CRYPTO_SHA1 select CRYPTO_HASH_INFO + select ASN1_ENCODER + select OID_REGISTRY + select ASN1 help This option provides support for creating, sealing, and unsealing keys in the kernel. Trusted keys are random number symmetric keys,
security/keys/trusted-keys/Makefile +3 -1
@@ -5,4 +5,6 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o trusted-y += trusted_tpm1.o -trusted-y += trusted_tpm2.o + +$(obj)/trusted_tpm2.o: $(obj)/tpm2key.asn1.h +trusted-y += trusted_tpm2.o tpm2key.asn1.o
security/keys/trusted-keys/tpm2key.asn1 new file +11 -0
@@ -0,0 +1,11 @@ +--- +--- ASN.1 for for TPM 2.0 keys +--- + +TPMKey ::= SEQUENCE { + type OBJECT IDENTIFIER ({tpm2_key_type}), + emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL, + parent INTEGER ({tpm2_key_parent}), + pubkey OCTET STRING ({tpm2_key_pub}), + privkey OCTET STRING ({tpm2_key_priv}) + }
security/keys/trusted-keys/trusted_tpm1.c +1 -1
@@ -1011,7 +1011,7 @@ static int trusted_instantiate(struct key *key, goto out; } -if (!options->keyhandle) { +if (!options->keyhandle && !tpm2) { ret = -EINVAL ; goto out; }
security/keys/trusted-keys/trusted_tpm2.c +203 -7
274 lines not on this page · raw message
Signature · 1 line
2.26.2
Re: [PATCH v14 4/5] security: keys: trusted: use ASN.1 TPM2 key format for the blobs
Quoted 17 lines · James Bottomley
Quoted 16 lines · Jarkko Sakkinen
Quoted 14 lines · Jarkko Sakkinen
Quoted 9 lines · James Bottomley
On Mon, 2020-11-30 at 10:10 +0800, kernel test robot wrote:
[...]Quoted 2 lines
Quoted 1 line
331 if (
payload->blob_len< 0)332 return
payload->blob_len;OK, I can rework this to use the signed version of blob len as below.
James
Do you have the patches in a git branch somewhere with this fixed?
I can take from there and apply.
Quoted 7 lines
Quoted 3 lines
CC my korg address. Sorry for the latency, I have this LKML migration going on (
MAINTAINERSis already updated). Sometimes forgot to check this inbox.I'm preparing a v15 but this is basically the only code change.
James
Please actually do. It's always nice to have a lore reference to the exact version that was merged.
/Jarkko
James Bottomley
maintainerPATCH v14 5/5 security: keys: trusted: Make sealed key properly interoperable
In reply to James BottomleyThe current implementation appends a migratable flag to the end of a key, meaning the format isn't exactly interoperable because the using party needs to know to strip this extra byte. However, all other consumers of TPM sealed blobs expect the unseal to return exactly the key. Since TPM2 keys have a key property flag that corresponds to migratable, use that flag instead and make the actual key the only sealed quantity. This is secure because the key properties are bound to a hash in the private part, so if they're altered the key won't load.
Backwards compatibility is implemented by detecting whether we're loading a new format key or not and correctly setting migratable from the last byte of old format keys.
---
v2: added length checks to untrusted payload
v8: recover patch
v14: add tested by
--- include/linux/tpm.h | 2 + security/keys/trusted-keys/trusted_tpm2.c | 53 ++++++++++++++++------- 2 files changed, 40 insertions(+), 15 deletions(-)
include/linux/tpm.h +2 -0
@@ -305,6 +305,8 @@ struct tpm_buf { };enum tpm2_object_attributes { +TPM2_OA_FIXED_TPM =BIT (1 ), +TPM2_OA_FIXED_PARENT =BIT (4 ),TPM2_OA_USER_WITH_AUTH =BIT (6 ), };
security/keys/trusted-keys/trusted_tpm2.c +38 -15
105 lines not on this page · raw message
Signature · 1 line
2.26.2