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

From: Zhao, Shirley
Date: Tue Dec 03 2019 - 22:01:58 EST


Hi, James,

Using policy digest to reload trusted key, doesn't work, either.
Please check the steps below.
I think policy digest should be calculated by TPM when verifying the policy to reload key.

/////// build policy
# tpm2_pcrlist -L sha256:7 -o pcr7.sha256
sha256:
7 : 0x061AAD0705A62361AD18E58B65D3D7383F4D10F7F5A7E78924BE057AC6797408
# tpm2_createpolicy --policy-pcr --pcr-list sha256:7 --policy pcr7_bin.policy > pcr7.policy
# cat pcr7.policy
321fbd28b60fcc23017d501b133bd5dbf2889814588e8a23510fe10105cb2cc9

/////// new trusted key and use policy to protect
# keyctl add trusted kmk "new 32 keyhandle=0x81000001 hash=sha256 policydigest=`cat pcr7.policy`" @u
466107578
# keyctl pipe 466107578 > kmk.blob
# keyctl print 466107578
007f0020a922ca764d3ae9feae4c3a1b140c610ad1df836df6d7054957f3f5da14042f290010d3ca83aca08ed10a433ba585a5147126d207f0c52e53a1edbfc31b89b30988053870553ef692c77c28b2c7adb63e1fc69869d7f2e8ab2b9d8906e02bd953dc58c3a5b1de0858ec38a6dcb551384f38d6834842fd22b4a9c61c0320004e0008000b000000000020321fbd28b60fcc23017d501b133bd5dbf2889814588e8a23510fe10105cb2cc9001000200280321810a66df63905d4846e39e6ad3ec69b77deac339f4209f291078483c10073000000000020e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85501000b0022000bdcdb694e102e13a0fba5111081cb6cf616c118d404936cac3e84db24c71e47d50022000b04b5db1aa52635dfb242e76f6bde8e2176ae48fc682946c6c76d96f608079d1f0000002036b6fcca8206c7f722de85821d7ecb4785976fdd642bc7538505a2a818c8a238802140000001002014b439da9b9490d9bb6e5a93e7e6ed408b1d51ae45abccd5d5dcc625d968282d
# cat kmk.blob
007f0020a922ca764d3ae9feae4c3a1b140c610ad1df836df6d7054957f3f5da14042f290010d3ca83aca08ed10a433ba585a5147126d207f0c52e53a1edbfc31b89b30988053870553ef692c77c28b2c7adb63e1fc69869d7f2e8ab2b9d8906e02bd953dc58c3a5b1de0858ec38a6dcb551384f38d6834842fd22b4a9c61c0320004e0008000b000000000020321fbd28b60fcc23017d501b133bd5dbf2889814588e8a23510fe10105cb2cc9001000200280321810a66df63905d4846e39e6ad3ec69b77deac339f4209f291078483c10073000000000020e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85501000b0022000bdcdb694e102e13a0fba5111081cb6cf616c118d404936cac3e84db24c71e47d50022000b04b5db1aa52635dfb242e76f6bde8e2176ae48fc682946c6c76d96f608079d1f0000002036b6fcca8206c7f722de85821d7ecb4785976fdd642bc7538505a2a818c8a238802140000001002014b439da9b9490d9bb6e5a93e7e6ed408b1d51ae45abccd5d5dcc625d968282d

//////////clear trusted key and reload
# keyctl clear @u
keyctl list @u
keyring is empty
# keyctl add trusted kmk "load `cat kmk.blob` keyhandle=0x81000001 hash=sha256 policydigest=`cat pcr7.policy`" @u
add_key: Operation not permitted


Thanks.

- Shirley

-----Original Message-----
From: James Bottomley <jejb@xxxxxxxxxxxxx>
Sent: Tuesday, December 3, 2019 11:12 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 Tue, 2019-12-03 at 02:11 +0000, Zhao, Shirley wrote:
> 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/Docu
> mentation/security/keys/trusted-encrypted.rst and
> https://github.com/zfsonlinux/dracut/tree/master/modules.d/97masterke
> y, the trusted key is a random number and generated by TPM2.0 and
> sealed with TPM2.0 2048 RSA key.

Well, um, that document seems to be based on TPM 1.2 ... a lot of what it says isn't quite true for TPM 2.0. For instance all TPM 2.0 primary keys come with a symmetric component, so the sealed data in TPM 2.0 is actually symmetrically encrypted to a primary 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

The problem TPM 2.0 has is that most of them can't generate prime numbers very fast, so even through the kernel could generate the RSA primary, it would usually take far too long, so if you want to use a RSA primary you have to pre-generate one and place it in NV storage; the TCG recommends doing this at handle 81000001, which is what you have above. However, the more modern way is to derive an elliptic curve key primary key every time ... EC keys can be generated by most TPMs in 10s of milliseconds, so the primary doesn't need to be present in NVRAM.

THe kernel should be using the EC primary method for the parent. The only exception is when the key has an intermediate parent, and then it can be simply loaded from a file.

> 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().

Well, the API is confusing, but the code seems to imply the parent should be present somehow. A key in NVRAM, like 81000001 is always present so it doesn't need to be loaded it can just be used as is.

> 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

As I said, using policy handles simply won't scale, so we need to use the actual policy instead ... thus the policy should be passed into the kernel as part of the trusted key and the kernel itself would generate a policy session from the policy statements ... this approach is aready proven to be useful and functional in the tpm2 openssl engine code.

James