xref: /linux/drivers/char/tpm/tpm-buf.c (revision e1b72e1b11109bd81577950538a17bc0428e647f)
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 }
48 EXPORT_SYMBOL_GPL(tpm_buf_reset);
49 
50 void tpm_buf_destroy(struct tpm_buf *buf)
51 {
52 	free_page((unsigned long)buf->data);
53 }
54 EXPORT_SYMBOL_GPL(tpm_buf_destroy);
55 
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  */
62 u32 tpm_buf_length(struct tpm_buf *buf)
63 {
64 	return buf->length;
65 }
66 EXPORT_SYMBOL_GPL(tpm_buf_length);
67 
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  */
74 void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_length)
75 {
76 	struct tpm_header *head = (struct tpm_header *)buf->data;
77 
78 	/* Return silently if overflow has already happened. */
79 	if (buf->flags & TPM_BUF_OVERFLOW)
80 		return;
81 
82 	if ((buf->length + new_length) > PAGE_SIZE) {
83 		WARN(1, "tpm_buf: overflow\n");
84 		buf->flags |= TPM_BUF_OVERFLOW;
85 		return;
86 	}
87 
88 	memcpy(&buf->data[buf->length], new_data, new_length);
89 	buf->length += new_length;
90 	head->length = cpu_to_be32(buf->length);
91 }
92 EXPORT_SYMBOL_GPL(tpm_buf_append);
93 
94 void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value)
95 {
96 	tpm_buf_append(buf, &value, 1);
97 }
98 EXPORT_SYMBOL_GPL(tpm_buf_append_u8);
99 
100 void 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 }
106 EXPORT_SYMBOL_GPL(tpm_buf_append_u16);
107 
108 void 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 }
114 EXPORT_SYMBOL_GPL(tpm_buf_append_u32);
115