mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
tpm: disociate TPMv1.x specific and generic code
There are no changes in this commit but a new organization of the code
as follow.
* cmd/ directory:
> move existing code from cmd/tpm.c in cmd/tpm-common.c
> move specific code in cmd/tpm-v1.c
> create a specific header file with generic definitions for
commands only called cmd/tpm-user-utils.h
* lib/ directory:
> move existing code from lib/tpm.c in lib/tpm-common.c
> move specific code in lib/tpm-v1.c
> create a specific header file with generic definitions for
the library itself called lib/tpm-utils.h
* include/ directory:
> move existing code from include/tpm.h in include/tpm-common.h
> move specific code in include/tpm-v1.h
Code designated as 'common' is compiled if TPM are used. Code designated
as 'specific' is compiled only if the right specification has been
selected.
All files include tpm-common.h.
Files in cmd/ include tpm-user-utils.h.
Files in lib/ include tpm-utils.h.
Depending on the specification, files may include either (not both)
tpm-v1.h or tpm-v2.h.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
[trini: Fix a few more cases of tpm.h -> tpm-v1.h, some Kconfig logic]
Signed-off-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
@@ -39,7 +39,8 @@ obj-$(CONFIG_PHYSMEM) += physmem.o
|
||||
obj-y += qsort.o
|
||||
obj-y += rc4.o
|
||||
obj-$(CONFIG_SUPPORT_EMMC_RPMB) += sha256.o
|
||||
obj-$(CONFIG_TPM_V1) += tpm.o
|
||||
obj-$(CONFIG_TPM) += tpm-common.o
|
||||
obj-$(CONFIG_TPM_V1) += tpm-v1.o
|
||||
obj-$(CONFIG_RBTREE) += rbtree.o
|
||||
obj-$(CONFIG_BITREVERSE) += bitrev.o
|
||||
obj-y += list_sort.o
|
||||
|
||||
188
lib/tpm-common.c
Normal file
188
lib/tpm-common.c
Normal file
@@ -0,0 +1,188 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2013 The Chromium OS Authors.
|
||||
* Coypright (c) 2013 Guntermann & Drunck GmbH
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <tpm-common.h>
|
||||
#include "tpm-utils.h"
|
||||
|
||||
int pack_byte_string(u8 *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
size_t offset = 0, length = 0;
|
||||
u8 *data = NULL;
|
||||
u32 value = 0;
|
||||
|
||||
va_start(args, format);
|
||||
for (; *format; format++) {
|
||||
switch (*format) {
|
||||
case 'b':
|
||||
offset = va_arg(args, size_t);
|
||||
value = va_arg(args, int);
|
||||
length = 1;
|
||||
break;
|
||||
case 'w':
|
||||
offset = va_arg(args, size_t);
|
||||
value = va_arg(args, int);
|
||||
length = 2;
|
||||
break;
|
||||
case 'd':
|
||||
offset = va_arg(args, size_t);
|
||||
value = va_arg(args, u32);
|
||||
length = 4;
|
||||
break;
|
||||
case 's':
|
||||
offset = va_arg(args, size_t);
|
||||
data = va_arg(args, u8 *);
|
||||
length = va_arg(args, u32);
|
||||
break;
|
||||
default:
|
||||
debug("Couldn't recognize format string\n");
|
||||
va_end(args);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset + length > size) {
|
||||
va_end(args);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (*format) {
|
||||
case 'b':
|
||||
str[offset] = value;
|
||||
break;
|
||||
case 'w':
|
||||
put_unaligned_be16(value, str + offset);
|
||||
break;
|
||||
case 'd':
|
||||
put_unaligned_be32(value, str + offset);
|
||||
break;
|
||||
case 's':
|
||||
memcpy(str + offset, data, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unpack_byte_string(const u8 *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
size_t offset = 0, length = 0;
|
||||
u8 *ptr8 = NULL;
|
||||
u16 *ptr16 = NULL;
|
||||
u32 *ptr32 = NULL;
|
||||
|
||||
va_start(args, format);
|
||||
for (; *format; format++) {
|
||||
switch (*format) {
|
||||
case 'b':
|
||||
offset = va_arg(args, size_t);
|
||||
ptr8 = va_arg(args, u8 *);
|
||||
length = 1;
|
||||
break;
|
||||
case 'w':
|
||||
offset = va_arg(args, size_t);
|
||||
ptr16 = va_arg(args, u16 *);
|
||||
length = 2;
|
||||
break;
|
||||
case 'd':
|
||||
offset = va_arg(args, size_t);
|
||||
ptr32 = va_arg(args, u32 *);
|
||||
length = 4;
|
||||
break;
|
||||
case 's':
|
||||
offset = va_arg(args, size_t);
|
||||
ptr8 = va_arg(args, u8 *);
|
||||
length = va_arg(args, u32);
|
||||
break;
|
||||
default:
|
||||
va_end(args);
|
||||
debug("Couldn't recognize format string\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset + length > size) {
|
||||
va_end(args);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (*format) {
|
||||
case 'b':
|
||||
*ptr8 = str[offset];
|
||||
break;
|
||||
case 'w':
|
||||
*ptr16 = get_unaligned_be16(str + offset);
|
||||
break;
|
||||
case 'd':
|
||||
*ptr32 = get_unaligned_be32(str + offset);
|
||||
break;
|
||||
case 's':
|
||||
memcpy(ptr8, str + offset, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 tpm_command_size(const void *command)
|
||||
{
|
||||
const size_t command_size_offset = 2;
|
||||
|
||||
return get_unaligned_be32(command + command_size_offset);
|
||||
}
|
||||
|
||||
u32 tpm_return_code(const void *response)
|
||||
{
|
||||
const size_t return_code_offset = 6;
|
||||
|
||||
return get_unaligned_be32(response + return_code_offset);
|
||||
}
|
||||
|
||||
u32 tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int err, ret;
|
||||
u8 response_buffer[COMMAND_BUFFER_SIZE];
|
||||
size_t response_length;
|
||||
|
||||
if (response) {
|
||||
response_length = *size_ptr;
|
||||
} else {
|
||||
response = response_buffer;
|
||||
response_length = sizeof(response_buffer);
|
||||
}
|
||||
|
||||
ret = uclass_first_device_err(UCLASS_TPM, &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
err = tpm_xfer(dev, command, tpm_command_size(command),
|
||||
response, &response_length);
|
||||
|
||||
if (err < 0)
|
||||
return TPM_LIB_ERROR;
|
||||
if (size_ptr)
|
||||
*size_ptr = response_length;
|
||||
|
||||
return tpm_return_code(response);
|
||||
}
|
||||
|
||||
int tpm_init(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int err;
|
||||
|
||||
err = uclass_first_device_err(UCLASS_TPM, &dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return tpm_open(dev);
|
||||
}
|
||||
95
lib/tpm-utils.h
Normal file
95
lib/tpm-utils.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (c) 2013 The Chromium OS Authors.
|
||||
* Coypright (c) 2013 Guntermann & Drunck GmbH
|
||||
*/
|
||||
|
||||
#ifndef __TPM_UTILS_H
|
||||
#define __TPM_UTILS_H
|
||||
|
||||
#define COMMAND_BUFFER_SIZE 256
|
||||
|
||||
/* Internal error of TPM command library */
|
||||
#define TPM_LIB_ERROR ((u32)~0u)
|
||||
|
||||
/**
|
||||
* tpm_open() - Request access to locality 0 for the caller
|
||||
*
|
||||
* After all commands have been completed the caller is supposed to
|
||||
* call tpm_close().
|
||||
*
|
||||
* Returns 0 on success, -ve on failure.
|
||||
*/
|
||||
int tpm_open(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* tpm_close() - Close the current session
|
||||
*
|
||||
* Releasing the locked locality. Returns 0 on success, -ve 1 on
|
||||
* failure (in case lock removal did not succeed).
|
||||
*/
|
||||
int tpm_close(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* Pack data into a byte string. The data types are specified in
|
||||
* the format string: 'b' means unsigned byte, 'w' unsigned word,
|
||||
* 'd' unsigned double word, and 's' byte string. The data are a
|
||||
* series of offsets and values (for type byte string there are also
|
||||
* lengths). The data values are packed into the byte string
|
||||
* sequentially, and so a latter value could over-write a former
|
||||
* value.
|
||||
*
|
||||
* @param str output string
|
||||
* @param size size of output string
|
||||
* @param format format string
|
||||
* @param ... data points
|
||||
* @return 0 on success, non-0 on error
|
||||
*/
|
||||
int pack_byte_string(u8 *str, size_t size, const char *format, ...);
|
||||
|
||||
/**
|
||||
* Unpack data from a byte string. The data types are specified in
|
||||
* the format string: 'b' means unsigned byte, 'w' unsigned word,
|
||||
* 'd' unsigned double word, and 's' byte string. The data are a
|
||||
* series of offsets and pointers (for type byte string there are also
|
||||
* lengths).
|
||||
*
|
||||
* @param str output string
|
||||
* @param size size of output string
|
||||
* @param format format string
|
||||
* @param ... data points
|
||||
* @return 0 on success, non-0 on error
|
||||
*/
|
||||
int unpack_byte_string(const u8 *str, size_t size, const char *format, ...);
|
||||
|
||||
/**
|
||||
* Get TPM command size.
|
||||
*
|
||||
* @param command byte string of TPM command
|
||||
* @return command size of the TPM command
|
||||
*/
|
||||
u32 tpm_command_size(const void *command);
|
||||
|
||||
/**
|
||||
* Get TPM response return code, which is one of TPM_RESULT values.
|
||||
*
|
||||
* @param response byte string of TPM response
|
||||
* @return return code of the TPM response
|
||||
*/
|
||||
u32 tpm_return_code(const void *response);
|
||||
|
||||
/**
|
||||
* Send a TPM command and return response's return code, and optionally
|
||||
* return response to caller.
|
||||
*
|
||||
* @param command byte string of TPM command
|
||||
* @param response output buffer for TPM response, or NULL if the
|
||||
* caller does not care about it
|
||||
* @param size_ptr output buffer size (input parameter) and TPM
|
||||
* response length (output parameter); this parameter
|
||||
* is a bidirectional
|
||||
* @return return code of the TPM response
|
||||
*/
|
||||
u32 tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr);
|
||||
|
||||
#endif /* __TPM_UTILS_H */
|
||||
@@ -6,26 +6,11 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <tpm.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <u-boot/sha1.h>
|
||||
|
||||
/* Internal error of TPM command library */
|
||||
#define TPM_LIB_ERROR ((u32)~0u)
|
||||
|
||||
/* Useful constants */
|
||||
enum {
|
||||
COMMAND_BUFFER_SIZE = 256,
|
||||
TPM_REQUEST_HEADER_LENGTH = 10,
|
||||
TPM_RESPONSE_HEADER_LENGTH = 10,
|
||||
PCR_DIGEST_LENGTH = 20,
|
||||
DIGEST_LENGTH = 20,
|
||||
TPM_REQUEST_AUTH_LENGTH = 45,
|
||||
TPM_RESPONSE_AUTH_LENGTH = 41,
|
||||
/* some max lengths, valid for RSA keys <= 2048 bits */
|
||||
TPM_KEY12_MAX_LENGTH = 618,
|
||||
TPM_PUBKEY_MAX_LENGTH = 288,
|
||||
};
|
||||
#include <tpm-common.h>
|
||||
#include <tpm-v1.h>
|
||||
#include "tpm-utils.h"
|
||||
|
||||
#ifdef CONFIG_TPM_AUTH_SESSIONS
|
||||
|
||||
@@ -44,235 +29,6 @@ static struct session_data oiap_session = {0, };
|
||||
|
||||
#endif /* CONFIG_TPM_AUTH_SESSIONS */
|
||||
|
||||
/**
|
||||
* Pack data into a byte string. The data types are specified in
|
||||
* the format string: 'b' means unsigned byte, 'w' unsigned word,
|
||||
* 'd' unsigned double word, and 's' byte string. The data are a
|
||||
* series of offsets and values (for type byte string there are also
|
||||
* lengths). The data values are packed into the byte string
|
||||
* sequentially, and so a latter value could over-write a former
|
||||
* value.
|
||||
*
|
||||
* @param str output string
|
||||
* @param size size of output string
|
||||
* @param format format string
|
||||
* @param ... data points
|
||||
* @return 0 on success, non-0 on error
|
||||
*/
|
||||
int pack_byte_string(u8 *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
size_t offset = 0, length = 0;
|
||||
u8 *data = NULL;
|
||||
u32 value = 0;
|
||||
|
||||
va_start(args, format);
|
||||
for (; *format; format++) {
|
||||
switch (*format) {
|
||||
case 'b':
|
||||
offset = va_arg(args, size_t);
|
||||
value = va_arg(args, int);
|
||||
length = 1;
|
||||
break;
|
||||
case 'w':
|
||||
offset = va_arg(args, size_t);
|
||||
value = va_arg(args, int);
|
||||
length = 2;
|
||||
break;
|
||||
case 'd':
|
||||
offset = va_arg(args, size_t);
|
||||
value = va_arg(args, u32);
|
||||
length = 4;
|
||||
break;
|
||||
case 's':
|
||||
offset = va_arg(args, size_t);
|
||||
data = va_arg(args, u8 *);
|
||||
length = va_arg(args, u32);
|
||||
break;
|
||||
default:
|
||||
debug("Couldn't recognize format string\n");
|
||||
va_end(args);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset + length > size) {
|
||||
va_end(args);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (*format) {
|
||||
case 'b':
|
||||
str[offset] = value;
|
||||
break;
|
||||
case 'w':
|
||||
put_unaligned_be16(value, str + offset);
|
||||
break;
|
||||
case 'd':
|
||||
put_unaligned_be32(value, str + offset);
|
||||
break;
|
||||
case 's':
|
||||
memcpy(str + offset, data, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpack data from a byte string. The data types are specified in
|
||||
* the format string: 'b' means unsigned byte, 'w' unsigned word,
|
||||
* 'd' unsigned double word, and 's' byte string. The data are a
|
||||
* series of offsets and pointers (for type byte string there are also
|
||||
* lengths).
|
||||
*
|
||||
* @param str output string
|
||||
* @param size size of output string
|
||||
* @param format format string
|
||||
* @param ... data points
|
||||
* @return 0 on success, non-0 on error
|
||||
*/
|
||||
int unpack_byte_string(const u8 *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
size_t offset = 0, length = 0;
|
||||
u8 *ptr8 = NULL;
|
||||
u16 *ptr16 = NULL;
|
||||
u32 *ptr32 = NULL;
|
||||
|
||||
va_start(args, format);
|
||||
for (; *format; format++) {
|
||||
switch (*format) {
|
||||
case 'b':
|
||||
offset = va_arg(args, size_t);
|
||||
ptr8 = va_arg(args, u8 *);
|
||||
length = 1;
|
||||
break;
|
||||
case 'w':
|
||||
offset = va_arg(args, size_t);
|
||||
ptr16 = va_arg(args, u16 *);
|
||||
length = 2;
|
||||
break;
|
||||
case 'd':
|
||||
offset = va_arg(args, size_t);
|
||||
ptr32 = va_arg(args, u32 *);
|
||||
length = 4;
|
||||
break;
|
||||
case 's':
|
||||
offset = va_arg(args, size_t);
|
||||
ptr8 = va_arg(args, u8 *);
|
||||
length = va_arg(args, u32);
|
||||
break;
|
||||
default:
|
||||
va_end(args);
|
||||
debug("Couldn't recognize format string\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (offset + length > size) {
|
||||
va_end(args);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (*format) {
|
||||
case 'b':
|
||||
*ptr8 = str[offset];
|
||||
break;
|
||||
case 'w':
|
||||
*ptr16 = get_unaligned_be16(str + offset);
|
||||
break;
|
||||
case 'd':
|
||||
*ptr32 = get_unaligned_be32(str + offset);
|
||||
break;
|
||||
case 's':
|
||||
memcpy(ptr8, str + offset, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TPM command size.
|
||||
*
|
||||
* @param command byte string of TPM command
|
||||
* @return command size of the TPM command
|
||||
*/
|
||||
static u32 tpm_command_size(const void *command)
|
||||
{
|
||||
const size_t command_size_offset = 2;
|
||||
|
||||
return get_unaligned_be32(command + command_size_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TPM response return code, which is one of TPM_RESULT values.
|
||||
*
|
||||
* @param response byte string of TPM response
|
||||
* @return return code of the TPM response
|
||||
*/
|
||||
static u32 tpm_return_code(const void *response)
|
||||
{
|
||||
const size_t return_code_offset = 6;
|
||||
|
||||
return get_unaligned_be32(response + return_code_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a TPM command and return response's return code, and optionally
|
||||
* return response to caller.
|
||||
*
|
||||
* @param command byte string of TPM command
|
||||
* @param response output buffer for TPM response, or NULL if the
|
||||
* caller does not care about it
|
||||
* @param size_ptr output buffer size (input parameter) and TPM
|
||||
* response length (output parameter); this parameter
|
||||
* is a bidirectional
|
||||
* @return return code of the TPM response
|
||||
*/
|
||||
static u32 tpm_sendrecv_command(const void *command, void *response,
|
||||
size_t *size_ptr)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int err, ret;
|
||||
u8 response_buffer[COMMAND_BUFFER_SIZE];
|
||||
size_t response_length;
|
||||
|
||||
if (response) {
|
||||
response_length = *size_ptr;
|
||||
} else {
|
||||
response = response_buffer;
|
||||
response_length = sizeof(response_buffer);
|
||||
}
|
||||
|
||||
ret = uclass_first_device_err(UCLASS_TPM, &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
err = tpm_xfer(dev, command, tpm_command_size(command),
|
||||
response, &response_length);
|
||||
|
||||
if (err < 0)
|
||||
return TPM_LIB_ERROR;
|
||||
if (size_ptr)
|
||||
*size_ptr = response_length;
|
||||
|
||||
return tpm_return_code(response);
|
||||
}
|
||||
|
||||
int tpm_init(void)
|
||||
{
|
||||
int err;
|
||||
struct udevice *dev;
|
||||
|
||||
err = uclass_first_device_err(UCLASS_TPM, &dev);
|
||||
if (err)
|
||||
return err;
|
||||
return tpm_open(dev);
|
||||
}
|
||||
|
||||
u32 tpm_startup(enum tpm_startup_type mode)
|
||||
{
|
||||
const u8 command[12] = {
|
||||
Reference in New Issue
Block a user