RE: One question about trusted key of keyring in Linux kernel.

From: Zhao, Shirley
Date: Mon Dec 02 2019 - 21:11:15 EST


Thanks so much for you feedback, James.
And glad to hear that the API will be made more friendly.

But I have a little confused about the call stack.
From the document, https://github.com/torvalds/linux/blob/master/Documentation/security/keys/trusted-encrypted.rst and
https://github.com/zfsonlinux/dracut/tree/master/modules.d/97masterkey, the trusted key is a random number and generated by TPM2.0 and sealed with TPM2.0 2048 RSA key.

The 2048 RSA key is generated by tpm2_createprimary, and it can be got by the TPM2.0 handle, just the "keyhandle" used in the following keyctl command.
$ keyctl add trusted kmk "new 32 keyhandle=0x81000001 hash=sha256 policydigest=`cat pcr7.policy`" @u

If reboot, to re-load the trusted key back to keyring, just call tpm2_unseal is enough, don't need to call tpm2_load to load the TPM2.0 2048 RSA key.
If the trusted key is also protected by policy, then the policy will be checked during tpm2_unseal.

After check the source code, the call stack is mostly like:
SYSCALL_DEFINE5(add_key,...) --> key_create_or_update() --> __key_instantiate_and_link() --> trusted_instantiate() --> tpm2_unseal_trusted() --> tpm2_unseal_cmd().

Another problem here is, to build the policy to unseal the key, it need to start an policy session, and transfer the session handle to TPM2.0 unseal command.
In my keyctl command, I use tpm2.0 command to start the session and get the handle, put it into the keyctl command like:
keyctl add trusted kmk "load `cat kmk.blob` keyhandle=0x81000001 policyhandle=0x3000000" @u

I am not sure whether it is correct.

Thanks.

- Shirley


-----Original Message-----
From: James Bottomley <jejb@xxxxxxxxxxxxx>
Sent: Tuesday, December 3, 2019 2:56 AM
To: Zhao, Shirley <shirley.zhao@xxxxxxxxx>; Mimi Zohar <zohar@xxxxxxxxxxxxx>; Jarkko Sakkinen <jarkko.sakkinen@xxxxxxxxxxxxxxx>; Jonathan Corbet <corbet@xxxxxxx>
Cc: linux-integrity@xxxxxxxxxxxxxxx; keyrings@xxxxxxxxxxxxxxx; linux-doc@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; 'Mauro Carvalho Chehab' <mchehab+samsung@xxxxxxxxxx>; Zhu, Bing <bing.zhu@xxxxxxxxx>; Chen, Luhai <luhai.chen@xxxxxxxxx>
Subject: Re: One question about trusted key of keyring in Linux kernel.

On Mon, 2019-12-02 at 06:50 +0000, Zhao, Shirley wrote:
> So I guess mostly like, it is the format of policydigest, policyhandle
> is not correctly in my keyctl command.
> But what is the correct using?
>
> My keyctl commands are attached as below:
> $ keyctl add trusted kmk "new 32 keyhandle=0x81000001 hash=sha256
> policydigest=`cat pcr7.policy`" @u
> 874117045
>
> Save the trusted key.
> $ keyctl pipe 874117045 > kmk.blob

OK, looking at the actual code, it seems that whoever wrote it didn't account for the differences between TPM1.2 and TPM2.0. With TPM2.0 TPM2_Create returns the public and private parts plus three other tpm2b entites used to certify and check the key. When you load the blob back using TPM2_Load, it only accepts the public and private parts.
However, your blob contains the other extraneous elements, that's why it can't be loaded. You could make it loadable by stripping off the extraneous pieces ... just take the first two tpm2b elements of the blob but it looks like we need to fix the API. I suppose the good news is given this failure that we have the opportunity to rewrite the API since no-one else can have used it for anything because of this. The fundamental problem with the current API is that most TPM2's only have three available session registers. It's simply not scalable to set them up in userspace and have the kernel use them, so what we should be doing is passing down the actual policy and having the kernel construct the session at the point of use and then flush it, thus solving the potential session exhaustion issue.

I'd actually propose we make a TSSLOADABLE the fundamental element of operation for trusted keys. The IBM and Intel TSS people have agreed to do this as the format for TPM loadable keys, but it should also apply to sealed data. The beauty of TSSLOADABLE is that the ASN.1 format includes a policy specification:

/*
* TSSLOADABLE ::= 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
* }
* TPMPolicy ::= SEQUENCE {
* CommandCode [0] EXPLICIT INTEGER
* CommandPolicy [1] EXPLICIT OCTET STRING
* }
*/

James