mirror of https://gitee.com/openkylin/linux.git
tpm: introduce tpm_buf
This patch introduces struct tpm_buf that provides a string buffer for constructing TPM commands. This allows to construct variable sized TPM commands. For the buffer a page is allocated and mapped, which limits maximum size to PAGE_SIZE. Variable sized TPM commands are needed in order to add algorithmic agility. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Reviewed-by: Peter Huewe <peterhuewe@gmx.de> Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
This commit is contained in:
parent
b8e98dcdc5
commit
a74f8b3635
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2004 IBM Corporation
|
||||
* Copyright (C) 2015 Intel Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Leendert van Doorn <leendert@watson.ibm.com>
|
||||
|
@ -28,6 +29,7 @@
|
|||
#include <linux/tpm.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/highmem.h>
|
||||
|
||||
enum tpm_const {
|
||||
TPM_MINOR = 224, /* officially assigned */
|
||||
|
@ -390,6 +392,101 @@ struct tpm_cmd_t {
|
|||
tpm_cmd_params params;
|
||||
} __packed;
|
||||
|
||||
/* A string buffer type for constructing TPM commands. This is based on the
|
||||
* ideas of string buffer code in security/keys/trusted.h but is heap based
|
||||
* in order to keep the stack usage minimal.
|
||||
*/
|
||||
|
||||
enum tpm_buf_flags {
|
||||
TPM_BUF_OVERFLOW = BIT(0),
|
||||
};
|
||||
|
||||
struct tpm_buf {
|
||||
struct page *data_page;
|
||||
unsigned int flags;
|
||||
u8 *data;
|
||||
};
|
||||
|
||||
static inline void tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
|
||||
{
|
||||
struct tpm_input_header *head;
|
||||
|
||||
buf->data_page = alloc_page(GFP_HIGHUSER);
|
||||
if (!buf->data_page)
|
||||
return -ENOMEM;
|
||||
|
||||
buf->flags = 0;
|
||||
buf->data = kmap(buf->data_page);
|
||||
|
||||
head = (struct tpm_input_header *) buf->data;
|
||||
|
||||
head->tag = cpu_to_be16(tag);
|
||||
head->length = cpu_to_be32(sizeof(*head));
|
||||
head->ordinal = cpu_to_be32(ordinal);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void tpm_buf_destroy(struct tpm_buf *buf)
|
||||
{
|
||||
kunmap(buf->data_page);
|
||||
__free_page(buf->data_page);
|
||||
}
|
||||
|
||||
static inline u32 tpm_buf_length(struct tpm_buf *buf)
|
||||
{
|
||||
struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
|
||||
|
||||
return be32_to_cpu(head->length);
|
||||
}
|
||||
|
||||
static inline u16 tpm_buf_tag(struct tpm_buf *buf)
|
||||
{
|
||||
struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
|
||||
|
||||
return be16_to_cpu(head->tag);
|
||||
}
|
||||
|
||||
static inline void tpm_buf_append(struct tpm_buf *buf,
|
||||
const unsigned char *new_data,
|
||||
unsigned int new_len)
|
||||
{
|
||||
struct tpm_input_header *head = (struct tpm_input_header *) buf->data;
|
||||
u32 len = tpm_buf_length(buf);
|
||||
|
||||
/* Return silently if overflow has already happened. */
|
||||
if (buf->flags & TPM_BUF_OVERFLOW)
|
||||
return;
|
||||
|
||||
if ((len + new_len) > PAGE_SIZE) {
|
||||
WARN(1, "tpm_buf: overflow\n");
|
||||
buf->flags |= TPM_BUF_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&buf->data[len], new_data, new_len);
|
||||
head->length = cpu_to_be32(len + new_len);
|
||||
}
|
||||
|
||||
static inline void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value)
|
||||
{
|
||||
tpm_buf_append(buf, &value, 1);
|
||||
}
|
||||
|
||||
static inline void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value)
|
||||
{
|
||||
__be16 value2 = cpu_to_be16(value);
|
||||
|
||||
tpm_buf_append(buf, (u8 *) &value2, 2);
|
||||
}
|
||||
|
||||
static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
|
||||
{
|
||||
__be32 value2 = cpu_to_be32(value);
|
||||
|
||||
tpm_buf_append(buf, (u8 *) &value2, 4);
|
||||
}
|
||||
|
||||
extern struct class *tpm_class;
|
||||
extern dev_t tpm_devt;
|
||||
extern const struct file_operations tpm_fops;
|
||||
|
|
Loading…
Reference in New Issue