Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

keys, trusted: seal with a TPM2 authorization policy

TPM2 supports authorization policies, which are essentially
combinational logic statements repsenting the conditions where the data
can be unsealed based on the TPM state. This patch enables to use
authorization policies to seal trusted keys.

Two following new options have been added for trusted keys:

* 'policydigest=': provide an auth policy digest for sealing.
* 'policyhandle=': provide a policy session handle for unsealing.

If 'hash=' option is supplied after 'policydigest=' option, this
will result an error because the state of the option would become
mixed.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: Colin Ian King <colin.king@canonical.com>
Reviewed-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Acked-by: Peter Huewe <peterhuewe@gmx.de>

+70 -18
+20 -14
Documentation/security/keys-trusted-encrypted.txt
··· 27 27 keyctl print keyid 28 28 29 29 options: 30 - keyhandle= ascii hex value of sealing key default 0x40000000 (SRK) 31 - keyauth= ascii hex auth for sealing key default 0x00...i 32 - (40 ascii zeros) 33 - blobauth= ascii hex auth for sealed data default 0x00... 34 - (40 ascii zeros) 35 - blobauth= ascii hex auth for sealed data default 0x00... 36 - (40 ascii zeros) 37 - pcrinfo= ascii hex of PCR_INFO or PCR_INFO_LONG (no default) 38 - pcrlock= pcr number to be extended to "lock" blob 39 - migratable= 0|1 indicating permission to reseal to new PCR values, 40 - default 1 (resealing allowed) 41 - hash= hash algorithm name as a string. For TPM 1.x the only 42 - allowed value is sha1. For TPM 2.x the allowed values 43 - are sha1, sha256, sha384, sha512 and sm3-256. 30 + keyhandle= ascii hex value of sealing key default 0x40000000 (SRK) 31 + keyauth= ascii hex auth for sealing key default 0x00...i 32 + (40 ascii zeros) 33 + blobauth= ascii hex auth for sealed data default 0x00... 34 + (40 ascii zeros) 35 + blobauth= ascii hex auth for sealed data default 0x00... 36 + (40 ascii zeros) 37 + pcrinfo= ascii hex of PCR_INFO or PCR_INFO_LONG (no default) 38 + pcrlock= pcr number to be extended to "lock" blob 39 + migratable= 0|1 indicating permission to reseal to new PCR values, 40 + default 1 (resealing allowed) 41 + hash= hash algorithm name as a string. For TPM 1.x the only 42 + allowed value is sha1. For TPM 2.x the allowed values 43 + are sha1, sha256, sha384, sha512 and sm3-256. 44 + policydigest= digest for the authorization policy. must be calculated 45 + with the same hash algorithm as specified by the 'hash=' 46 + option. 47 + policyhandle= handle to an authorization policy session that defines the 48 + same policy and with the same hash algorithm as was used to 49 + seal the key. 44 50 45 51 "keyctl print" returns an ascii hex copy of the sealed key, which is in standard 46 52 TPM_STORED_DATA format. The key length for new keys are always in bytes.
+20 -4
drivers/char/tpm/tpm2-cmd.c
··· 478 478 tpm_buf_append_u8(&buf, payload->migratable); 479 479 480 480 /* public */ 481 - tpm_buf_append_u16(&buf, 14); 481 + if (options->policydigest) 482 + tpm_buf_append_u16(&buf, 14 + options->digest_len); 483 + else 484 + tpm_buf_append_u16(&buf, 14); 482 485 483 486 tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH); 484 487 tpm_buf_append_u16(&buf, hash); 485 - tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH); 486 - tpm_buf_append_u16(&buf, 0); /* policy digest size */ 488 + 489 + /* policy */ 490 + if (options->policydigest) { 491 + tpm_buf_append_u32(&buf, 0); 492 + tpm_buf_append_u16(&buf, options->digest_len); 493 + tpm_buf_append(&buf, options->policydigest, 494 + options->digest_len); 495 + } else { 496 + tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH); 497 + tpm_buf_append_u16(&buf, 0); 498 + } 499 + 500 + /* public parameters */ 487 501 tpm_buf_append_u16(&buf, TPM2_ALG_NULL); 488 502 tpm_buf_append_u16(&buf, 0); 489 503 ··· 627 613 return rc; 628 614 629 615 tpm_buf_append_u32(&buf, blob_handle); 630 - tpm2_buf_append_auth(&buf, TPM2_RS_PW, 616 + tpm2_buf_append_auth(&buf, 617 + options->policyhandle ? 618 + options->policyhandle : TPM2_RS_PW, 631 619 NULL /* nonce */, 0, 632 620 0 /* session_attributes */, 633 621 options->blobauth /* hmac */,
+4
include/keys/trusted-type.h
··· 18 18 #define MAX_KEY_SIZE 128 19 19 #define MAX_BLOB_SIZE 512 20 20 #define MAX_PCRINFO_SIZE 64 21 + #define MAX_DIGEST_SIZE 64 21 22 22 23 struct trusted_key_payload { 23 24 struct rcu_head rcu; ··· 38 37 unsigned char pcrinfo[MAX_PCRINFO_SIZE]; 39 38 int pcrlock; 40 39 uint32_t hash; 40 + uint32_t digest_len; 41 + unsigned char policydigest[MAX_DIGEST_SIZE]; 42 + uint32_t policyhandle; 41 43 }; 42 44 43 45 extern struct key_type key_type_trusted;
+26
security/keys/trusted.c
··· 713 713 Opt_keyhandle, Opt_keyauth, Opt_blobauth, 714 714 Opt_pcrinfo, Opt_pcrlock, Opt_migratable, 715 715 Opt_hash, 716 + Opt_policydigest, 717 + Opt_policyhandle, 716 718 }; 717 719 718 720 static const match_table_t key_tokens = { ··· 728 726 {Opt_pcrlock, "pcrlock=%s"}, 729 727 {Opt_migratable, "migratable=%s"}, 730 728 {Opt_hash, "hash=%s"}, 729 + {Opt_policydigest, "policydigest=%s"}, 730 + {Opt_policyhandle, "policyhandle=%s"}, 731 731 {Opt_err, NULL} 732 732 }; 733 733 ··· 752 748 return tpm2; 753 749 754 750 opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1; 751 + opt->digest_len = hash_digest_size[opt->hash]; 755 752 756 753 while ((p = strsep(&c, " \t"))) { 757 754 if (*p == '\0' || *p == ' ' || *p == '\t') ··· 807 802 opt->pcrlock = lock; 808 803 break; 809 804 case Opt_hash: 805 + if (test_bit(Opt_policydigest, &token_mask)) 806 + return -EINVAL; 810 807 for (i = 0; i < HASH_ALGO__LAST; i++) { 811 808 if (!strcmp(args[0].from, hash_algo_name[i])) { 812 809 opt->hash = i; 810 + opt->digest_len = 811 + hash_digest_size[opt->hash]; 813 812 break; 814 813 } 815 814 } ··· 823 814 pr_info("trusted_key: TPM 1.x only supports SHA-1.\n"); 824 815 return -EINVAL; 825 816 } 817 + break; 818 + case Opt_policydigest: 819 + if (!tpm2 || 820 + strlen(args[0].from) != (2 * opt->digest_len)) 821 + return -EINVAL; 822 + res = hex2bin(opt->policydigest, args[0].from, 823 + opt->digest_len); 824 + if (res < 0) 825 + return -EINVAL; 826 + break; 827 + case Opt_policyhandle: 828 + if (!tpm2) 829 + return -EINVAL; 830 + res = kstrtoul(args[0].from, 16, &handle); 831 + if (res < 0) 832 + return -EINVAL; 833 + opt->policyhandle = handle; 826 834 break; 827 835 default: 828 836 return -EINVAL;