1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3 * Copyright (c) 2018 Intel Corporation
4 * All rights reserved.
5 */
6
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stdarg.h>
15 #include <sys/time.h>
16 #include <inttypes.h>
17 #include <unistd.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21
22 #include "tss2_mu.h"
23 #include "tss2_tcti_fuzzing.h"
24
25 #include "tcti-fuzzing.h"
26 #include "tss2-tcti/tcti-common.h"
27 #include "util/key-value-parse.h"
28 #define LOGMODULE tcti
29 #include "util/log.h"
30
31 /*
32 * Using the data and size fields of the fuzzing TCTI memcpy the data into the
33 * structures given via va_list. Caller will pass the sysContext and number of
34 * arguments that follow. Following the count of arguments caller should pass
35 * the sizeof the next argument, which shall be a pointer to the structure to be
36 * filled.
37 *
38 * Example:
39 *
40 * TPMI_DH_OBJECT keyA = {0};
41 * TPM2B_ECC_POINT inQsB = {0};
42 * TPM2B_ECC_POINT inQeB = {0};
43 * TPMI_ECC_KEY_EXCHANGE inScheme = {0};
44 * UINT16 counter = {0};
45 *
46 * ret = fuzz_fill (
47 * sysContext,
48 * 10,
49 * sizeof (keyA), &keyA,
50 * sizeof (inQsB), &inQsB,
51 * sizeof (inQeB), &inQeB,
52 * sizeof (inScheme), &inScheme,
53 * sizeof (counter), &counter
54 * );
55 * if (ret) {
56 * ... handle failure
57 * }
58 */
59 int
fuzz_fill(TSS2_SYS_CONTEXT * sysContext,size_t count,...)60 fuzz_fill (
61 TSS2_SYS_CONTEXT *sysContext,
62 size_t count,
63 ...)
64 {
65 va_list ap;
66 const uint8_t *data = NULL;
67 const uint8_t *pointer_into_data = NULL;
68 size_t size = 0U;
69 size_t i = 0U;
70 void *copy_into_type;
71 size_t copy_into_length = 0U;
72 size_t data_used = 0U;
73 _TSS2_SYS_CONTEXT_BLOB *ctx = NULL;
74 TSS2_TCTI_FUZZING_CONTEXT *tcti_fuzzing = NULL;
75
76 ctx = syscontext_cast (sysContext);
77 tcti_fuzzing = tcti_fuzzing_context_cast (ctx->tctiContext);
78 data = tcti_fuzzing->data;
79 size = tcti_fuzzing->size;
80
81 va_start (ap, count);
82
83 for (i = 0U; i < (count / 2); ++i) {
84 copy_into_length = va_arg (ap, size_t);
85 copy_into_type = va_arg (ap, void *);
86 if (size > (data_used + copy_into_length)) {
87 pointer_into_data = &data[data_used];
88 data_used += copy_into_length;
89 memcpy (copy_into_type, pointer_into_data, copy_into_length);
90 }
91 }
92
93 va_end (ap);
94
95 return EXIT_SUCCESS;
96 }
97
98 /*
99 * This function wraps the "up-cast" of the opaque TCTI context type to the
100 * type for the fuzzing TCTI context. The only safeguard we have to ensure this
101 * operation is possible is the magic number in the fuzzing TCTI context.
102 * If passed a NULL context, or the magic number check fails, this function
103 * will return NULL.
104 */
105 TSS2_TCTI_FUZZING_CONTEXT*
tcti_fuzzing_context_cast(TSS2_TCTI_CONTEXT * tcti_ctx)106 tcti_fuzzing_context_cast (TSS2_TCTI_CONTEXT *tcti_ctx)
107 {
108 if (tcti_ctx != NULL && TSS2_TCTI_MAGIC (tcti_ctx) == TCTI_FUZZING_MAGIC) {
109 return (TSS2_TCTI_FUZZING_CONTEXT*)tcti_ctx;
110 }
111 return NULL;
112 }
113
114 /*
115 * This function down-casts the fuzzing TCTI context to the common context
116 * defined in the tcti-common module.
117 */
118 TSS2_TCTI_COMMON_CONTEXT*
tcti_fuzzing_down_cast(TSS2_TCTI_FUZZING_CONTEXT * tcti_fuzzing)119 tcti_fuzzing_down_cast (TSS2_TCTI_FUZZING_CONTEXT *tcti_fuzzing)
120 {
121 if (tcti_fuzzing == NULL) {
122 return NULL;
123 }
124 return &tcti_fuzzing->common;
125 }
126
127 TSS2_RC
tcti_fuzzing_transmit(TSS2_TCTI_CONTEXT * tcti_ctx,size_t size,const uint8_t * cmd_buf)128 tcti_fuzzing_transmit (
129 TSS2_TCTI_CONTEXT *tcti_ctx,
130 size_t size,
131 const uint8_t *cmd_buf)
132 {
133 (void) tcti_ctx;
134 (void) size;
135 (void) cmd_buf;
136 ((TSS2_TCTI_FUZZING_CONTEXT*) tcti_ctx)->common.state = TCTI_STATE_RECEIVE;
137 return TSS2_RC_SUCCESS;
138 }
139
140 TSS2_RC
tcti_fuzzing_cancel(TSS2_TCTI_CONTEXT * tcti_ctx)141 tcti_fuzzing_cancel (
142 TSS2_TCTI_CONTEXT *tcti_ctx)
143 {
144 (void) tcti_ctx;
145 return TSS2_RC_SUCCESS;
146 }
147
148 TSS2_RC
tcti_fuzzing_set_locality(TSS2_TCTI_CONTEXT * tcti_ctx,uint8_t locality)149 tcti_fuzzing_set_locality (
150 TSS2_TCTI_CONTEXT *tcti_ctx,
151 uint8_t locality)
152 {
153 (void) tcti_ctx;
154 (void) locality;
155 return TSS2_RC_SUCCESS;
156 }
157
158 TSS2_RC
tcti_fuzzing_get_poll_handles(TSS2_TCTI_CONTEXT * tcti_ctx,TSS2_TCTI_POLL_HANDLE * handles,size_t * num_handles)159 tcti_fuzzing_get_poll_handles (
160 TSS2_TCTI_CONTEXT *tcti_ctx,
161 TSS2_TCTI_POLL_HANDLE *handles,
162 size_t *num_handles)
163 {
164 (void)(tcti_ctx);
165 (void)(handles);
166 (void)(num_handles);
167 return TSS2_TCTI_RC_NOT_IMPLEMENTED;
168 }
169
170 void
tcti_fuzzing_finalize(TSS2_TCTI_CONTEXT * tcti_ctx)171 tcti_fuzzing_finalize(
172 TSS2_TCTI_CONTEXT *tcti_ctx)
173 {
174 (void)(tcti_ctx);
175 }
176
177 TSS2_RC
tcti_fuzzing_receive(TSS2_TCTI_CONTEXT * tcti_ctx,size_t * response_size,unsigned char * response_buffer,int32_t timeout)178 tcti_fuzzing_receive (
179 TSS2_TCTI_CONTEXT *tcti_ctx,
180 size_t *response_size,
181 unsigned char *response_buffer,
182 int32_t timeout)
183 {
184 TSS2_TCTI_FUZZING_CONTEXT *tcti_fuzzing = tcti_fuzzing_context_cast (tcti_ctx);
185 TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_fuzzing_down_cast (tcti_fuzzing);
186 TSS2_RC rc;
187
188 rc = tcti_common_receive_checks (tcti_common, response_size);
189 if (rc != TSS2_RC_SUCCESS) {
190 return rc;
191 }
192 if (timeout != TSS2_TCTI_TIMEOUT_BLOCK) {
193 LOG_WARNING ("The underlying IPC mechanism does not support "
194 "asynchronous I/O. The 'timeout' parameter must be "
195 "TSS2_TCTI_TIMEOUT_BLOCK");
196 return TSS2_TCTI_RC_BAD_VALUE;
197 }
198 if (response_buffer == NULL) {
199 LOG_DEBUG ("Caller queried for size but linux kernel doesn't allow this. "
200 "Returning 4k which is the max size for a response buffer.");
201 *response_size = tcti_fuzzing->size;
202 return TSS2_RC_SUCCESS;
203 }
204 if (*response_size < tcti_fuzzing->size) {
205 LOG_INFO ("Caller provided buffer that *may* not be large enough to "
206 "hold the response buffer.");
207 }
208
209 /* Receive the TPM response. */
210 *response_size = tcti_fuzzing->size;
211 tcti_common->header.size = 0;
212 tcti_common->state = TCTI_STATE_TRANSMIT;
213 memcpy(response_buffer, tcti_fuzzing->data, *response_size);
214
215 return rc;
216 }
217
218 void
tcti_fuzzing_init_context_data(TSS2_TCTI_COMMON_CONTEXT * tcti_common)219 tcti_fuzzing_init_context_data (
220 TSS2_TCTI_COMMON_CONTEXT *tcti_common)
221 {
222 TSS2_TCTI_MAGIC (tcti_common) = TCTI_FUZZING_MAGIC;
223 TSS2_TCTI_VERSION (tcti_common) = TCTI_VERSION;
224 TSS2_TCTI_TRANSMIT (tcti_common) = tcti_fuzzing_transmit;
225 TSS2_TCTI_RECEIVE (tcti_common) = tcti_fuzzing_receive;
226 TSS2_TCTI_FINALIZE (tcti_common) = tcti_fuzzing_finalize;
227 TSS2_TCTI_CANCEL (tcti_common) = tcti_fuzzing_cancel;
228 TSS2_TCTI_GET_POLL_HANDLES (tcti_common) = tcti_fuzzing_get_poll_handles;
229 TSS2_TCTI_SET_LOCALITY (tcti_common) = tcti_fuzzing_set_locality;
230 TSS2_TCTI_MAKE_STICKY (tcti_common) = tcti_make_sticky_not_implemented;
231 tcti_common->state = TCTI_STATE_TRANSMIT;
232 tcti_common->locality = 3;
233 memset (&tcti_common->header, 0, sizeof (tcti_common->header));
234 }
235
236 /*
237 * This is an implementation of the standard TCTI initialization function for
238 * this module.
239 */
240 TSS2_RC
Tss2_Tcti_Fuzzing_Init(TSS2_TCTI_CONTEXT * tcti_ctx,size_t * size,const char * conf)241 Tss2_Tcti_Fuzzing_Init (
242 TSS2_TCTI_CONTEXT *tcti_ctx,
243 size_t *size,
244 const char *conf)
245 {
246 (void) conf;
247
248 if (size == NULL) {
249 return TSS2_TCTI_RC_BAD_VALUE;
250 }
251 if (tcti_ctx == NULL) {
252 *size = sizeof (TSS2_TCTI_FUZZING_CONTEXT);
253 return TSS2_RC_SUCCESS;
254 }
255 if (*size != sizeof (TSS2_TCTI_FUZZING_CONTEXT)) {
256 return TSS2_TCTI_RC_BAD_VALUE;
257 }
258
259 tcti_fuzzing_init_context_data (
260 &(((TSS2_TCTI_FUZZING_CONTEXT*) tcti_ctx)->common));
261
262 return TSS2_RC_SUCCESS;
263 }
264
265 /* public info structure */
266 const TSS2_TCTI_INFO tss2_tcti_info = {
267 .version = TCTI_VERSION,
268 .name = "tcti-fuzzing",
269 .description = "TCTI module for fuzzing the System API.",
270 .config_help = "Takes no configuration.",
271 .init = Tss2_Tcti_Fuzzing_Init,
272 };
273
274 const TSS2_TCTI_INFO*
Tss2_Tcti_Info(void)275 Tss2_Tcti_Info (void)
276 {
277 return &tss2_tcti_info;
278 }
279