| Index: firmware/stub/tpm_lite_stub.c
|
| diff --git a/firmware/stub/tpm_lite_stub.c b/firmware/stub/tpm_lite_stub.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ee1cbf13664c1d7b2e9d1b353cd3fca65f0d7b65
|
| --- /dev/null
|
| +++ b/firmware/stub/tpm_lite_stub.c
|
| @@ -0,0 +1,178 @@
|
| +/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + *
|
| + * Stub implementations of utility functions which call their linux-specific
|
| + * equivalents.
|
| + */
|
| +
|
| +#define _STUB_IMPLEMENTATION_
|
| +#include "tlcl.h"
|
| +#include "tlcl_internal.h"
|
| +#include "utility.h"
|
| +
|
| +#include <errno.h>
|
| +#include <fcntl.h>
|
| +#include <stdarg.h>
|
| +#include <stdio.h>
|
| +#include <string.h>
|
| +#include <sys/time.h>
|
| +#include <sys/types.h>
|
| +#include <sys/stat.h>
|
| +#include <unistd.h>
|
| +#include <tss/tcs.h>
|
| +#include "tpmextras.h"
|
| +#define TPM_DEVICE_PATH "/dev/tpm0"
|
| +
|
| +/* TODO: these functions should pass errors back rather than returning void */
|
| +/* TODO: if the only callers to these are just wrappers, should just
|
| + * remove the wrappers and call us directly. */
|
| +
|
| +
|
| +/* The file descriptor for the TPM device.
|
| + */
|
| +static int tpm_fd = -1;
|
| +
|
| +
|
| +/* Print |n| bytes from array |a|, with newlines.
|
| + */
|
| +POSSIBLY_UNUSED static void PrintBytes(uint8_t* a, int n) {
|
| + int i;
|
| + for (i = 0; i < n; i++) {
|
| + VBDEBUG(("%02x ", a[i]));
|
| + if ((i + 1) % 16 == 0) {
|
| + VBDEBUG(("\n"));
|
| + }
|
| + }
|
| + if (i % 16 != 0) {
|
| + VBDEBUG(("\n"));
|
| + }
|
| +}
|
| +
|
| +
|
| +/* Executes a command on the TPM.
|
| + */
|
| +static void TpmExecute(const uint8_t *in, const uint32_t in_len,
|
| + uint8_t *out, uint32_t *pout_len) {
|
| + uint8_t response[TPM_MAX_COMMAND_SIZE];
|
| + if (in_len <= 0) {
|
| + error("invalid command length %d\n", in_len);
|
| + } else if (tpm_fd < 0) {
|
| + error("the TPM device was not opened. Forgot to call TlclLibInit?\n");
|
| + } else {
|
| + int n = write(tpm_fd, in, in_len);
|
| + if (n != in_len) {
|
| + error("write failure to TPM device: %s\n", strerror(errno));
|
| + }
|
| + n = read(tpm_fd, response, sizeof(response));
|
| + if (n == 0) {
|
| + error("null read from TPM device\n");
|
| + } else if (n < 0) {
|
| + error("read failure from TPM device: %s\n", strerror(errno));
|
| + } else {
|
| + if (n > *pout_len) {
|
| + error("TPM response too long for output buffer\n");
|
| + } else {
|
| + *pout_len = n;
|
| + Memcpy(out, response, n);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +/* Gets the tag field of a TPM command.
|
| + */
|
| +POSSIBLY_UNUSED static INLINE int TpmTag(uint8_t* buffer) {
|
| + uint16_t tag;
|
| + FromTpmUint16(buffer, &tag);
|
| + return (int) tag;
|
| +}
|
| +
|
| +
|
| +/* Gets the size field of a TPM command.
|
| + */
|
| +POSSIBLY_UNUSED static INLINE int TpmResponseSize(const uint8_t* buffer) {
|
| + uint32_t size;
|
| + FromTpmUint32(buffer + sizeof(uint16_t), &size);
|
| + return (int) size;
|
| +}
|
| +
|
| +
|
| +void TlclStubInit(void) {
|
| + TlclOpenDevice();
|
| +}
|
| +
|
| +
|
| +void TlclCloseDevice(void) {
|
| + close(tpm_fd);
|
| + tpm_fd = -1;
|
| +}
|
| +
|
| +
|
| +void TlclOpenDevice(void) {
|
| + if (tpm_fd >= 0)
|
| + return; /* Already open */
|
| +
|
| + tpm_fd = open(TPM_DEVICE_PATH, O_RDWR);
|
| + if (tpm_fd < 0) {
|
| + error("cannot open TPM device %s: %s\n", TPM_DEVICE_PATH, strerror(errno));
|
| + }
|
| +}
|
| +
|
| +
|
| +void TlclStubSendReceive(uint8_t* request, int request_length,
|
| + uint8_t* response, int max_length) {
|
| + /*
|
| + * In a real firmware implementation, this function should contain
|
| + * the equivalent API call for the firmware TPM driver which takes a
|
| + * raw sequence of bytes as input command and a pointer to the
|
| + * output buffer for putting in the results.
|
| + *
|
| + * For EFI firmwares, this can make use of the EFI TPM driver as
|
| + * follows (based on page 16, of TCG EFI Protocol Specs Version 1.20
|
| + * availaible from the TCG website):
|
| + *
|
| + * EFI_STATUS status;
|
| + * status = TcgProtocol->EFI_TCG_PASS_THROUGH_TO_TPM(TpmCommandSize(request),
|
| + * request,
|
| + * max_length,
|
| + * response);
|
| + * // Error checking depending on the value of the status above
|
| + */
|
| + uint32_t response_length = max_length;
|
| + int tag, response_tag;
|
| +
|
| + struct timeval before, after;
|
| + gettimeofday(&before, NULL);
|
| + TpmExecute(request, request_length, response, &response_length);
|
| + gettimeofday(&after, NULL);
|
| +
|
| +#ifdef VBOOT_DEBUG
|
| + {
|
| + int x = request_length;
|
| + int y = response_length;
|
| + VBDEBUG(("request (%d bytes): ", x));
|
| + PrintBytes(request, 10);
|
| + PrintBytes(request + 10, x - 10);
|
| + VBDEBUG(("response (%d bytes): ", y));
|
| + PrintBytes(response, 10);
|
| + PrintBytes(response + 10, y - 10);
|
| + VBDEBUG(("execution time: %dms\n",
|
| + (int) ((after.tv_sec - before.tv_sec) * 1000 +
|
| + (after.tv_usec - before.tv_usec) / 1000)));
|
| + }
|
| +#endif
|
| +
|
| + /* sanity checks */
|
| + tag = TpmTag(request);
|
| + response_tag = TpmTag(response);
|
| + assert(
|
| + (tag == TPM_TAG_RQU_COMMAND &&
|
| + response_tag == TPM_TAG_RSP_COMMAND) ||
|
| + (tag == TPM_TAG_RQU_AUTH1_COMMAND &&
|
| + response_tag == TPM_TAG_RSP_AUTH1_COMMAND) ||
|
| + (tag == TPM_TAG_RQU_AUTH2_COMMAND &&
|
| + response_tag == TPM_TAG_RSP_AUTH2_COMMAND));
|
| + assert(response_length == TpmResponseSize(response));
|
| +}
|
|
|