1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /***********************************************************************
3  * Copyright (c) 2015 - 2017, Intel Corporation
4  *
5  * All rights reserved.
6  ***********************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 
12 #include <inttypes.h>
13 #include <string.h>
14 
15 #include "tss2_mu.h"
16 
17 #include "util/tpm2b.h"
18 #include "util/tss2_endian.h"
19 #define LOGMODULE marshal
20 #include "util/log.h"
21 
22 #define TPM2B_MARSHAL(type) \
23 TSS2_RC Tss2_MU_##type##_Marshal(type const *src, uint8_t buffer[], \
24                                  size_t buffer_size, size_t *offset) \
25 { \
26     size_t local_offset = 0; \
27     TSS2_RC rc; \
28 \
29     if (src == NULL) { \
30         LOG_WARNING("src param is NULL"); \
31         return TSS2_MU_RC_BAD_REFERENCE; \
32     } \
33     if (offset != NULL) { \
34         LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \
35         local_offset = *offset; \
36     } \
37     if (buffer == NULL && offset == NULL) { \
38         LOG_WARNING("buffer and offset parameter are NULL"); \
39         return TSS2_MU_RC_BAD_REFERENCE; \
40     } else if (buffer == NULL && offset != NULL) { \
41         *offset += sizeof(src->size) + src->size; \
42         LOG_TRACE("buffer NULL and offset non-NULL, updating offset to %zu", \
43              *offset); \
44         return TSS2_RC_SUCCESS; \
45     } else if (buffer_size < local_offset || \
46                buffer_size - local_offset < (sizeof(src->size) + src->size)) { \
47         LOG_WARNING(\
48              "buffer_size: %zu with offset: %zu are insufficient for object " \
49              "of size %zu", \
50              buffer_size, \
51              local_offset, \
52              sizeof(src->size) + src->size); \
53         return TSS2_MU_RC_INSUFFICIENT_BUFFER; \
54     } else if ((sizeof(type) - sizeof(src->size)) < src->size) { \
55         LOG_WARNING(\
56              "size: %u for buffer of " #type " is larger than max length" \
57              " of buffer: %zu", \
58              src->size, \
59              (sizeof(type) - sizeof(src->size))); \
60         return TSS2_MU_RC_BAD_SIZE; \
61     } \
62 \
63     LOG_DEBUG(\
64          "Marshalling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \
65          " at index 0x%zx, buffer size %zu, object size %u", \
66          (uintptr_t)&src, \
67          (uintptr_t)buffer, \
68          local_offset, \
69          buffer_size, \
70          src->size); \
71 \
72     rc = Tss2_MU_UINT16_Marshal(src->size, buffer, buffer_size, &local_offset); \
73     if (rc) \
74         return rc; \
75 \
76     if (src->size) { \
77         memcpy(&buffer[local_offset], ((TPM2B *)src)->buffer, src->size); \
78         local_offset += src->size; \
79     } \
80 \
81     if (offset != NULL) { \
82         *offset = local_offset; \
83         LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \
84     } \
85 \
86     return TSS2_RC_SUCCESS; \
87 }
88 
89 #define TPM2B_UNMARSHAL(type, buf_name) \
90 TSS2_RC Tss2_MU_##type##_Unmarshal(uint8_t const buffer[], size_t buffer_size, \
91                                    size_t *offset, type *dest) \
92 { \
93     size_t  local_offset = 0; \
94     UINT16 size = 0; \
95     TSS2_RC rc; \
96 \
97     if (offset != NULL) { \
98         LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \
99         local_offset = *offset; \
100     } \
101 \
102     if (buffer == NULL || (dest == NULL && offset == NULL)) { \
103         LOG_WARNING("buffer or dest and offset parameter are NULL"); \
104         return TSS2_MU_RC_BAD_REFERENCE; \
105     } else if (buffer_size < local_offset || \
106                sizeof(size) > buffer_size - local_offset) \
107     { \
108         LOG_WARNING(\
109              "buffer_size: %zu with offset: %zu are insufficient for object " \
110              "of size %zu", \
111              buffer_size, \
112              local_offset, \
113              sizeof(size)); \
114         return TSS2_MU_RC_INSUFFICIENT_BUFFER; \
115     } \
116 \
117     rc = Tss2_MU_UINT16_Unmarshal(buffer, buffer_size, &local_offset, &size); \
118     if (rc) \
119         return rc; \
120 \
121     LOG_DEBUG(\
122          "Unmarshaling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \
123          " at index 0x%zx, buffer size %zu, object size %u", \
124          (uintptr_t)buffer, \
125          (uintptr_t)dest, \
126          local_offset, \
127          buffer_size, \
128          size); \
129 \
130     if (size > buffer_size - local_offset) { \
131         LOG_WARNING(\
132              "buffer_size: %zu with offset: %zu are insufficient for object " \
133              "of size %zu", \
134              buffer_size, \
135              local_offset, \
136              (size_t)size); \
137         return TSS2_MU_RC_INSUFFICIENT_BUFFER; \
138     } \
139     if (sizeof(dest->buf_name) < size) { \
140         LOG_ERROR("The dest field size of %zu is too small to unmarshal %d bytes", \
141                   sizeof(dest->buf_name), size); \
142         return TSS2_MU_RC_INSUFFICIENT_BUFFER; \
143     } \
144 \
145     if (dest != NULL) { \
146         dest->size = size; \
147         memcpy(((TPM2B *)dest)->buffer, &buffer[local_offset], size); \
148     } \
149     local_offset += size; \
150     if (offset != NULL) { \
151         *offset = local_offset; \
152         LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \
153     } \
154 \
155     return TSS2_RC_SUCCESS; \
156 }
157 
158 #define TPM2B_MARSHAL_SUBTYPE(type, subtype, member) \
159 TSS2_RC Tss2_MU_##type##_Marshal(type const *src, uint8_t buffer[], \
160                                  size_t buffer_size, size_t *offset) \
161 { \
162     size_t local_offset = 0; \
163     UINT8 *ptr = NULL; \
164     TSS2_RC rc; \
165 \
166     if (src == NULL) { \
167         LOG_WARNING("src param is NULL"); \
168         return TSS2_MU_RC_BAD_REFERENCE; \
169     } \
170 \
171     if (offset != NULL) { \
172         LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \
173         local_offset = *offset; \
174     } \
175 \
176     if (buffer == NULL && offset == NULL) { \
177         LOG_WARNING("buffer and offset parameter are NULL"); \
178         return TSS2_MU_RC_BAD_REFERENCE; \
179     } else if (buffer_size < local_offset || \
180                buffer_size - local_offset < sizeof(src->size)) { \
181         LOG_WARNING(\
182              "buffer_size: %zu with offset: %zu are insufficient for object " \
183              "of size %zu", \
184              buffer_size, \
185              local_offset, \
186              sizeof(src->size)); \
187         return TSS2_MU_RC_INSUFFICIENT_BUFFER; \
188     } \
189 \
190     if (buffer) \
191         ptr = &buffer[local_offset];            \
192 \
193     LOG_DEBUG(\
194          "Marshalling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \
195          " at index 0x%zx, buffer size %zu, object size %u", \
196          (uintptr_t)&src, \
197          (uintptr_t)buffer, \
198          local_offset, \
199          buffer_size, \
200          src->size); \
201 \
202     rc = Tss2_MU_UINT16_Marshal(src->size, buffer, buffer_size, &local_offset); \
203     if (rc) \
204         return rc; \
205 \
206     rc = Tss2_MU_##subtype##_Marshal(&src->member, buffer, buffer_size, &local_offset); \
207     if (rc) \
208         return rc; \
209 \
210     /* Update the size to the real value */ \
211     if (buffer) \
212         *(UINT16 *)ptr = HOST_TO_BE_16(buffer + local_offset - ptr - 2); \
213 \
214     if (offset != NULL) { \
215         *offset = local_offset; \
216         LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \
217     } \
218 \
219     return TSS2_RC_SUCCESS; \
220 }
221 
222 #define TPM2B_UNMARSHAL_SUBTYPE(type, subtype, member) \
223 TSS2_RC Tss2_MU_##type##_Unmarshal(uint8_t const buffer[], size_t buffer_size, \
224                                    size_t *offset, type *dest) \
225 { \
226     size_t  local_offset = 0; \
227     UINT16 size = 0; \
228     TSS2_RC rc; \
229 \
230     if (offset != NULL) { \
231         LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \
232         local_offset = *offset; \
233     } \
234 \
235     if (buffer == NULL || (dest == NULL && offset == NULL)) { \
236         LOG_WARNING("buffer or dest and offset parameter are NULL"); \
237         return TSS2_MU_RC_BAD_REFERENCE; \
238     } else if (buffer_size < local_offset || \
239                sizeof(size) > buffer_size - local_offset) \
240     { \
241         LOG_WARNING(\
242              "buffer_size: %zu with offset: %zu are insufficient for object " \
243              "of size %zu", \
244              buffer_size, \
245              local_offset, \
246              sizeof(size)); \
247         return TSS2_MU_RC_INSUFFICIENT_BUFFER; \
248     } \
249     if (dest && dest->size != 0) { \
250         LOG_WARNING("Size not zero"); \
251         return TSS2_SYS_RC_BAD_VALUE; \
252     } \
253 \
254     rc = Tss2_MU_UINT16_Unmarshal(buffer, buffer_size, &local_offset, &size); \
255     if (rc) \
256         return rc; \
257     LOG_DEBUG(\
258          "Unmarshaling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \
259          " at index 0x%zx, buffer size %zu, object size %u", \
260          (uintptr_t)buffer, \
261          (uintptr_t)dest, \
262          local_offset, \
263          buffer_size, \
264          size); \
265 \
266     if (size > buffer_size - local_offset) { \
267         LOG_WARNING(\
268              "buffer_size: %zu with offset: %zu are insufficient for object " \
269              "of size %zu", \
270              buffer_size, \
271              local_offset, \
272              (size_t)size); \
273         return TSS2_MU_RC_INSUFFICIENT_BUFFER; \
274     } \
275     if (sizeof(dest->member) < size) { \
276         LOG_ERROR("The dest field size of %zu is too small to unmarshal %d bytes", \
277                   sizeof(dest->member), size); \
278         return TSS2_MU_RC_INSUFFICIENT_BUFFER; \
279     } \
280 \
281     if (dest != NULL) { \
282         dest->size = size; \
283         Tss2_MU_##subtype##_Unmarshal(buffer, buffer_size, &local_offset, &dest->member); \
284         if (rc) \
285             return rc; \
286     } else { \
287         local_offset += size; \
288     } \
289 \
290     if (offset != NULL) { \
291         *offset = local_offset; \
292         LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \
293     } \
294 \
295     return TSS2_RC_SUCCESS; \
296 }
297 
298 /*
299  * These macros expand to (un)marshal functions for each of the TPM2B types
300  * the specification part 2.
301  */
302 TPM2B_MARSHAL  (TPM2B_DIGEST);
303 TPM2B_UNMARSHAL(TPM2B_DIGEST, buffer);
304 TPM2B_MARSHAL  (TPM2B_DATA);
305 TPM2B_UNMARSHAL(TPM2B_DATA, buffer);
306 TPM2B_MARSHAL  (TPM2B_EVENT);
307 TPM2B_UNMARSHAL(TPM2B_EVENT, buffer);
308 TPM2B_MARSHAL  (TPM2B_MAX_BUFFER);
309 TPM2B_UNMARSHAL(TPM2B_MAX_BUFFER, buffer);
310 TPM2B_MARSHAL  (TPM2B_MAX_NV_BUFFER);
311 TPM2B_UNMARSHAL(TPM2B_MAX_NV_BUFFER, buffer);
312 TPM2B_MARSHAL  (TPM2B_IV);
313 TPM2B_UNMARSHAL(TPM2B_IV, buffer);
314 TPM2B_MARSHAL  (TPM2B_NAME);
315 TPM2B_UNMARSHAL(TPM2B_NAME, name);
316 TPM2B_MARSHAL  (TPM2B_ATTEST);
317 TPM2B_UNMARSHAL(TPM2B_ATTEST, attestationData);
318 TPM2B_MARSHAL  (TPM2B_SYM_KEY);
319 TPM2B_UNMARSHAL(TPM2B_SYM_KEY, buffer);
320 TPM2B_MARSHAL  (TPM2B_SENSITIVE_DATA);
321 TPM2B_UNMARSHAL(TPM2B_SENSITIVE_DATA, buffer);
322 TPM2B_MARSHAL  (TPM2B_PUBLIC_KEY_RSA);
323 TPM2B_UNMARSHAL(TPM2B_PUBLIC_KEY_RSA, buffer);
324 TPM2B_MARSHAL  (TPM2B_PRIVATE_KEY_RSA);
325 TPM2B_UNMARSHAL(TPM2B_PRIVATE_KEY_RSA, buffer);
326 TPM2B_MARSHAL  (TPM2B_ECC_PARAMETER);
327 TPM2B_UNMARSHAL(TPM2B_ECC_PARAMETER, buffer);
328 TPM2B_MARSHAL  (TPM2B_ENCRYPTED_SECRET);
329 TPM2B_UNMARSHAL(TPM2B_ENCRYPTED_SECRET, secret);
330 TPM2B_MARSHAL  (TPM2B_PRIVATE_VENDOR_SPECIFIC);
331 TPM2B_UNMARSHAL(TPM2B_PRIVATE_VENDOR_SPECIFIC, buffer);
332 TPM2B_MARSHAL  (TPM2B_PRIVATE);
333 TPM2B_UNMARSHAL(TPM2B_PRIVATE, buffer);
334 TPM2B_MARSHAL  (TPM2B_ID_OBJECT);
335 TPM2B_UNMARSHAL(TPM2B_ID_OBJECT, credential);
336 TPM2B_MARSHAL  (TPM2B_CONTEXT_SENSITIVE);
337 TPM2B_UNMARSHAL(TPM2B_CONTEXT_SENSITIVE, buffer);
338 TPM2B_MARSHAL  (TPM2B_CONTEXT_DATA);
339 TPM2B_UNMARSHAL(TPM2B_CONTEXT_DATA, buffer);
340 TPM2B_MARSHAL  (TPM2B_NONCE);
341 TPM2B_UNMARSHAL(TPM2B_NONCE, buffer);
342 TPM2B_MARSHAL  (TPM2B_TIMEOUT);
343 TPM2B_UNMARSHAL(TPM2B_TIMEOUT, buffer);
344 TPM2B_MARSHAL  (TPM2B_AUTH);
345 TPM2B_UNMARSHAL(TPM2B_AUTH, buffer);
346 TPM2B_MARSHAL  (TPM2B_OPERAND);
347 TPM2B_UNMARSHAL(TPM2B_OPERAND, buffer);
348 TPM2B_MARSHAL  (TPM2B_TEMPLATE);
349 TPM2B_UNMARSHAL(TPM2B_TEMPLATE, buffer);
350 TPM2B_MARSHAL_SUBTYPE(TPM2B_ECC_POINT, TPMS_ECC_POINT, point);
351 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_ECC_POINT, TPMS_ECC_POINT, point);
352 TPM2B_MARSHAL_SUBTYPE(TPM2B_NV_PUBLIC, TPMS_NV_PUBLIC, nvPublic);
353 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_NV_PUBLIC, TPMS_NV_PUBLIC, nvPublic);
354 TPM2B_MARSHAL_SUBTYPE(TPM2B_SENSITIVE, TPMT_SENSITIVE, sensitiveArea);
355 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_SENSITIVE, TPMT_SENSITIVE, sensitiveArea);
356 TPM2B_MARSHAL_SUBTYPE(TPM2B_SENSITIVE_CREATE, TPMS_SENSITIVE_CREATE, sensitive);
357 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_SENSITIVE_CREATE, TPMS_SENSITIVE_CREATE, sensitive);
358 TPM2B_MARSHAL_SUBTYPE(TPM2B_CREATION_DATA, TPMS_CREATION_DATA, creationData);
359 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_CREATION_DATA, TPMS_CREATION_DATA, creationData);
360 TPM2B_MARSHAL_SUBTYPE(TPM2B_PUBLIC, TPMT_PUBLIC, publicArea);
361 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_PUBLIC, TPMT_PUBLIC, publicArea);
362