tpm: Store the length of the tpm_buf data separately.
[linux-2.6-block.git] / drivers / char / tpm / tpm-buf.c
CommitLineData
17d89b2e
JB
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Handling of TPM command and other buffers.
4 */
5
e1b72e1b 6#include <linux/tpm_command.h>
17d89b2e
JB
7#include <linux/module.h>
8#include <linux/tpm.h>
9
e1b72e1b
JS
10/**
11 * tpm_buf_init() - Allocate and initialize a TPM command
12 * @buf: A &tpm_buf
13 * @tag: TPM_TAG_RQU_COMMAND, TPM2_ST_NO_SESSIONS or TPM2_ST_SESSIONS
14 * @ordinal: A command ordinal
15 *
16 * Return: 0 or -ENOMEM
17 */
17d89b2e
JB
18int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal)
19{
20 buf->data = (u8 *)__get_free_page(GFP_KERNEL);
21 if (!buf->data)
22 return -ENOMEM;
23
17d89b2e
JB
24 tpm_buf_reset(buf, tag, ordinal);
25 return 0;
26}
27EXPORT_SYMBOL_GPL(tpm_buf_init);
28
e1b72e1b
JS
29/**
30 * tpm_buf_reset() - Initialize a TPM command
31 * @buf: A &tpm_buf
32 * @tag: TPM_TAG_RQU_COMMAND, TPM2_ST_NO_SESSIONS or TPM2_ST_SESSIONS
33 * @ordinal: A command ordinal
34 */
17d89b2e
JB
35void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal)
36{
37 struct tpm_header *head = (struct tpm_header *)buf->data;
38
e1b72e1b
JS
39 WARN_ON(tag != TPM_TAG_RQU_COMMAND && tag != TPM2_ST_NO_SESSIONS &&
40 tag != TPM2_ST_SESSIONS && tag != 0);
41
42 buf->flags = 0;
43 buf->length = sizeof(*head);
17d89b2e
JB
44 head->tag = cpu_to_be16(tag);
45 head->length = cpu_to_be32(sizeof(*head));
46 head->ordinal = cpu_to_be32(ordinal);
47}
48EXPORT_SYMBOL_GPL(tpm_buf_reset);
49
50void tpm_buf_destroy(struct tpm_buf *buf)
51{
52 free_page((unsigned long)buf->data);
53}
54EXPORT_SYMBOL_GPL(tpm_buf_destroy);
55
e1b72e1b
JS
56/**
57 * tpm_buf_length() - Return the number of bytes consumed by the data
58 * @buf: A &tpm_buf
59 *
60 * Return: The number of bytes consumed by the buffer
61 */
17d89b2e
JB
62u32 tpm_buf_length(struct tpm_buf *buf)
63{
e1b72e1b 64 return buf->length;
17d89b2e
JB
65}
66EXPORT_SYMBOL_GPL(tpm_buf_length);
67
e1b72e1b
JS
68/**
69 * tpm_buf_append() - Append data to an initialized buffer
70 * @buf: A &tpm_buf
71 * @new_data: A data blob
72 * @new_length: Size of the appended data
73 */
74void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_length)
17d89b2e
JB
75{
76 struct tpm_header *head = (struct tpm_header *)buf->data;
17d89b2e
JB
77
78 /* Return silently if overflow has already happened. */
79 if (buf->flags & TPM_BUF_OVERFLOW)
80 return;
81
e1b72e1b 82 if ((buf->length + new_length) > PAGE_SIZE) {
17d89b2e
JB
83 WARN(1, "tpm_buf: overflow\n");
84 buf->flags |= TPM_BUF_OVERFLOW;
85 return;
86 }
87
e1b72e1b
JS
88 memcpy(&buf->data[buf->length], new_data, new_length);
89 buf->length += new_length;
90 head->length = cpu_to_be32(buf->length);
17d89b2e
JB
91}
92EXPORT_SYMBOL_GPL(tpm_buf_append);
93
94void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value)
95{
96 tpm_buf_append(buf, &value, 1);
97}
98EXPORT_SYMBOL_GPL(tpm_buf_append_u8);
99
100void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value)
101{
102 __be16 value2 = cpu_to_be16(value);
103
104 tpm_buf_append(buf, (u8 *)&value2, 2);
105}
106EXPORT_SYMBOL_GPL(tpm_buf_append_u16);
107
108void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
109{
110 __be32 value2 = cpu_to_be32(value);
111
112 tpm_buf_append(buf, (u8 *)&value2, 4);
113}
114EXPORT_SYMBOL_GPL(tpm_buf_append_u32);