1f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
239f66114c03639715cb88774255f066a2d942557Randall Spangler * Use of this source code is governed by a BSD-style license that can be
339f66114c03639715cb88774255f066a2d942557Randall Spangler * found in the LICENSE file.
439f66114c03639715cb88774255f066a2d942557Randall Spangler */
539f66114c03639715cb88774255f066a2d942557Randall Spangler
639f66114c03639715cb88774255f066a2d942557Randall Spangler/* A lightweight TPM command library.
739f66114c03639715cb88774255f066a2d942557Randall Spangler *
839f66114c03639715cb88774255f066a2d942557Randall Spangler * The general idea is that TPM commands are array of bytes whose
939f66114c03639715cb88774255f066a2d942557Randall Spangler * fields are mostly compile-time constant.  The goal is to build much
1039f66114c03639715cb88774255f066a2d942557Randall Spangler * of the commands at compile time (or build time) and change some of
1139f66114c03639715cb88774255f066a2d942557Randall Spangler * the fields at run time as needed.  The code in
1239f66114c03639715cb88774255f066a2d942557Randall Spangler * utility/tlcl_generator.c builds structures containing the commands,
1339f66114c03639715cb88774255f066a2d942557Randall Spangler * as well as the offsets of the fields that need to be set at run
1439f66114c03639715cb88774255f066a2d942557Randall Spangler * time.
1539f66114c03639715cb88774255f066a2d942557Randall Spangler */
1639f66114c03639715cb88774255f066a2d942557Randall Spangler
1739f66114c03639715cb88774255f066a2d942557Randall Spangler#include "sysincludes.h"
180c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson
1939f66114c03639715cb88774255f066a2d942557Randall Spangler#include "tlcl.h"
2039f66114c03639715cb88774255f066a2d942557Randall Spangler#include "tlcl_internal.h"
2139f66114c03639715cb88774255f066a2d942557Randall Spangler#include "tlcl_structures.h"
2239f66114c03639715cb88774255f066a2d942557Randall Spangler#include "utility.h"
23e49e8af65fce38da7a308305566f8a14f102254aRandall Spangler#include "vboot_api.h"
2439f66114c03639715cb88774255f066a2d942557Randall Spangler
25c3d488d155961d2849dfdaa4f0461df1aa95c2caRandall Spangler#ifdef FOR_TEST
26c3d488d155961d2849dfdaa4f0461df1aa95c2caRandall Spangler/* Allow unit testing implementation of TlclSendReceive() */
27c3d488d155961d2849dfdaa4f0461df1aa95c2caRandall Spangler#undef CHROMEOS_ENVIRONMENT
28c3d488d155961d2849dfdaa4f0461df1aa95c2caRandall Spangler#endif
29c3d488d155961d2849dfdaa4f0461df1aa95c2caRandall Spangler
3039f66114c03639715cb88774255f066a2d942557Randall Spangler/* Sets the size field of a TPM command. */
31ac8805e7e9bd40c03baf44e37b26f28d9b763ab5Gabe Blackstatic inline void SetTpmCommandSize(uint8_t* buffer, uint32_t size) {
3239f66114c03639715cb88774255f066a2d942557Randall Spangler  ToTpmUint32(buffer + sizeof(uint16_t), size);
3339f66114c03639715cb88774255f066a2d942557Randall Spangler}
3439f66114c03639715cb88774255f066a2d942557Randall Spangler
3539f66114c03639715cb88774255f066a2d942557Randall Spangler/* Gets the size field of a TPM command. */
36ac8805e7e9bd40c03baf44e37b26f28d9b763ab5Gabe Black__attribute__((unused))
37ac8805e7e9bd40c03baf44e37b26f28d9b763ab5Gabe Blackstatic inline int TpmCommandSize(const uint8_t* buffer) {
3839f66114c03639715cb88774255f066a2d942557Randall Spangler  uint32_t size;
3939f66114c03639715cb88774255f066a2d942557Randall Spangler  FromTpmUint32(buffer + sizeof(uint16_t), &size);
4039f66114c03639715cb88774255f066a2d942557Randall Spangler  return (int) size;
4139f66114c03639715cb88774255f066a2d942557Randall Spangler}
4239f66114c03639715cb88774255f066a2d942557Randall Spangler
433428b4bcd99a6d2e9f8b3e1bdf800d943fbe78c3Luigi Semenzato/* Gets the size field of a TPM request or response. */
443428b4bcd99a6d2e9f8b3e1bdf800d943fbe78c3Luigi Semenzatoint TlclPacketSize(const uint8_t* packet) {
453428b4bcd99a6d2e9f8b3e1bdf800d943fbe78c3Luigi Semenzato  return TpmCommandSize(packet);
463428b4bcd99a6d2e9f8b3e1bdf800d943fbe78c3Luigi Semenzato}
473428b4bcd99a6d2e9f8b3e1bdf800d943fbe78c3Luigi Semenzato
4839f66114c03639715cb88774255f066a2d942557Randall Spangler/* Gets the code field of a TPM command. */
49ac8805e7e9bd40c03baf44e37b26f28d9b763ab5Gabe Blackstatic inline int TpmCommandCode(const uint8_t* buffer) {
5039f66114c03639715cb88774255f066a2d942557Randall Spangler  uint32_t code;
5139f66114c03639715cb88774255f066a2d942557Randall Spangler  FromTpmUint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code);
5239f66114c03639715cb88774255f066a2d942557Randall Spangler  return code;
5339f66114c03639715cb88774255f066a2d942557Randall Spangler}
5439f66114c03639715cb88774255f066a2d942557Randall Spangler
5539f66114c03639715cb88774255f066a2d942557Randall Spangler/* Gets the return code field of a TPM result. */
56ac8805e7e9bd40c03baf44e37b26f28d9b763ab5Gabe Blackstatic inline int TpmReturnCode(const uint8_t* buffer) {
5739f66114c03639715cb88774255f066a2d942557Randall Spangler  return TpmCommandCode(buffer);
5839f66114c03639715cb88774255f066a2d942557Randall Spangler}
5939f66114c03639715cb88774255f066a2d942557Randall Spangler
6006fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato/* Like TlclSendReceive below, but do not retry if NEEDS_SELFTEST or
6106fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato * DOING_SELFTEST errors are returned.
6206fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato */
6306fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzatostatic uint32_t TlclSendReceiveNoRetry(const uint8_t* request,
6406fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato                                       uint8_t* response, int max_length) {
651b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler
661b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler  uint32_t response_length = max_length;
67205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  uint32_t result;
683e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler
6963dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler#ifdef EXTRA_LOGGING
7063dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler  VBDEBUG(("TPM: command: %x%x %x%x%x%x %x%x%x%x\n",
7163dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler           request[0], request[1],
7263dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler           request[2], request[3], request[4], request[5],
7363dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler           request[6], request[7], request[8], request[9]));
7450d48feb9e0df6a990cc5890ce14e1398798eeb1Luigi Semenzato#endif
7563dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler
761b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler  result = VbExTpmSendReceive(request, TpmCommandSize(request),
771b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler                              response, &response_length);
78205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  if (0 != result) {
79205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler    /* Communication with TPM failed, so response is garbage */
80205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler    VBDEBUG(("TPM: command 0x%x send/receive failed: 0x%x\n",
81205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler             TpmCommandCode(request), result));
8200cc72894f3ce5c3b0d337e424f19da089140237Kees Cook    return result;
83205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  }
84205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  /* Otherwise, use the result code from the response */
85205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  result = TpmReturnCode(response);
8663dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler
871b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler  /* TODO: add paranoia about returned response_length vs. max_length
881b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler   * (and possibly expected length from the response header).  See
891b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler   * crosbug.com/17017 */
901b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler
9163dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler#ifdef EXTRA_LOGGING
9263dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler  VBDEBUG(("TPM: response: %x%x %x%x%x%x %x%x%x%x\n",
9363dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler           response[0], response[1],
9463dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler           response[2], response[3], response[4], response[5],
9563dffcb52b56f27d5315de249d20958b94eed47fRandall Spangler           response[6], response[7], response[8], response[9]));
9650d48feb9e0df6a990cc5890ce14e1398798eeb1Luigi Semenzato#endif
973e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler
98205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  VBDEBUG(("TPM: command 0x%x returned 0x%x\n",
99205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler           TpmCommandCode(request), result));
100205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler
101205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  return result;
10239f66114c03639715cb88774255f066a2d942557Randall Spangler}
10339f66114c03639715cb88774255f066a2d942557Randall Spangler
10439f66114c03639715cb88774255f066a2d942557Randall Spangler
10506fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato/* Sends a TPM command and gets a response.  Returns 0 if success or the TPM
10606fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato * error code if error. In the firmware, waits for the self test to complete
10706fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato * if needed. In the host, reports the first error without retries. */
1083428b4bcd99a6d2e9f8b3e1bdf800d943fbe78c3Luigi Semenzatouint32_t TlclSendReceive(const uint8_t* request, uint8_t* response,
1093428b4bcd99a6d2e9f8b3e1bdf800d943fbe78c3Luigi Semenzato                         int max_length) {
11006fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato  uint32_t result = TlclSendReceiveNoRetry(request, response, max_length);
11106fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato  /* When compiling for the firmware, hide command failures due to the self
11206fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato   * test not having run or completed. */
11306fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato#ifndef CHROMEOS_ENVIRONMENT
11406fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato  /* If the command fails because the self test has not completed, try it
11506fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato   * again after attempting to ensure that the self test has completed. */
11606fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato  if (result == TPM_E_NEEDS_SELFTEST || result == TPM_E_DOING_SELFTEST) {
11706fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato    result = TlclContinueSelfTest();
11806fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato    if (result != TPM_SUCCESS) {
11906fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato      return result;
12006fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato    }
12106fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato#if defined(TPM_BLOCKING_CONTINUESELFTEST) || defined(VB_RECOVERY_MODE)
12206fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato    /* Retry only once */
12306fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato    result = TlclSendReceiveNoRetry(request, response, max_length);
12406fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato#else
12506fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato    /* This needs serious testing.  The TPM specification says: "iii. The
12606fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato     * caller MUST wait for the actions of TPM_ContinueSelfTest to complete
12706fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato     * before reissuing the command C1."  But, if ContinueSelfTest is
12806fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato     * non-blocking, how do we know that the actions have completed other than
12906fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato     * trying again? */
13006fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato    do {
13106fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato      result = TlclSendReceiveNoRetry(request, response, max_length);
13206fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato    } while (result == TPM_E_DOING_SELFTEST);
13306fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato#endif
13406fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato  }
13506fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato#endif  /* ! defined(CHROMEOS_ENVIRONMENT) */
13606fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato  return result;
13706fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato}
13806fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato
13939f66114c03639715cb88774255f066a2d942557Randall Spangler/* Sends a command and returns the error code. */
14089a02c194f1b6da0de7f98784d85e6827c3a1aecLuigi Semenzatostatic uint32_t Send(const uint8_t* command) {
14139f66114c03639715cb88774255f066a2d942557Randall Spangler  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
142205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  return TlclSendReceive(command, response, sizeof(response));
14339f66114c03639715cb88774255f066a2d942557Randall Spangler}
14439f66114c03639715cb88774255f066a2d942557Randall Spangler
14539f66114c03639715cb88774255f066a2d942557Randall Spangler/* Exported functions. */
14639f66114c03639715cb88774255f066a2d942557Randall Spangler
1475d9509cbdee7b9c8dd91ed47d967569dbb9af83dChe-Liang Chiouuint32_t TlclLibInit(void) {
1481b1998dff0002f20b3f27a21e6e79d8951e64684Randall Spangler  return VbExTpmInit();
14939f66114c03639715cb88774255f066a2d942557Randall Spangler}
15039f66114c03639715cb88774255f066a2d942557Randall Spangler
151f9e82e9695d3f208b549cc0208baf24985bbb488Kees Cookuint32_t TlclLibClose(void) {
152f9e82e9695d3f208b549cc0208baf24985bbb488Kees Cook  return VbExTpmClose();
153f9e82e9695d3f208b549cc0208baf24985bbb488Kees Cook}
154f9e82e9695d3f208b549cc0208baf24985bbb488Kees Cook
15539f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclStartup(void) {
1563e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: Startup\n"));
15739f66114c03639715cb88774255f066a2d942557Randall Spangler  return Send(tpm_startup_cmd.buffer);
15839f66114c03639715cb88774255f066a2d942557Randall Spangler}
15939f66114c03639715cb88774255f066a2d942557Randall Spangler
16054992f9d3379c4b048d8da6171f0e578b2db4facLuigi Semenzatouint32_t TlclSaveState(void) {
16154992f9d3379c4b048d8da6171f0e578b2db4facLuigi Semenzato  VBDEBUG(("TPM: SaveState\n"));
16254992f9d3379c4b048d8da6171f0e578b2db4facLuigi Semenzato  return Send(tpm_savestate_cmd.buffer);
16354992f9d3379c4b048d8da6171f0e578b2db4facLuigi Semenzato}
16454992f9d3379c4b048d8da6171f0e578b2db4facLuigi Semenzato
1653da063e3f7612464a41a4c9b2b31fb7eade57a13Luigi Semenzatouint32_t TlclResume(void) {
1663da063e3f7612464a41a4c9b2b31fb7eade57a13Luigi Semenzato  VBDEBUG(("TPM: Resume\n"));
1673da063e3f7612464a41a4c9b2b31fb7eade57a13Luigi Semenzato  return Send(tpm_resume_cmd.buffer);
1683da063e3f7612464a41a4c9b2b31fb7eade57a13Luigi Semenzato}
1693da063e3f7612464a41a4c9b2b31fb7eade57a13Luigi Semenzato
1703e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangleruint32_t TlclSelfTestFull(void) {
1713e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: Self test full\n"));
17239f66114c03639715cb88774255f066a2d942557Randall Spangler  return Send(tpm_selftestfull_cmd.buffer);
17339f66114c03639715cb88774255f066a2d942557Randall Spangler}
17439f66114c03639715cb88774255f066a2d942557Randall Spangler
17539f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclContinueSelfTest(void) {
17606fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
1773e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: Continue self test\n"));
17806fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato  /* Call the No Retry version of SendReceive to avoid recursion. */
17906fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato  return TlclSendReceiveNoRetry(tpm_continueselftest_cmd.buffer,
18006fbb168ac49dd63f427beb3907f3c129d81bf84Luigi Semenzato                                response, sizeof(response));
18139f66114c03639715cb88774255f066a2d942557Randall Spangler}
18239f66114c03639715cb88774255f066a2d942557Randall Spangler
18339f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) {
184553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  struct s_tpm_nv_definespace_cmd cmd;
1853e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: TlclDefineSpace(0x%x, 0x%x, %d)\n", index, perm, size));
186553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  Memcpy(&cmd, &tpm_nv_definespace_cmd, sizeof(cmd));
187553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.index, index);
188553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.perm, perm);
189553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.size, size);
190553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  return Send(cmd.buffer);
19139f66114c03639715cb88774255f066a2d942557Randall Spangler}
19239f66114c03639715cb88774255f066a2d942557Randall Spangler
1934abede35afc8b5ecc8165d5d79f77c203bce51fcRandall Spangleruint32_t TlclWrite(uint32_t index, const void* data, uint32_t length) {
194553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  struct s_tpm_nv_write_cmd cmd;
19539f66114c03639715cb88774255f066a2d942557Randall Spangler  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
19639f66114c03639715cb88774255f066a2d942557Randall Spangler  const int total_length =
19739f66114c03639715cb88774255f066a2d942557Randall Spangler    kTpmRequestHeaderLength + kWriteInfoLength + length;
19839f66114c03639715cb88774255f066a2d942557Randall Spangler
1993e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: TlclWrite(0x%x, %d)\n", index, length));
200553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  Memcpy(&cmd, &tpm_nv_write_cmd, sizeof(cmd));
20132a6526d25d4bf9a1c137fc3d275d1c68935d184Randall Spangler  VbAssert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE);
20250d48feb9e0df6a990cc5890ce14e1398798eeb1Luigi Semenzato  SetTpmCommandSize(cmd.buffer, total_length);
20339f66114c03639715cb88774255f066a2d942557Randall Spangler
204553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.index, index);
205553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.length, length);
206553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  Memcpy(cmd.buffer + tpm_nv_write_cmd.data, data, length);
20739f66114c03639715cb88774255f066a2d942557Randall Spangler
208205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  return TlclSendReceive(cmd.buffer, response, sizeof(response));
20939f66114c03639715cb88774255f066a2d942557Randall Spangler}
21039f66114c03639715cb88774255f066a2d942557Randall Spangler
2114abede35afc8b5ecc8165d5d79f77c203bce51fcRandall Spangleruint32_t TlclRead(uint32_t index, void* data, uint32_t length) {
212553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  struct s_tpm_nv_read_cmd cmd;
21339f66114c03639715cb88774255f066a2d942557Randall Spangler  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
21439f66114c03639715cb88774255f066a2d942557Randall Spangler  uint32_t result_length;
21539f66114c03639715cb88774255f066a2d942557Randall Spangler  uint32_t result;
21639f66114c03639715cb88774255f066a2d942557Randall Spangler
2173e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: TlclRead(0x%x, %d)\n", index, length));
218553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  Memcpy(&cmd, &tpm_nv_read_cmd, sizeof(cmd));
219553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.index, index);
220553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.length, length);
22139f66114c03639715cb88774255f066a2d942557Randall Spangler
222205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  result = TlclSendReceive(cmd.buffer, response, sizeof(response));
22339f66114c03639715cb88774255f066a2d942557Randall Spangler  if (result == TPM_SUCCESS && length > 0) {
22439f66114c03639715cb88774255f066a2d942557Randall Spangler    uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength;
22539f66114c03639715cb88774255f066a2d942557Randall Spangler    FromTpmUint32(nv_read_cursor, &result_length);
22639f66114c03639715cb88774255f066a2d942557Randall Spangler    nv_read_cursor += sizeof(uint32_t);
22739f66114c03639715cb88774255f066a2d942557Randall Spangler    Memcpy(data, nv_read_cursor, result_length);
22839f66114c03639715cb88774255f066a2d942557Randall Spangler  }
22939f66114c03639715cb88774255f066a2d942557Randall Spangler
23039f66114c03639715cb88774255f066a2d942557Randall Spangler  return result;
23139f66114c03639715cb88774255f066a2d942557Randall Spangler}
23239f66114c03639715cb88774255f066a2d942557Randall Spangler
233946370d012a809bba833ff9d37fe0ce86af09860Kees Cookuint32_t TlclPCRRead(uint32_t index, void* data, uint32_t length) {
23425d1c25efb6b3ad5b34905d4f8452b4a58613af1Kees Cook  struct s_tpm_pcr_read_cmd cmd;
235946370d012a809bba833ff9d37fe0ce86af09860Kees Cook  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
236946370d012a809bba833ff9d37fe0ce86af09860Kees Cook  uint32_t result;
237946370d012a809bba833ff9d37fe0ce86af09860Kees Cook
238946370d012a809bba833ff9d37fe0ce86af09860Kees Cook  VBDEBUG(("TPM: TlclPCRRead(0x%x, %d)\n", index, length));
239946370d012a809bba833ff9d37fe0ce86af09860Kees Cook  if (length < kPcrDigestLength) {
240946370d012a809bba833ff9d37fe0ce86af09860Kees Cook    return TPM_E_IOERROR;
241946370d012a809bba833ff9d37fe0ce86af09860Kees Cook  }
242946370d012a809bba833ff9d37fe0ce86af09860Kees Cook  Memcpy(&cmd, &tpm_pcr_read_cmd, sizeof(cmd));
243946370d012a809bba833ff9d37fe0ce86af09860Kees Cook  ToTpmUint32(cmd.buffer + tpm_pcr_read_cmd.pcrNum, index);
244946370d012a809bba833ff9d37fe0ce86af09860Kees Cook
245946370d012a809bba833ff9d37fe0ce86af09860Kees Cook  result = TlclSendReceive(cmd.buffer, response, sizeof(response));
246946370d012a809bba833ff9d37fe0ce86af09860Kees Cook  if (result == TPM_SUCCESS) {
247946370d012a809bba833ff9d37fe0ce86af09860Kees Cook    uint8_t* pcr_read_cursor = response + kTpmResponseHeaderLength;
248946370d012a809bba833ff9d37fe0ce86af09860Kees Cook    Memcpy(data, pcr_read_cursor, kPcrDigestLength);
249946370d012a809bba833ff9d37fe0ce86af09860Kees Cook  }
250946370d012a809bba833ff9d37fe0ce86af09860Kees Cook
251946370d012a809bba833ff9d37fe0ce86af09860Kees Cook  return result;
252946370d012a809bba833ff9d37fe0ce86af09860Kees Cook}
253946370d012a809bba833ff9d37fe0ce86af09860Kees Cook
25439f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclWriteLock(uint32_t index) {
2553e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: Write lock 0x%x\n", index));
25639f66114c03639715cb88774255f066a2d942557Randall Spangler  return TlclWrite(index, NULL, 0);
25739f66114c03639715cb88774255f066a2d942557Randall Spangler}
25839f66114c03639715cb88774255f066a2d942557Randall Spangler
25939f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclReadLock(uint32_t index) {
2603e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: Read lock 0x%x\n", index));
26139f66114c03639715cb88774255f066a2d942557Randall Spangler  return TlclRead(index, NULL, 0);
26239f66114c03639715cb88774255f066a2d942557Randall Spangler}
26339f66114c03639715cb88774255f066a2d942557Randall Spangler
26439f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclAssertPhysicalPresence(void) {
2653e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: Asserting physical presence\n"));
26639f66114c03639715cb88774255f066a2d942557Randall Spangler  return Send(tpm_ppassert_cmd.buffer);
26739f66114c03639715cb88774255f066a2d942557Randall Spangler}
26839f66114c03639715cb88774255f066a2d942557Randall Spangler
2691d83dd1ba5b825407a8e17972c54577d14ba173dLuigi Semenzatouint32_t TlclPhysicalPresenceCMDEnable(void) {
2701d83dd1ba5b825407a8e17972c54577d14ba173dLuigi Semenzato  VBDEBUG(("TPM: Enable the physical presence command\n"));
2711d83dd1ba5b825407a8e17972c54577d14ba173dLuigi Semenzato  return Send(tpm_ppenable_cmd.buffer);
2721d83dd1ba5b825407a8e17972c54577d14ba173dLuigi Semenzato}
2731d83dd1ba5b825407a8e17972c54577d14ba173dLuigi Semenzato
274377557fcb260c9b41abc36ebba5759336436e59cLuigi Semenzatouint32_t TlclFinalizePhysicalPresence(void) {
275377557fcb260c9b41abc36ebba5759336436e59cLuigi Semenzato  VBDEBUG(("TPM: Enable PP cmd, disable HW pp, and set lifetime lock\n"));
276377557fcb260c9b41abc36ebba5759336436e59cLuigi Semenzato  return Send(tpm_finalizepp_cmd.buffer);
277377557fcb260c9b41abc36ebba5759336436e59cLuigi Semenzato}
278377557fcb260c9b41abc36ebba5759336436e59cLuigi Semenzato
27939f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclAssertPhysicalPresenceResult(void) {
28039f66114c03639715cb88774255f066a2d942557Randall Spangler  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
281205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  return TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response));
28239f66114c03639715cb88774255f066a2d942557Randall Spangler}
28339f66114c03639715cb88774255f066a2d942557Randall Spangler
28439f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclLockPhysicalPresence(void) {
2853e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: Lock physical presence\n"));
28639f66114c03639715cb88774255f066a2d942557Randall Spangler  return Send(tpm_pplock_cmd.buffer);
28739f66114c03639715cb88774255f066a2d942557Randall Spangler}
28839f66114c03639715cb88774255f066a2d942557Randall Spangler
28939f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclSetNvLocked(void) {
2903e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: Set NV locked\n"));
29139f66114c03639715cb88774255f066a2d942557Randall Spangler  return TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0);
29239f66114c03639715cb88774255f066a2d942557Randall Spangler}
29339f66114c03639715cb88774255f066a2d942557Randall Spangler
29439f66114c03639715cb88774255f066a2d942557Randall Spanglerint TlclIsOwned(void) {
29539f66114c03639715cb88774255f066a2d942557Randall Spangler  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE];
29639f66114c03639715cb88774255f066a2d942557Randall Spangler  uint32_t result;
297377557fcb260c9b41abc36ebba5759336436e59cLuigi Semenzato  result = TlclSendReceive(tpm_readpubek_cmd.buffer,
298377557fcb260c9b41abc36ebba5759336436e59cLuigi Semenzato                           response, sizeof(response));
29939f66114c03639715cb88774255f066a2d942557Randall Spangler  return (result != TPM_SUCCESS);
30039f66114c03639715cb88774255f066a2d942557Randall Spangler}
30139f66114c03639715cb88774255f066a2d942557Randall Spangler
30239f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclForceClear(void) {
3033e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: Force clear\n"));
30439f66114c03639715cb88774255f066a2d942557Randall Spangler  return Send(tpm_forceclear_cmd.buffer);
30539f66114c03639715cb88774255f066a2d942557Randall Spangler}
30639f66114c03639715cb88774255f066a2d942557Randall Spangler
30739f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclSetEnable(void) {
3083e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: Enabling TPM\n"));
30939f66114c03639715cb88774255f066a2d942557Randall Spangler  return Send(tpm_physicalenable_cmd.buffer);
31039f66114c03639715cb88774255f066a2d942557Randall Spangler}
31139f66114c03639715cb88774255f066a2d942557Randall Spangler
31239f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclClearEnable(void) {
3133e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: Disabling TPM\n"));
31439f66114c03639715cb88774255f066a2d942557Randall Spangler  return Send(tpm_physicaldisable_cmd.buffer);
31539f66114c03639715cb88774255f066a2d942557Randall Spangler}
31639f66114c03639715cb88774255f066a2d942557Randall Spangler
31739f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclSetDeactivated(uint8_t flag) {
318553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  struct s_tpm_physicalsetdeactivated_cmd cmd;
3193e1081fb71385d72fd3a522599c35b516dda7a37Randall Spangler  VBDEBUG(("TPM: SetDeactivated(%d)\n", flag));
32050d48feb9e0df6a990cc5890ce14e1398798eeb1Luigi Semenzato  Memcpy(&cmd, &tpm_physicalsetdeactivated_cmd, sizeof(cmd));
321553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  *(cmd.buffer + cmd.deactivated) = flag;
322553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  return Send(cmd.buffer);
32339f66114c03639715cb88774255f066a2d942557Randall Spangler}
32439f66114c03639715cb88774255f066a2d942557Randall Spangler
3255896b9664d088699e246de964a7c374af663a34eLuigi Semenzatouint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS* pflags) {
32639f66114c03639715cb88774255f066a2d942557Randall Spangler  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
32739f66114c03639715cb88774255f066a2d942557Randall Spangler  uint32_t size;
3285896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  uint32_t result =
3295896b9664d088699e246de964a7c374af663a34eLuigi Semenzato    TlclSendReceive(tpm_getflags_cmd.buffer, response, sizeof(response));
330205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  if (result != TPM_SUCCESS)
33139f66114c03639715cb88774255f066a2d942557Randall Spangler    return result;
33239f66114c03639715cb88774255f066a2d942557Randall Spangler  FromTpmUint32(response + kTpmResponseHeaderLength, &size);
3334c3b4ea3d810a2ed907078a6b9a379442aaf6defBill Richardson  /* TODO(crbug.com/379255): This fails. Find out why.
3344c3b4ea3d810a2ed907078a6b9a379442aaf6defBill Richardson   * VbAssert(size == sizeof(TPM_PERMANENT_FLAGS));
3354c3b4ea3d810a2ed907078a6b9a379442aaf6defBill Richardson   */
3365896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  Memcpy(pflags,
3375896b9664d088699e246de964a7c374af663a34eLuigi Semenzato         response + kTpmResponseHeaderLength + sizeof(size),
3385896b9664d088699e246de964a7c374af663a34eLuigi Semenzato         sizeof(TPM_PERMANENT_FLAGS));
3395896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  return result;
3405896b9664d088699e246de964a7c374af663a34eLuigi Semenzato}
3415896b9664d088699e246de964a7c374af663a34eLuigi Semenzato
3425896b9664d088699e246de964a7c374af663a34eLuigi Semenzatouint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS* vflags) {
3435896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
3445896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  uint32_t size;
3455896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  uint32_t result =
3465896b9664d088699e246de964a7c374af663a34eLuigi Semenzato    TlclSendReceive(tpm_getstclearflags_cmd.buffer, response, sizeof(response));
3475896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  if (result != TPM_SUCCESS)
3485896b9664d088699e246de964a7c374af663a34eLuigi Semenzato    return result;
3495896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  FromTpmUint32(response + kTpmResponseHeaderLength, &size);
3505896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  /* Ugly assertion, but the struct is padded up by one byte. */
3514c3b4ea3d810a2ed907078a6b9a379442aaf6defBill Richardson  /* TODO(crbug.com/379255): This fails. Find out why.
3524c3b4ea3d810a2ed907078a6b9a379442aaf6defBill Richardson   * VbAssert(size == 7 && sizeof(TPM_STCLEAR_FLAGS) - 1 == 7);
3534c3b4ea3d810a2ed907078a6b9a379442aaf6defBill Richardson   */
3545896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  Memcpy(vflags,
3555896b9664d088699e246de964a7c374af663a34eLuigi Semenzato         response + kTpmResponseHeaderLength + sizeof(size),
3565896b9664d088699e246de964a7c374af663a34eLuigi Semenzato         sizeof(TPM_STCLEAR_FLAGS));
35739f66114c03639715cb88774255f066a2d942557Randall Spangler  return result;
35839f66114c03639715cb88774255f066a2d942557Randall Spangler}
35939f66114c03639715cb88774255f066a2d942557Randall Spangler
3605896b9664d088699e246de964a7c374af663a34eLuigi Semenzatouint32_t TlclGetFlags(uint8_t* disable,
3615896b9664d088699e246de964a7c374af663a34eLuigi Semenzato                      uint8_t* deactivated,
3625896b9664d088699e246de964a7c374af663a34eLuigi Semenzato                      uint8_t *nvlocked) {
3635896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  TPM_PERMANENT_FLAGS pflags;
3645896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  uint32_t result = TlclGetPermanentFlags(&pflags);
3655896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  if (result == TPM_SUCCESS) {
3665896b9664d088699e246de964a7c374af663a34eLuigi Semenzato    if (disable)
3675896b9664d088699e246de964a7c374af663a34eLuigi Semenzato      *disable = pflags.disable;
3685896b9664d088699e246de964a7c374af663a34eLuigi Semenzato    if (deactivated)
3695896b9664d088699e246de964a7c374af663a34eLuigi Semenzato      *deactivated = pflags.deactivated;
3705896b9664d088699e246de964a7c374af663a34eLuigi Semenzato    if (nvlocked)
3715896b9664d088699e246de964a7c374af663a34eLuigi Semenzato      *nvlocked = pflags.nvLocked;
3725896b9664d088699e246de964a7c374af663a34eLuigi Semenzato    VBDEBUG(("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n",
3735896b9664d088699e246de964a7c374af663a34eLuigi Semenzato             pflags.disable, pflags.deactivated, pflags.nvLocked));
3745896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  }
3755896b9664d088699e246de964a7c374af663a34eLuigi Semenzato  return result;
3765896b9664d088699e246de964a7c374af663a34eLuigi Semenzato}
3771d83dd1ba5b825407a8e17972c54577d14ba173dLuigi Semenzato
37839f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclSetGlobalLock(void) {
37939f66114c03639715cb88774255f066a2d942557Randall Spangler  uint32_t x;
380205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  VBDEBUG(("TPM: Set global lock\n"));
38139f66114c03639715cb88774255f066a2d942557Randall Spangler  return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0);
38239f66114c03639715cb88774255f066a2d942557Randall Spangler}
38339f66114c03639715cb88774255f066a2d942557Randall Spangler
384b64faaa7f4167344765eb32baebb0aa01a03bc29Gaurav Shahuint32_t TlclExtend(int pcr_num, const uint8_t* in_digest,
385b64faaa7f4167344765eb32baebb0aa01a03bc29Gaurav Shah                    uint8_t* out_digest) {
386553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  struct s_tpm_extend_cmd cmd;
38739f66114c03639715cb88774255f066a2d942557Randall Spangler  uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength];
388205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  uint32_t result;
389ada3fa9ee606c07d7675e235506522fa332c1747Randall Spangler
390ada3fa9ee606c07d7675e235506522fa332c1747Randall Spangler  Memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd));
391553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  ToTpmUint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num);
392553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  Memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength);
393205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler
394205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  result = TlclSendReceive(cmd.buffer, response, sizeof(response));
395205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  if (result != TPM_SUCCESS)
396205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler    return result;
397205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler
39839f66114c03639715cb88774255f066a2d942557Randall Spangler  Memcpy(out_digest, response + kTpmResponseHeaderLength, kPcrDigestLength);
399205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  return result;
40039f66114c03639715cb88774255f066a2d942557Randall Spangler}
40139f66114c03639715cb88774255f066a2d942557Randall Spangler
40239f66114c03639715cb88774255f066a2d942557Randall Spangleruint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) {
403553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  struct s_tpm_getpermissions_cmd cmd;
40439f66114c03639715cb88774255f066a2d942557Randall Spangler  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
40539f66114c03639715cb88774255f066a2d942557Randall Spangler  uint8_t* nvdata;
40639f66114c03639715cb88774255f066a2d942557Randall Spangler  uint32_t result;
40739f66114c03639715cb88774255f066a2d942557Randall Spangler  uint32_t size;
40839f66114c03639715cb88774255f066a2d942557Randall Spangler
409553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  Memcpy(&cmd, &tpm_getpermissions_cmd, sizeof(cmd));
410553d00ec86fed95888dcaff1b911ce8c444d03fdGaurav Shah  ToTpmUint32(cmd.buffer + tpm_getpermissions_cmd.index, index);
411205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  result = TlclSendReceive(cmd.buffer, response, sizeof(response));
412205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler  if (result != TPM_SUCCESS)
41339f66114c03639715cb88774255f066a2d942557Randall Spangler    return result;
414205190d4ae8080298d9d1b580dd95c885f2af42cRandall Spangler
41539f66114c03639715cb88774255f066a2d942557Randall Spangler  nvdata = response + kTpmResponseHeaderLength + sizeof(size);
41639f66114c03639715cb88774255f066a2d942557Randall Spangler  FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions);
41739f66114c03639715cb88774255f066a2d942557Randall Spangler  return result;
41839f66114c03639715cb88774255f066a2d942557Randall Spangler}
419f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook
4208b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cookuint32_t TlclGetOwnership(uint8_t* owned) {
4218b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
4228b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook  uint32_t size;
4238b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook  uint32_t result =
4248b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook    TlclSendReceive(tpm_getownership_cmd.buffer, response, sizeof(response));
4258b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook  if (result != TPM_SUCCESS)
4268b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook    return result;
4278b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook  FromTpmUint32(response + kTpmResponseHeaderLength, &size);
4284c3b4ea3d810a2ed907078a6b9a379442aaf6defBill Richardson  /* TODO(crbug.com/379255): This fails. Find out why.
4294c3b4ea3d810a2ed907078a6b9a379442aaf6defBill Richardson   * VbAssert(size == sizeof(*owned));
4304c3b4ea3d810a2ed907078a6b9a379442aaf6defBill Richardson   */
4318b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook  Memcpy(owned,
4328b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook         response + kTpmResponseHeaderLength + sizeof(size),
4338b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook         sizeof(*owned));
4348b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook  return result;
4358b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook}
4368b6da26a6e5978a43233f7a43c7bab5889d3817aKees Cook
437f0605cbdc36f58829a908a3333e438c565c8c7afKees Cookuint32_t TlclGetRandom(uint8_t* data, uint32_t length, uint32_t *size) {
438f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  struct s_tpm_get_random_cmd cmd;
439f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
440f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  uint32_t result;
441f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook
442f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  VBDEBUG(("TPM: TlclGetRandom(%d)\n", length));
443f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  Memcpy(&cmd, &tpm_get_random_cmd, sizeof(cmd));
444f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  ToTpmUint32(cmd.buffer + tpm_get_random_cmd.bytesRequested, length);
445f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  /* There must be room in the response buffer for the bytes. */
446f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  if (length > TPM_LARGE_ENOUGH_COMMAND_SIZE - kTpmResponseHeaderLength
447f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook               - sizeof(uint32_t)) {
448f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook    return TPM_E_IOERROR;
449f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  }
450f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook
451f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  result = TlclSendReceive(cmd.buffer, response, sizeof(response));
452f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  if (result == TPM_SUCCESS) {
453f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook    uint8_t* get_random_cursor;
454f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook    FromTpmUint32(response + kTpmResponseHeaderLength, size);
455f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook
456f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook    /* There must be room in the target buffer for the bytes. */
457f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook    if (*size > length) {
458f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook      return TPM_E_RESPONSE_TOO_LARGE;
459f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook    }
460f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook    get_random_cursor = response + kTpmResponseHeaderLength
461f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook                                 + sizeof(uint32_t);
462f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook    Memcpy(data, get_random_cursor, *size);
463f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  }
464f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook
465f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook  return result;
466f0605cbdc36f58829a908a3333e438c565c8c7afKees Cook}
467