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