Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5beb0c43 authored by Jarkko Sakkinen's avatar Jarkko Sakkinen
Browse files

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: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: default avatarColin Ian King <colin.king@canonical.com>
Reviewed-by: default avatarMimi Zohar <zohar@linux.vnet.ibm.com>
Acked-by: default avatarPeter Huewe <peterhuewe@gmx.de>
parent 5ca4c20c
Loading
Loading
Loading
Loading
+20 −14
Original line number Diff line number Diff line
@@ -41,6 +41,12 @@ Usage:
       hash=         hash algorithm name as a string. For TPM 1.x the only
                     allowed value is sha1. For TPM 2.x the allowed values
                     are sha1, sha256, sha384, sha512 and sm3-256.
       policydigest= digest for the authorization policy. must be calculated
                     with the same hash algorithm as specified by the 'hash='
                     option.
       policyhandle= handle to an authorization policy session that defines the
                     same policy and with the same hash algorithm as was used to
                     seal the key.

"keyctl print" returns an ascii hex copy of the sealed key, which is in standard
TPM_STORED_DATA format.  The key length for new keys are always in bytes.
+20 −4
Original line number Diff line number Diff line
@@ -478,12 +478,26 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
	tpm_buf_append_u8(&buf, payload->migratable);

	/* public */
	if (options->policydigest)
		tpm_buf_append_u16(&buf, 14 + options->digest_len);
	else
		tpm_buf_append_u16(&buf, 14);

	tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
	tpm_buf_append_u16(&buf, hash);

	/* policy */
	if (options->policydigest) {
		tpm_buf_append_u32(&buf, 0);
		tpm_buf_append_u16(&buf, options->digest_len);
		tpm_buf_append(&buf, options->policydigest,
			       options->digest_len);
	} else {
		tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
	tpm_buf_append_u16(&buf, 0); /* policy digest size */
		tpm_buf_append_u16(&buf, 0);
	}

	/* public parameters */
	tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
	tpm_buf_append_u16(&buf, 0);

@@ -613,7 +627,9 @@ static int tpm2_unseal(struct tpm_chip *chip,
		return rc;

	tpm_buf_append_u32(&buf, blob_handle);
	tpm2_buf_append_auth(&buf, TPM2_RS_PW,
	tpm2_buf_append_auth(&buf,
			     options->policyhandle ?
			     options->policyhandle : TPM2_RS_PW,
			     NULL /* nonce */, 0,
			     0 /* session_attributes */,
			     options->blobauth /* hmac */,
+4 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define MAX_KEY_SIZE			128
#define MAX_BLOB_SIZE			512
#define MAX_PCRINFO_SIZE		64
#define MAX_DIGEST_SIZE			64

struct trusted_key_payload {
	struct rcu_head rcu;
@@ -37,6 +38,9 @@ struct trusted_key_options {
	unsigned char pcrinfo[MAX_PCRINFO_SIZE];
	int pcrlock;
	uint32_t hash;
	uint32_t digest_len;
	unsigned char policydigest[MAX_DIGEST_SIZE];
	uint32_t policyhandle;
};

extern struct key_type key_type_trusted;
+26 −0
Original line number Diff line number Diff line
@@ -713,6 +713,8 @@ enum {
	Opt_keyhandle, Opt_keyauth, Opt_blobauth,
	Opt_pcrinfo, Opt_pcrlock, Opt_migratable,
	Opt_hash,
	Opt_policydigest,
	Opt_policyhandle,
};

static const match_table_t key_tokens = {
@@ -726,6 +728,8 @@ static const match_table_t key_tokens = {
	{Opt_pcrlock, "pcrlock=%s"},
	{Opt_migratable, "migratable=%s"},
	{Opt_hash, "hash=%s"},
	{Opt_policydigest, "policydigest=%s"},
	{Opt_policyhandle, "policyhandle=%s"},
	{Opt_err, NULL}
};

@@ -748,6 +752,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
		return tpm2;

	opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
	opt->digest_len = hash_digest_size[opt->hash];

	while ((p = strsep(&c, " \t"))) {
		if (*p == '\0' || *p == ' ' || *p == '\t')
@@ -802,9 +807,13 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
			opt->pcrlock = lock;
			break;
		case Opt_hash:
			if (test_bit(Opt_policydigest, &token_mask))
				return -EINVAL;
			for (i = 0; i < HASH_ALGO__LAST; i++) {
				if (!strcmp(args[0].from, hash_algo_name[i])) {
					opt->hash = i;
					opt->digest_len =
						hash_digest_size[opt->hash];
					break;
				}
			}
@@ -815,6 +824,23 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
				return -EINVAL;
			}
			break;
		case Opt_policydigest:
			if (!tpm2 ||
			    strlen(args[0].from) != (2 * opt->digest_len))
				return -EINVAL;
			res = hex2bin(opt->policydigest, args[0].from,
				      opt->digest_len);
			if (res < 0)
				return -EINVAL;
			break;
		case Opt_policyhandle:
			if (!tpm2)
				return -EINVAL;
			res = kstrtoul(args[0].from, 16, &handle);
			if (res < 0)
				return -EINVAL;
			opt->policyhandle = handle;
			break;
		default:
			return -EINVAL;
		}