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