Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/char/tpm/tpm-buf.c
26285 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Handling of TPM command and other buffers.
4
*/
5
6
#include <linux/tpm_command.h>
7
#include <linux/module.h>
8
#include <linux/tpm.h>
9
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
*/
18
int 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
24
tpm_buf_reset(buf, tag, ordinal);
25
return 0;
26
}
27
EXPORT_SYMBOL_GPL(tpm_buf_init);
28
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
*/
35
void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal)
36
{
37
struct tpm_header *head = (struct tpm_header *)buf->data;
38
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);
44
head->tag = cpu_to_be16(tag);
45
head->length = cpu_to_be32(sizeof(*head));
46
head->ordinal = cpu_to_be32(ordinal);
47
buf->handles = 0;
48
}
49
EXPORT_SYMBOL_GPL(tpm_buf_reset);
50
51
/**
52
* tpm_buf_init_sized() - Allocate and initialize a sized (TPM2B) buffer
53
* @buf: A @tpm_buf
54
*
55
* Return: 0 or -ENOMEM
56
*/
57
int tpm_buf_init_sized(struct tpm_buf *buf)
58
{
59
buf->data = (u8 *)__get_free_page(GFP_KERNEL);
60
if (!buf->data)
61
return -ENOMEM;
62
63
tpm_buf_reset_sized(buf);
64
return 0;
65
}
66
EXPORT_SYMBOL_GPL(tpm_buf_init_sized);
67
68
/**
69
* tpm_buf_reset_sized() - Initialize a sized buffer
70
* @buf: A &tpm_buf
71
*/
72
void tpm_buf_reset_sized(struct tpm_buf *buf)
73
{
74
buf->flags = TPM_BUF_TPM2B;
75
buf->length = 2;
76
buf->data[0] = 0;
77
buf->data[1] = 0;
78
}
79
EXPORT_SYMBOL_GPL(tpm_buf_reset_sized);
80
81
void tpm_buf_destroy(struct tpm_buf *buf)
82
{
83
free_page((unsigned long)buf->data);
84
}
85
EXPORT_SYMBOL_GPL(tpm_buf_destroy);
86
87
/**
88
* tpm_buf_length() - Return the number of bytes consumed by the data
89
* @buf: A &tpm_buf
90
*
91
* Return: The number of bytes consumed by the buffer
92
*/
93
u32 tpm_buf_length(struct tpm_buf *buf)
94
{
95
return buf->length;
96
}
97
EXPORT_SYMBOL_GPL(tpm_buf_length);
98
99
/**
100
* tpm_buf_append() - Append data to an initialized buffer
101
* @buf: A &tpm_buf
102
* @new_data: A data blob
103
* @new_length: Size of the appended data
104
*/
105
void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_length)
106
{
107
/* Return silently if overflow has already happened. */
108
if (buf->flags & TPM_BUF_OVERFLOW)
109
return;
110
111
if ((buf->length + new_length) > PAGE_SIZE) {
112
WARN(1, "tpm_buf: write overflow\n");
113
buf->flags |= TPM_BUF_OVERFLOW;
114
return;
115
}
116
117
memcpy(&buf->data[buf->length], new_data, new_length);
118
buf->length += new_length;
119
120
if (buf->flags & TPM_BUF_TPM2B)
121
((__be16 *)buf->data)[0] = cpu_to_be16(buf->length - 2);
122
else
123
((struct tpm_header *)buf->data)->length = cpu_to_be32(buf->length);
124
}
125
EXPORT_SYMBOL_GPL(tpm_buf_append);
126
127
void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value)
128
{
129
tpm_buf_append(buf, &value, 1);
130
}
131
EXPORT_SYMBOL_GPL(tpm_buf_append_u8);
132
133
void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value)
134
{
135
__be16 value2 = cpu_to_be16(value);
136
137
tpm_buf_append(buf, (u8 *)&value2, 2);
138
}
139
EXPORT_SYMBOL_GPL(tpm_buf_append_u16);
140
141
void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
142
{
143
__be32 value2 = cpu_to_be32(value);
144
145
tpm_buf_append(buf, (u8 *)&value2, 4);
146
}
147
EXPORT_SYMBOL_GPL(tpm_buf_append_u32);
148
149
/**
150
* tpm_buf_append_handle() - Add a handle
151
* @chip: &tpm_chip instance
152
* @buf: &tpm_buf instance
153
* @handle: a TPM object handle
154
*
155
* Add a handle to the buffer, and increase the count tracking the number of
156
* handles in the command buffer. Works only for command buffers.
157
*/
158
void tpm_buf_append_handle(struct tpm_chip *chip, struct tpm_buf *buf, u32 handle)
159
{
160
if (buf->flags & TPM_BUF_TPM2B) {
161
dev_err(&chip->dev, "Invalid buffer type (TPM2B)\n");
162
return;
163
}
164
165
tpm_buf_append_u32(buf, handle);
166
buf->handles++;
167
}
168
169
/**
170
* tpm_buf_read() - Read from a TPM buffer
171
* @buf: &tpm_buf instance
172
* @offset: offset within the buffer
173
* @count: the number of bytes to read
174
* @output: the output buffer
175
*/
176
static void tpm_buf_read(struct tpm_buf *buf, off_t *offset, size_t count, void *output)
177
{
178
off_t next_offset;
179
180
/* Return silently if overflow has already happened. */
181
if (buf->flags & TPM_BUF_BOUNDARY_ERROR)
182
return;
183
184
next_offset = *offset + count;
185
if (next_offset > buf->length) {
186
WARN(1, "tpm_buf: read out of boundary\n");
187
buf->flags |= TPM_BUF_BOUNDARY_ERROR;
188
return;
189
}
190
191
memcpy(output, &buf->data[*offset], count);
192
*offset = next_offset;
193
}
194
195
/**
196
* tpm_buf_read_u8() - Read 8-bit word from a TPM buffer
197
* @buf: &tpm_buf instance
198
* @offset: offset within the buffer
199
*
200
* Return: next 8-bit word
201
*/
202
u8 tpm_buf_read_u8(struct tpm_buf *buf, off_t *offset)
203
{
204
u8 value = 0;
205
206
tpm_buf_read(buf, offset, sizeof(value), &value);
207
208
return value;
209
}
210
EXPORT_SYMBOL_GPL(tpm_buf_read_u8);
211
212
/**
213
* tpm_buf_read_u16() - Read 16-bit word from a TPM buffer
214
* @buf: &tpm_buf instance
215
* @offset: offset within the buffer
216
*
217
* Return: next 16-bit word
218
*/
219
u16 tpm_buf_read_u16(struct tpm_buf *buf, off_t *offset)
220
{
221
u16 value = 0;
222
223
tpm_buf_read(buf, offset, sizeof(value), &value);
224
225
return be16_to_cpu(value);
226
}
227
EXPORT_SYMBOL_GPL(tpm_buf_read_u16);
228
229
/**
230
* tpm_buf_read_u32() - Read 32-bit word from a TPM buffer
231
* @buf: &tpm_buf instance
232
* @offset: offset within the buffer
233
*
234
* Return: next 32-bit word
235
*/
236
u32 tpm_buf_read_u32(struct tpm_buf *buf, off_t *offset)
237
{
238
u32 value = 0;
239
240
tpm_buf_read(buf, offset, sizeof(value), &value);
241
242
return be32_to_cpu(value);
243
}
244
EXPORT_SYMBOL_GPL(tpm_buf_read_u32);
245
246
247
248