1
0

Merge tag 'tpmdd-sessions-next-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd

Pull more tpm updates from Jarkko Sakkinen:
 "This is targeted for tpm2-sessions updates.

  There's two bug fixes and two more cosmetic tweaks for HMAC protected
  sessions. They provide a baseine for further improvements to be
  implemented during the the course of the release cycle"

* tag 'tpmdd-sessions-next-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd:
  tpm2-sessions: Open code tpm_buf_append_hmac_session()
  tpm2-sessions: Remove 'attributes' parameter from tpm_buf_append_auth
  tpm2-sessions: Fix tpm2_read_public range checks
  tpm2-sessions: Fix out of range indexing in name_size
This commit is contained in:
Linus Torvalds
2025-12-05 20:36:28 -08:00
4 changed files with 204 additions and 116 deletions

View File

@@ -11,8 +11,11 @@
* used by the kernel internally. * used by the kernel internally.
*/ */
#include "linux/dev_printk.h"
#include "linux/tpm.h"
#include "tpm.h" #include "tpm.h"
#include <crypto/hash_info.h> #include <crypto/hash_info.h>
#include <linux/unaligned.h>
static bool disable_pcr_integrity; static bool disable_pcr_integrity;
module_param(disable_pcr_integrity, bool, 0444); module_param(disable_pcr_integrity, bool, 0444);
@@ -199,11 +202,15 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
} }
if (!disable_pcr_integrity) { if (!disable_pcr_integrity) {
tpm_buf_append_name(chip, &buf, pcr_idx, NULL); rc = tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
if (rc) {
tpm_buf_destroy(&buf);
return rc;
}
tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0); tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0);
} else { } else {
tpm_buf_append_handle(chip, &buf, pcr_idx); tpm_buf_append_handle(chip, &buf, pcr_idx);
tpm_buf_append_auth(chip, &buf, 0, NULL, 0); tpm_buf_append_auth(chip, &buf, NULL, 0);
} }
tpm_buf_append_u32(&buf, chip->nr_allocated_banks); tpm_buf_append_u32(&buf, chip->nr_allocated_banks);
@@ -214,8 +221,14 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
chip->allocated_banks[i].digest_size); chip->allocated_banks[i].digest_size);
} }
if (!disable_pcr_integrity) if (!disable_pcr_integrity) {
tpm_buf_fill_hmac_session(chip, &buf); rc = tpm_buf_fill_hmac_session(chip, &buf);
if (rc) {
tpm_buf_destroy(&buf);
return rc;
}
}
rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value"); rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value");
if (!disable_pcr_integrity) if (!disable_pcr_integrity)
rc = tpm_buf_check_hmac_response(chip, &buf, rc); rc = tpm_buf_check_hmac_response(chip, &buf, rc);
@@ -269,11 +282,24 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
do { do {
tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM); tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM);
tpm_buf_append_hmac_session_opt(chip, &buf, TPM2_SA_ENCRYPT if (tpm2_chip_auth(chip)) {
| TPM2_SA_CONTINUE_SESSION, tpm_buf_append_hmac_session(chip, &buf,
TPM2_SA_ENCRYPT |
TPM2_SA_CONTINUE_SESSION,
NULL, 0); NULL, 0);
} else {
offset = buf.handles * 4 + TPM_HEADER_SIZE;
head = (struct tpm_header *)buf.data;
if (tpm_buf_length(&buf) == offset)
head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
}
tpm_buf_append_u16(&buf, num_bytes); tpm_buf_append_u16(&buf, num_bytes);
tpm_buf_fill_hmac_session(chip, &buf); err = tpm_buf_fill_hmac_session(chip, &buf);
if (err) {
tpm_buf_destroy(&buf);
return err;
}
err = tpm_transmit_cmd(chip, &buf, err = tpm_transmit_cmd(chip, &buf,
offsetof(struct tpm2_get_random_out, offsetof(struct tpm2_get_random_out,
buffer), buffer),

View File

@@ -144,59 +144,80 @@ struct tpm2_auth {
/* /*
* Name Size based on TPM algorithm (assumes no hash bigger than 255) * Name Size based on TPM algorithm (assumes no hash bigger than 255)
*/ */
static u8 name_size(const u8 *name) static int name_size(const u8 *name)
{ {
static u8 size_map[] = { u16 hash_alg = get_unaligned_be16(name);
[TPM_ALG_SHA1] = SHA1_DIGEST_SIZE,
[TPM_ALG_SHA256] = SHA256_DIGEST_SIZE, switch (hash_alg) {
[TPM_ALG_SHA384] = SHA384_DIGEST_SIZE, case TPM_ALG_SHA1:
[TPM_ALG_SHA512] = SHA512_DIGEST_SIZE, return SHA1_DIGEST_SIZE + 2;
}; case TPM_ALG_SHA256:
u16 alg = get_unaligned_be16(name); return SHA256_DIGEST_SIZE + 2;
return size_map[alg] + 2; case TPM_ALG_SHA384:
return SHA384_DIGEST_SIZE + 2;
case TPM_ALG_SHA512:
return SHA512_DIGEST_SIZE + 2;
default:
pr_warn("tpm: unsupported name algorithm: 0x%04x\n", hash_alg);
return -EINVAL;
}
} }
static int tpm2_parse_read_public(char *name, struct tpm_buf *buf) static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name)
{ {
struct tpm_header *head = (struct tpm_header *)buf->data; u32 mso = tpm2_handle_mso(handle);
off_t offset = TPM_HEADER_SIZE; off_t offset = TPM_HEADER_SIZE;
u32 tot_len = be32_to_cpu(head->length); int rc, name_size_alg;
u32 val;
/* we're starting after the header so adjust the length */
tot_len -= TPM_HEADER_SIZE;
/* skip public */
val = tpm_buf_read_u16(buf, &offset);
if (val > tot_len)
return -EINVAL;
offset += val;
/* name */
val = tpm_buf_read_u16(buf, &offset);
if (val != name_size(&buf->data[offset]))
return -EINVAL;
memcpy(name, &buf->data[offset], val);
/* forget the rest */
return 0;
}
static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name)
{
struct tpm_buf buf; struct tpm_buf buf;
int rc;
if (mso != TPM2_MSO_PERSISTENT && mso != TPM2_MSO_VOLATILE &&
mso != TPM2_MSO_NVRAM) {
memcpy(name, &handle, sizeof(u32));
return sizeof(u32);
}
rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC); rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC);
if (rc) if (rc)
return rc; return rc;
tpm_buf_append_u32(&buf, handle); tpm_buf_append_u32(&buf, handle);
rc = tpm_transmit_cmd(chip, &buf, 0, "read public");
if (rc == TPM2_RC_SUCCESS)
rc = tpm2_parse_read_public(name, &buf);
rc = tpm_transmit_cmd(chip, &buf, 0, "TPM2_ReadPublic");
if (rc) {
tpm_buf_destroy(&buf); tpm_buf_destroy(&buf);
return tpm_ret_to_err(rc);
}
return rc; /* Skip TPMT_PUBLIC: */
offset += tpm_buf_read_u16(&buf, &offset);
/*
* Ensure space for the length field of TPM2B_NAME and hashAlg field of
* TPMT_HA (the extra four bytes).
*/
if (offset + 4 > tpm_buf_length(&buf)) {
tpm_buf_destroy(&buf);
return -EIO;
}
rc = tpm_buf_read_u16(&buf, &offset);
name_size_alg = name_size(&buf.data[offset]);
if (name_size_alg < 0)
return name_size_alg;
if (rc != name_size_alg) {
tpm_buf_destroy(&buf);
return -EIO;
}
if (offset + rc > tpm_buf_length(&buf)) {
tpm_buf_destroy(&buf);
return -EIO;
}
memcpy(name, &buf.data[offset], rc);
return name_size_alg;
} }
#endif /* CONFIG_TCG_TPM2_HMAC */ #endif /* CONFIG_TCG_TPM2_HMAC */
@@ -221,52 +242,76 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name)
* As with most tpm_buf operations, success is assumed because failure * As with most tpm_buf operations, success is assumed because failure
* will be caused by an incorrect programming model and indicated by a * will be caused by an incorrect programming model and indicated by a
* kernel message. * kernel message.
*
* Ends the authorization session on failure.
*/ */
void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf, int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
u32 handle, u8 *name) u32 handle, u8 *name)
{ {
#ifdef CONFIG_TCG_TPM2_HMAC #ifdef CONFIG_TCG_TPM2_HMAC
enum tpm2_mso_type mso = tpm2_handle_mso(handle); enum tpm2_mso_type mso = tpm2_handle_mso(handle);
struct tpm2_auth *auth; struct tpm2_auth *auth;
u16 name_size_alg;
int slot; int slot;
int ret;
#endif #endif
if (!tpm2_chip_auth(chip)) { if (!tpm2_chip_auth(chip)) {
tpm_buf_append_handle(chip, buf, handle); tpm_buf_append_handle(chip, buf, handle);
return; return 0;
} }
#ifdef CONFIG_TCG_TPM2_HMAC #ifdef CONFIG_TCG_TPM2_HMAC
slot = (tpm_buf_length(buf) - TPM_HEADER_SIZE) / 4; slot = (tpm_buf_length(buf) - TPM_HEADER_SIZE) / 4;
if (slot >= AUTH_MAX_NAMES) { if (slot >= AUTH_MAX_NAMES) {
dev_err(&chip->dev, "TPM: too many handles\n"); dev_err(&chip->dev, "too many handles\n");
return; ret = -EIO;
goto err;
} }
auth = chip->auth; auth = chip->auth;
WARN(auth->session != tpm_buf_length(buf), if (auth->session != tpm_buf_length(buf)) {
"name added in wrong place\n"); dev_err(&chip->dev, "session state malformed");
ret = -EIO;
goto err;
}
tpm_buf_append_u32(buf, handle); tpm_buf_append_u32(buf, handle);
auth->session += 4; auth->session += 4;
if (mso == TPM2_MSO_PERSISTENT || if (mso == TPM2_MSO_PERSISTENT ||
mso == TPM2_MSO_VOLATILE || mso == TPM2_MSO_VOLATILE ||
mso == TPM2_MSO_NVRAM) { mso == TPM2_MSO_NVRAM) {
if (!name) if (!name) {
tpm2_read_public(chip, handle, auth->name[slot]); ret = tpm2_read_public(chip, handle, auth->name[slot]);
if (ret < 0)
goto err;
name_size_alg = ret;
}
} else { } else {
if (name) if (name) {
dev_err(&chip->dev, "TPM: Handle does not require name but one is specified\n"); dev_err(&chip->dev, "handle 0x%08x does not use a name\n",
handle);
ret = -EIO;
goto err;
}
} }
auth->name_h[slot] = handle; auth->name_h[slot] = handle;
if (name) if (name)
memcpy(auth->name[slot], name, name_size(name)); memcpy(auth->name[slot], name, name_size_alg);
#endif
return 0;
#ifdef CONFIG_TCG_TPM2_HMAC
err:
tpm2_end_auth_session(chip);
return tpm_ret_to_err(ret);
#endif #endif
} }
EXPORT_SYMBOL_GPL(tpm_buf_append_name); EXPORT_SYMBOL_GPL(tpm_buf_append_name);
void tpm_buf_append_auth(struct tpm_chip *chip, struct tpm_buf *buf, void tpm_buf_append_auth(struct tpm_chip *chip, struct tpm_buf *buf,
u8 attributes, u8 *passphrase, int passphrase_len) u8 *passphrase, int passphrase_len)
{ {
/* offset tells us where the sessions area begins */ /* offset tells us where the sessions area begins */
int offset = buf->handles * 4 + TPM_HEADER_SIZE; int offset = buf->handles * 4 + TPM_HEADER_SIZE;
@@ -327,8 +372,7 @@ void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
#endif #endif
if (!tpm2_chip_auth(chip)) { if (!tpm2_chip_auth(chip)) {
tpm_buf_append_auth(chip, buf, attributes, passphrase, tpm_buf_append_auth(chip, buf, passphrase, passphrase_len);
passphrase_len);
return; return;
} }
@@ -533,11 +577,9 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
* encryption key and encrypts the first parameter of the command * encryption key and encrypts the first parameter of the command
* buffer with it. * buffer with it.
* *
* As with most tpm_buf operations, success is assumed because failure * Ends the authorization session on failure.
* will be caused by an incorrect programming model and indicated by a
* kernel message.
*/ */
void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf) int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
{ {
u32 cc, handles, val; u32 cc, handles, val;
struct tpm2_auth *auth = chip->auth; struct tpm2_auth *auth = chip->auth;
@@ -549,9 +591,12 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
u8 cphash[SHA256_DIGEST_SIZE]; u8 cphash[SHA256_DIGEST_SIZE];
struct sha256_ctx sctx; struct sha256_ctx sctx;
struct hmac_sha256_ctx hctx; struct hmac_sha256_ctx hctx;
int ret;
if (!auth) if (!auth) {
return; ret = -EIO;
goto err;
}
/* save the command code in BE format */ /* save the command code in BE format */
auth->ordinal = head->ordinal; auth->ordinal = head->ordinal;
@@ -560,9 +605,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
i = tpm2_find_cc(chip, cc); i = tpm2_find_cc(chip, cc);
if (i < 0) { if (i < 0) {
dev_err(&chip->dev, "Command 0x%x not found in TPM\n", cc); dev_err(&chip->dev, "command 0x%08x not found\n", cc);
return; ret = -EIO;
goto err;
} }
attrs = chip->cc_attrs_tbl[i]; attrs = chip->cc_attrs_tbl[i];
handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0); handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
@@ -576,9 +623,9 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
u32 handle = tpm_buf_read_u32(buf, &offset_s); u32 handle = tpm_buf_read_u32(buf, &offset_s);
if (auth->name_h[i] != handle) { if (auth->name_h[i] != handle) {
dev_err(&chip->dev, "TPM: handle %d wrong for name\n", dev_err(&chip->dev, "invalid handle 0x%08x\n", handle);
i); ret = -EIO;
return; goto err;
} }
} }
/* point offset_s to the start of the sessions */ /* point offset_s to the start of the sessions */
@@ -609,12 +656,14 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
offset_s += len; offset_s += len;
} }
if (offset_s != offset_p) { if (offset_s != offset_p) {
dev_err(&chip->dev, "TPM session length is incorrect\n"); dev_err(&chip->dev, "session length is incorrect\n");
return; ret = -EIO;
goto err;
} }
if (!hmac) { if (!hmac) {
dev_err(&chip->dev, "TPM could not find HMAC session\n"); dev_err(&chip->dev, "could not find HMAC session\n");
return; ret = -EIO;
goto err;
} }
/* encrypt before HMAC */ /* encrypt before HMAC */
@@ -646,8 +695,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
if (mso == TPM2_MSO_PERSISTENT || if (mso == TPM2_MSO_PERSISTENT ||
mso == TPM2_MSO_VOLATILE || mso == TPM2_MSO_VOLATILE ||
mso == TPM2_MSO_NVRAM) { mso == TPM2_MSO_NVRAM) {
sha256_update(&sctx, auth->name[i], ret = name_size(auth->name[i]);
name_size(auth->name[i])); if (ret < 0)
goto err;
sha256_update(&sctx, auth->name[i], ret);
} else { } else {
__be32 h = cpu_to_be32(auth->name_h[i]); __be32 h = cpu_to_be32(auth->name_h[i]);
@@ -668,6 +720,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
hmac_sha256_update(&hctx, auth->tpm_nonce, sizeof(auth->tpm_nonce)); hmac_sha256_update(&hctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
hmac_sha256_update(&hctx, &auth->attrs, 1); hmac_sha256_update(&hctx, &auth->attrs, 1);
hmac_sha256_final(&hctx, hmac); hmac_sha256_final(&hctx, hmac);
return 0;
err:
tpm2_end_auth_session(chip);
return ret;
} }
EXPORT_SYMBOL(tpm_buf_fill_hmac_session); EXPORT_SYMBOL(tpm_buf_fill_hmac_session);

View File

@@ -529,41 +529,18 @@ static inline struct tpm2_auth *tpm2_chip_auth(struct tpm_chip *chip)
#endif #endif
} }
void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf, int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
u32 handle, u8 *name); u32 handle, u8 *name);
void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf, void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
u8 attributes, u8 *passphrase, u8 attributes, u8 *passphrase,
int passphraselen); int passphraselen);
void tpm_buf_append_auth(struct tpm_chip *chip, struct tpm_buf *buf, void tpm_buf_append_auth(struct tpm_chip *chip, struct tpm_buf *buf,
u8 attributes, u8 *passphrase, int passphraselen); u8 *passphrase, int passphraselen);
static inline void tpm_buf_append_hmac_session_opt(struct tpm_chip *chip,
struct tpm_buf *buf,
u8 attributes,
u8 *passphrase,
int passphraselen)
{
struct tpm_header *head;
int offset;
if (tpm2_chip_auth(chip)) {
tpm_buf_append_hmac_session(chip, buf, attributes, passphrase, passphraselen);
} else {
offset = buf->handles * 4 + TPM_HEADER_SIZE;
head = (struct tpm_header *)buf->data;
/*
* If the only sessions are optional, the command tag must change to
* TPM2_ST_NO_SESSIONS.
*/
if (tpm_buf_length(buf) == offset)
head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
}
}
#ifdef CONFIG_TCG_TPM2_HMAC #ifdef CONFIG_TCG_TPM2_HMAC
int tpm2_start_auth_session(struct tpm_chip *chip); int tpm2_start_auth_session(struct tpm_chip *chip);
void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf); int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf);
int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf, int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
int rc); int rc);
void tpm2_end_auth_session(struct tpm_chip *chip); void tpm2_end_auth_session(struct tpm_chip *chip);
@@ -577,10 +554,13 @@ static inline int tpm2_start_auth_session(struct tpm_chip *chip)
static inline void tpm2_end_auth_session(struct tpm_chip *chip) static inline void tpm2_end_auth_session(struct tpm_chip *chip)
{ {
} }
static inline void tpm_buf_fill_hmac_session(struct tpm_chip *chip,
static inline int tpm_buf_fill_hmac_session(struct tpm_chip *chip,
struct tpm_buf *buf) struct tpm_buf *buf)
{ {
return 0;
} }
static inline int tpm_buf_check_hmac_response(struct tpm_chip *chip, static inline int tpm_buf_check_hmac_response(struct tpm_chip *chip,
struct tpm_buf *buf, struct tpm_buf *buf,
int rc) int rc)

View File

@@ -268,7 +268,10 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
goto out_put; goto out_put;
} }
tpm_buf_append_name(chip, &buf, options->keyhandle, NULL); rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
if (rc)
goto out;
tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT, tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT,
options->keyauth, TPM_DIGEST_SIZE); options->keyauth, TPM_DIGEST_SIZE);
@@ -316,7 +319,10 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
goto out; goto out;
} }
tpm_buf_fill_hmac_session(chip, &buf); rc = tpm_buf_fill_hmac_session(chip, &buf);
if (rc)
goto out;
rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data"); rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
rc = tpm_buf_check_hmac_response(chip, &buf, rc); rc = tpm_buf_check_hmac_response(chip, &buf, rc);
if (rc) if (rc)
@@ -427,7 +433,10 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
return rc; return rc;
} }
tpm_buf_append_name(chip, &buf, options->keyhandle, NULL); rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
if (rc)
goto out;
tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth, tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth,
TPM_DIGEST_SIZE); TPM_DIGEST_SIZE);
@@ -439,7 +448,10 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
goto out; goto out;
} }
tpm_buf_fill_hmac_session(chip, &buf); rc = tpm_buf_fill_hmac_session(chip, &buf);
if (rc)
goto out;
rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob"); rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob");
rc = tpm_buf_check_hmac_response(chip, &buf, rc); rc = tpm_buf_check_hmac_response(chip, &buf, rc);
if (!rc) if (!rc)
@@ -469,8 +481,10 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
struct trusted_key_options *options, struct trusted_key_options *options,
u32 blob_handle) u32 blob_handle)
{ {
struct tpm_header *head;
struct tpm_buf buf; struct tpm_buf buf;
u16 data_len; u16 data_len;
int offset;
u8 *data; u8 *data;
int rc; int rc;
@@ -484,7 +498,9 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
return rc; return rc;
} }
tpm_buf_append_name(chip, &buf, blob_handle, NULL); rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
if (rc)
goto out;
if (!options->policyhandle) { if (!options->policyhandle) {
tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT,
@@ -505,11 +521,20 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
tpm2_buf_append_auth(&buf, options->policyhandle, tpm2_buf_append_auth(&buf, options->policyhandle,
NULL /* nonce */, 0, 0, NULL /* nonce */, 0, 0,
options->blobauth, options->blobauth_len); options->blobauth, options->blobauth_len);
tpm_buf_append_hmac_session_opt(chip, &buf, TPM2_SA_ENCRYPT, if (tpm2_chip_auth(chip)) {
NULL, 0); tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, NULL, 0);
} else {
offset = buf.handles * 4 + TPM_HEADER_SIZE;
head = (struct tpm_header *)buf.data;
if (tpm_buf_length(&buf) == offset)
head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
}
} }
tpm_buf_fill_hmac_session(chip, &buf); rc = tpm_buf_fill_hmac_session(chip, &buf);
if (rc)
goto out;
rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing"); rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing");
rc = tpm_buf_check_hmac_response(chip, &buf, rc); rc = tpm_buf_check_hmac_response(chip, &buf, rc);