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

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
...@@ -41,6 +41,12 @@ Usage: ...@@ -41,6 +41,12 @@ Usage:
hash= hash algorithm name as a string. For TPM 1.x the only hash= hash algorithm name as a string. For TPM 1.x the only
allowed value is sha1. For TPM 2.x the allowed values allowed value is sha1. For TPM 2.x the allowed values
are sha1, sha256, sha384, sha512 and sm3-256. 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 "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. TPM_STORED_DATA format. The key length for new keys are always in bytes.
......
...@@ -478,12 +478,26 @@ int tpm2_seal_trusted(struct tpm_chip *chip, ...@@ -478,12 +478,26 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
tpm_buf_append_u8(&buf, payload->migratable); tpm_buf_append_u8(&buf, payload->migratable);
/* public */ /* 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, 14);
tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH); tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
tpm_buf_append_u16(&buf, hash); 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_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, TPM2_ALG_NULL);
tpm_buf_append_u16(&buf, 0); tpm_buf_append_u16(&buf, 0);
...@@ -613,7 +627,9 @@ static int tpm2_unseal(struct tpm_chip *chip, ...@@ -613,7 +627,9 @@ static int tpm2_unseal(struct tpm_chip *chip,
return rc; return rc;
tpm_buf_append_u32(&buf, blob_handle); 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, NULL /* nonce */, 0,
0 /* session_attributes */, 0 /* session_attributes */,
options->blobauth /* hmac */, options->blobauth /* hmac */,
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#define MAX_KEY_SIZE 128 #define MAX_KEY_SIZE 128
#define MAX_BLOB_SIZE 512 #define MAX_BLOB_SIZE 512
#define MAX_PCRINFO_SIZE 64 #define MAX_PCRINFO_SIZE 64
#define MAX_DIGEST_SIZE 64
struct trusted_key_payload { struct trusted_key_payload {
struct rcu_head rcu; struct rcu_head rcu;
...@@ -37,6 +38,9 @@ struct trusted_key_options { ...@@ -37,6 +38,9 @@ struct trusted_key_options {
unsigned char pcrinfo[MAX_PCRINFO_SIZE]; unsigned char pcrinfo[MAX_PCRINFO_SIZE];
int pcrlock; int pcrlock;
uint32_t hash; uint32_t hash;
uint32_t digest_len;
unsigned char policydigest[MAX_DIGEST_SIZE];
uint32_t policyhandle;
}; };
extern struct key_type key_type_trusted; extern struct key_type key_type_trusted;
......
...@@ -713,6 +713,8 @@ enum { ...@@ -713,6 +713,8 @@ enum {
Opt_keyhandle, Opt_keyauth, Opt_blobauth, Opt_keyhandle, Opt_keyauth, Opt_blobauth,
Opt_pcrinfo, Opt_pcrlock, Opt_migratable, Opt_pcrinfo, Opt_pcrlock, Opt_migratable,
Opt_hash, Opt_hash,
Opt_policydigest,
Opt_policyhandle,
}; };
static const match_table_t key_tokens = { static const match_table_t key_tokens = {
...@@ -726,6 +728,8 @@ static const match_table_t key_tokens = { ...@@ -726,6 +728,8 @@ static const match_table_t key_tokens = {
{Opt_pcrlock, "pcrlock=%s"}, {Opt_pcrlock, "pcrlock=%s"},
{Opt_migratable, "migratable=%s"}, {Opt_migratable, "migratable=%s"},
{Opt_hash, "hash=%s"}, {Opt_hash, "hash=%s"},
{Opt_policydigest, "policydigest=%s"},
{Opt_policyhandle, "policyhandle=%s"},
{Opt_err, NULL} {Opt_err, NULL}
}; };
...@@ -748,6 +752,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay, ...@@ -748,6 +752,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
return tpm2; return tpm2;
opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1; opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
opt->digest_len = hash_digest_size[opt->hash];
while ((p = strsep(&c, " \t"))) { while ((p = strsep(&c, " \t"))) {
if (*p == '\0' || *p == ' ' || *p == '\t') if (*p == '\0' || *p == ' ' || *p == '\t')
...@@ -802,9 +807,13 @@ static int getoptions(char *c, struct trusted_key_payload *pay, ...@@ -802,9 +807,13 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
opt->pcrlock = lock; opt->pcrlock = lock;
break; break;
case Opt_hash: case Opt_hash:
if (test_bit(Opt_policydigest, &token_mask))
return -EINVAL;
for (i = 0; i < HASH_ALGO__LAST; i++) { for (i = 0; i < HASH_ALGO__LAST; i++) {
if (!strcmp(args[0].from, hash_algo_name[i])) { if (!strcmp(args[0].from, hash_algo_name[i])) {
opt->hash = i; opt->hash = i;
opt->digest_len =
hash_digest_size[opt->hash];
break; break;
} }
} }
...@@ -815,6 +824,23 @@ static int getoptions(char *c, struct trusted_key_payload *pay, ...@@ -815,6 +824,23 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
return -EINVAL; return -EINVAL;
} }
break; 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: default:
return -EINVAL; return -EINVAL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment