@@ -418,7 +418,9 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
{
unsigned int blob_len;
struct tpm_buf buf;
+ struct tpm_buf t2b;
u32 hash;
+ struct tpm2_auth *auth;
int i;
int rc;
@@ -432,45 +434,56 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
if (i == ARRAY_SIZE(tpm2_hash_map))
return -EINVAL;
- rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
+ rc = tpm2_start_auth_session(chip, &auth);
if (rc)
return rc;
- tpm_buf_append_u32(&buf, options->keyhandle);
- tpm2_buf_append_auth(&buf, TPM2_RS_PW,
- NULL /* nonce */, 0,
- 0 /* session_attributes */,
- options->keyauth /* hmac */,
- TPM_DIGEST_SIZE);
+ rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
+ if (rc) {
+ tpm2_end_auth_session(auth);
+ return rc;
+ }
+
+ rc = tpm_buf_init_2b(&t2b);
+ if (rc) {
+ tpm_buf_destroy(&buf);
+ tpm2_end_auth_session(auth);
+ return rc;
+ }
+ tpm_buf_append_name(&buf, auth, options->keyhandle, NULL);
+ tpm_buf_append_hmac_session(&buf, auth, TPM2_SA_DECRYPT,
+ options->keyauth, TPM_DIGEST_SIZE);
/* sensitive */
- tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len + 1);
+ tpm_buf_append_u16(&t2b, TPM_DIGEST_SIZE);
+ tpm_buf_append(&t2b, options->blobauth, TPM_DIGEST_SIZE);
+ tpm_buf_append_u16(&t2b, payload->key_len + 1);
+ tpm_buf_append(&t2b, payload->key, payload->key_len);
+ tpm_buf_append_u8(&t2b, payload->migratable);
- tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE);
- tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE);
- tpm_buf_append_u16(&buf, payload->key_len + 1);
- tpm_buf_append(&buf, payload->key, payload->key_len);
- tpm_buf_append_u8(&buf, payload->migratable);
+ tpm_buf_append_2b(&buf, &t2b);
/* public */
- tpm_buf_append_u16(&buf, 14 + options->policydigest_len);
- tpm_buf_append_u16(&buf, TPM_ALG_KEYEDHASH);
- tpm_buf_append_u16(&buf, hash);
+ tpm_buf_append_u16(&t2b, TPM_ALG_KEYEDHASH);
+ tpm_buf_append_u16(&t2b, hash);
/* policy */
if (options->policydigest_len) {
- tpm_buf_append_u32(&buf, 0);
- tpm_buf_append_u16(&buf, options->policydigest_len);
- tpm_buf_append(&buf, options->policydigest,
+ tpm_buf_append_u32(&t2b, 0);
+ tpm_buf_append_u16(&t2b, options->policydigest_len);
+ tpm_buf_append(&t2b, options->policydigest,
options->policydigest_len);
} else {
- tpm_buf_append_u32(&buf, TPM2_OA_USER_WITH_AUTH);
- tpm_buf_append_u16(&buf, 0);
+ tpm_buf_append_u32(&t2b, TPM2_OA_USER_WITH_AUTH);
+ tpm_buf_append_u16(&t2b, 0);
}
/* public parameters */
- tpm_buf_append_u16(&buf, TPM_ALG_NULL);
- tpm_buf_append_u16(&buf, 0);
+ tpm_buf_append_u16(&t2b, TPM_ALG_NULL);
+ /* unique (zero) */
+ tpm_buf_append_u16(&t2b, 0);
+
+ tpm_buf_append_2b(&buf, &t2b);
/* outside info */
tpm_buf_append_u16(&buf, 0);
@@ -483,7 +496,9 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
goto out;
}
+ tpm_buf_fill_hmac_session(&buf, auth);
rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
+ rc = tpm_buf_check_hmac_response(&buf, auth, rc);
if (rc)
goto out;
@@ -501,6 +516,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
payload->blob_len = blob_len;
out:
+ tpm_buf_destroy(&t2b);
tpm_buf_destroy(&buf);
if (rc > 0) {
@@ -532,6 +548,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
u32 *blob_handle)
{
struct tpm_buf buf;
+ struct tpm2_auth *auth;
unsigned int private_len;
unsigned int public_len;
unsigned int blob_len;
@@ -546,17 +563,18 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
if (blob_len > payload->blob_len)
return -E2BIG;
- rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
+ rc = tpm2_start_auth_session(chip, &auth);
if (rc)
return rc;
- tpm_buf_append_u32(&buf, options->keyhandle);
- tpm2_buf_append_auth(&buf, TPM2_RS_PW,
- NULL /* nonce */, 0,
- 0 /* session_attributes */,
- options->keyauth /* hmac */,
- TPM_DIGEST_SIZE);
+ rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
+ if (rc) {
+ tpm2_end_auth_session(auth);
+ return rc;
+ }
+ tpm_buf_append_name(&buf, auth, options->keyhandle, NULL);
+ tpm_buf_append_hmac_session(&buf, auth, 0, options->keyauth, TPM_DIGEST_SIZE);
tpm_buf_append(&buf, payload->blob, blob_len);
if (buf.flags & TPM_BUF_OVERFLOW) {
@@ -564,7 +582,9 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
goto out;
}
+ tpm_buf_fill_hmac_session(&buf, auth);
rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob");
+ rc = tpm_buf_check_hmac_response(&buf, auth, rc);
if (!rc)
*blob_handle = be32_to_cpup(
(__be32 *) &buf.data[TPM_HEADER_SIZE]);
@@ -596,24 +616,50 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
u32 blob_handle)
{
struct tpm_buf buf;
+ struct tpm2_auth *auth;
u16 data_len;
u8 *data;
int rc;
- rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
+ rc = tpm2_start_auth_session(chip, &auth);
if (rc)
return rc;
- tpm_buf_append_u32(&buf, blob_handle);
- tpm2_buf_append_auth(&buf,
- options->policyhandle ?
- options->policyhandle : TPM2_RS_PW,
- NULL /* nonce */, 0,
- TPM2_SA_CONTINUE_SESSION,
- options->blobauth /* hmac */,
- TPM_DIGEST_SIZE);
+ rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
+ if (rc) {
+ tpm2_end_auth_session(auth);
+ return rc;
+ }
+
+ tpm_buf_append_name(&buf, auth, blob_handle, NULL);
+
+ if (!options->policyhandle) {
+ tpm_buf_append_hmac_session(&buf, auth, TPM2_SA_ENCRYPT,
+ options->blobauth, TPM_DIGEST_SIZE);
+ } else {
+ /*
+ * FIXME: the policy can't be used for HMAC protection
+ * of the authorization because it must be generated
+ * with the initial nonces which isn't passed in, so
+ * append a second encryption session to at least HMAC
+ * protect the command and encrypt the sealed blob on
+ * return.
+ *
+ * Note: this also means the caller either has to use
+ * an empty password or compute the password HMAC
+ * based on the policy nonces and place it in blobauth
+ */
+ tpm2_buf_append_auth(&buf, options->policyhandle,
+ NULL /* nonce */, 0, 0,
+ options->blobauth /* hmac */,
+ TPM_DIGEST_SIZE);
+ tpm_buf_append_hmac_session_opt(&buf, auth, TPM2_SA_ENCRYPT,
+ NULL, 0);
+ }
+ tpm_buf_fill_hmac_session(&buf, auth);
rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing");
+ rc = tpm_buf_check_hmac_response(&buf, auth, rc);
if (rc > 0)
rc = -EPERM;