blob: d18c1d2c40bef790ba384f213e59ae18fe545442 [file] [log] [blame]
/* Copyright (c) 2011 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.
*
* Linux-specific access to the TPM.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "trunks_internal.h"
#define TPM_DEVICE_PATH "/dev/tpm0"
/* The file descriptor for the TPM device.
*/
static int tpm_fd = -1;
void TtlError(const char *format, ...) {
va_list ap;
va_start(ap, format);
fprintf(stderr, "ERROR: ");
vfprintf(stderr, format, ap);
va_end(ap);
fprintf(stderr, "\n");
exit(1);
}
#ifdef TESTING
uint8_t TtlTestCommandBuffer[4096];
#endif
/* Executes a command on the TPM.
*/
uint32_t TtlExecute(uint8_t* buffer, uint32_t cmd_len, uint32_t buf_len,
uint32_t* read_bytes) {
#ifdef TESTING
memcpy(TtlTestCommandBuffer, buffer, cmd_len);
#else
if (cmd_len > TPM_MAX_COMMAND_LENGTH) {
TtlError("invalid command length %d for command 0x%x", cmd_len, buffer[9]);
} else if (tpm_fd < 0) {
TtlError("the TPM device was not opened");
} else {
int n = write(tpm_fd, buffer, cmd_len);
if (n != cmd_len) {
TtlError("write failure to TPM device: %s", strerror(errno));
}
n = read(tpm_fd, buffer, buf_len);
if (n == 0) {
TtlError("null read from TPM device");
} else if (n < 0) {
TtlError("read failure from TPM device: %s", strerror(errno));
}
*read_bytes = n;
}
#endif
return TPM_SUCCESS;
}
uint32_t TtlCloseDevice(void) {
if (tpm_fd != -1) {
close(tpm_fd);
tpm_fd = -1;
}
return 0;
}
uint32_t TtlOpenDevice(void) {
char* device_path;
if (tpm_fd >= 0)
return 0; /* Already open */
device_path = getenv("TPM_DEVICE_PATH");
if (device_path == NULL) {
device_path = TPM_DEVICE_PATH;
}
tpm_fd = open(device_path, O_RDWR);
if (tpm_fd < 0) {
TtlError("TPM: Cannot open TPM device %s: %s",
device_path, strerror(errno));
}
return 0;
}