xref: /linux/include/linux/tpm_svsm.h (revision dd3922cf9d4d1421e5883614d1a6add912131c00)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2023 James.Bottomley@HansenPartnership.com
4  * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
5  *
6  * Helpers for the SVSM_VTPM_CMD calls used by the vTPM protocol defined by the
7  * AMD SVSM spec [1].
8  *
9  * The vTPM protocol follows the Official TPM 2.0 Reference Implementation
10  * (originally by Microsoft, now part of the TCG) simulator protocol.
11  *
12  * [1] "Secure VM Service Module for SEV-SNP Guests"
13  *     Publication # 58019 Revision: 1.00
14  */
15 #ifndef _TPM_SVSM_H_
16 #define _TPM_SVSM_H_
17 
18 #include <linux/errno.h>
19 #include <linux/string.h>
20 #include <linux/types.h>
21 
22 #define SVSM_VTPM_MAX_BUFFER		4096 /* max req/resp buffer size */
23 
24 /**
25  * struct svsm_vtpm_request - Generic request for single word command
26  * @cmd:	The command to send
27  *
28  * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" -
29  * Table 15: vTPM Common Request/Response Structure
30  *     Byte      Size       In/Out    Description
31  *     Offset    (Bytes)
32  *     0x000     4          In        Platform command
33  *                          Out       Platform command response size
34  */
35 struct svsm_vtpm_request {
36 	u32 cmd;
37 };
38 
39 /**
40  * struct svsm_vtpm_response - Generic response
41  * @size:	The response size (zero if nothing follows)
42  *
43  * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" -
44  * Table 15: vTPM Common Request/Response Structure
45  *     Byte      Size       In/Out    Description
46  *     Offset    (Bytes)
47  *     0x000     4          In        Platform command
48  *                          Out       Platform command response size
49  *
50  * Note: most TCG Simulator commands simply return zero here with no indication
51  * of success or failure.
52  */
53 struct svsm_vtpm_response {
54 	u32 size;
55 };
56 
57 /**
58  * struct svsm_vtpm_cmd_request - Structure for a TPM_SEND_COMMAND request
59  * @cmd:	The command to send (must be TPM_SEND_COMMAND)
60  * @locality:	The locality
61  * @buf_size:	The size of the input buffer following
62  * @buf:	A buffer of size buf_size
63  *
64  * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" -
65  * Table 16: TPM_SEND_COMMAND Request Structure
66  *     Byte      Size       Meaning
67  *     Offset    (Bytes)
68  *     0x000     4          Platform command (8)
69  *     0x004     1          Locality (must-be-0)
70  *     0x005     4          TPM Command size (in bytes)
71  *     0x009     Variable   TPM Command
72  *
73  * Note: the TCG Simulator expects @buf_size to be equal to the size of the
74  * specific TPM command, otherwise an TPM_RC_COMMAND_SIZE error is returned.
75  */
76 struct svsm_vtpm_cmd_request {
77 	u32 cmd;
78 	u8 locality;
79 	u32 buf_size;
80 	u8 buf[];
81 } __packed;
82 
83 /**
84  * struct svsm_vtpm_cmd_response - Structure for a TPM_SEND_COMMAND response
85  * @buf_size:	The size of the output buffer following
86  * @buf:	A buffer of size buf_size
87  *
88  * Defined by AMD SVSM spec [1] in section "8.2 SVSM_VTPM_CMD Call" -
89  * Table 17: TPM_SEND_COMMAND Response Structure
90  *     Byte      Size       Meaning
91  *     Offset    (Bytes)
92  *     0x000     4          Response size (in bytes)
93  *     0x004     Variable   Response
94  */
95 struct svsm_vtpm_cmd_response {
96 	u32 buf_size;
97 	u8 buf[];
98 };
99 
100 /**
101  * svsm_vtpm_cmd_request_fill() - Fill a TPM_SEND_COMMAND request to be sent to SVSM
102  * @req: The struct svsm_vtpm_cmd_request to fill
103  * @locality: The locality
104  * @buf: The buffer from where to copy the payload of the command
105  * @len: The size of the buffer
106  *
107  * Return: 0 on success, negative error code on failure.
108  */
109 static inline int
svsm_vtpm_cmd_request_fill(struct svsm_vtpm_cmd_request * req,u8 locality,const u8 * buf,size_t len)110 svsm_vtpm_cmd_request_fill(struct svsm_vtpm_cmd_request *req, u8 locality,
111 			   const u8 *buf, size_t len)
112 {
113 	if (len > SVSM_VTPM_MAX_BUFFER - sizeof(*req))
114 		return -EINVAL;
115 
116 	req->cmd = 8; /* TPM_SEND_COMMAND */
117 	req->locality = locality;
118 	req->buf_size = len;
119 
120 	memcpy(req->buf, buf, len);
121 
122 	return 0;
123 }
124 
125 /**
126  * svsm_vtpm_cmd_response_parse() - Parse a TPM_SEND_COMMAND response received from SVSM
127  * @resp: The struct svsm_vtpm_cmd_response to parse
128  * @buf: The buffer where to copy the response
129  * @len: The size of the buffer
130  *
131  * Return: buffer size filled with the response on success, negative error
132  * code on failure.
133  */
134 static inline int
svsm_vtpm_cmd_response_parse(const struct svsm_vtpm_cmd_response * resp,u8 * buf,size_t len)135 svsm_vtpm_cmd_response_parse(const struct svsm_vtpm_cmd_response *resp, u8 *buf,
136 			     size_t len)
137 {
138 	if (len < resp->buf_size)
139 		return -E2BIG;
140 
141 	if (resp->buf_size > SVSM_VTPM_MAX_BUFFER - sizeof(*resp))
142 		return -EINVAL;  // Invalid response from the platform TPM
143 
144 	memcpy(buf, resp->buf, resp->buf_size);
145 
146 	return resp->buf_size;
147 }
148 
149 #endif /* _TPM_SVSM_H_ */
150