1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /***********************************************************************
3 * Copyright (c) 2017-2018, Intel Corporation
4 *
5 * All rights reserved.
6 ***********************************************************************/
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <setjmp.h>
15 #include <cmocka.h>
16 #include "tss2_mu.h"
17 #include "util/tss2_endian.h"
18
19 /*
20 * Success case
21 */
22 static void
tpm2b_marshal_success(void ** state)23 tpm2b_marshal_success(void **state) {
24 TPM2B_DIGEST dgst = {4, {0}};
25 TPM2B_ECC_POINT point = {0};
26 uint8_t buffer[sizeof(dgst) + sizeof(point)] = {0};
27 size_t buffer_size = sizeof(buffer);
28 uint16_t *size_ptr = (uint16_t *) buffer;
29 uint32_t *ptr = (uint32_t *) (buffer + 2);
30 uint32_t value = 0xdeadbeef;
31 uint64_t value2 = 0xdeadbeefdeadbeefULL;
32 uint64_t *ptr2;
33 TSS2_RC rc;
34
35 memcpy(dgst.buffer, &value, sizeof(value));
36 memcpy(point.point.x.buffer, &value, sizeof(value));
37 point.point.x.size = sizeof(value);
38 memcpy(point.point.y.buffer, &value2, sizeof(value2));
39 point.point.y.size = sizeof(value2);
40
41 rc = Tss2_MU_TPM2B_DIGEST_Marshal(&dgst, buffer, buffer_size, NULL);
42 assert_int_equal (rc, TSS2_RC_SUCCESS);
43 assert_int_equal (*size_ptr, HOST_TO_BE_16(4));
44 assert_int_equal (*ptr, value);
45
46 size_ptr = (uint16_t *) buffer;
47 ptr = (uint32_t *) (buffer + 4);
48 rc = Tss2_MU_TPM2B_ECC_POINT_Marshal(&point, buffer, buffer_size, NULL);
49 assert_int_equal (rc, TSS2_RC_SUCCESS);
50 /*
51 * size_ptr points to the size of the whole TPMS_ECC_POINT:
52 * sizeof(unit16) + sizeof(value) + sizeof(unit16) + sizeof(value2)
53 */
54 assert_int_equal (*size_ptr, HOST_TO_BE_16(2 + 4 + 2 + 8));
55 /* check point.x: */
56 assert_int_equal (*(size_ptr + 1), HOST_TO_BE_16(4));
57 assert_int_equal (*ptr, value);
58 size_ptr = (uint16_t *) (buffer + 2 + 2 + 4);
59 ptr2 = (uint64_t *) (buffer + 2 + 2 + 2 + 4);
60 /* check point.y: */
61 assert_int_equal (*size_ptr, HOST_TO_BE_16(8));
62 assert_int_equal (*ptr2, value2);
63 }
64
65 /*
66 * Success case with a valid offset
67 */
68 static void
tpm2b_marshal_success_offset(void ** state)69 tpm2b_marshal_success_offset(void **state) {
70 TPM2B_DIGEST dgst = {4, {0}};
71 TPM2B_ECC_POINT point = {0};
72 size_t offset = 10;
73 uint8_t buffer[sizeof(dgst) + sizeof(point) + 10] = {0};
74 size_t buffer_size = sizeof(buffer);
75 uint16_t *size_ptr = (uint16_t *) (buffer + 10);
76 uint32_t *ptr = (uint32_t *) (buffer + 2 + 10);
77 uint32_t value = 0xdeadbeef;
78 uint64_t value2 = 0xdeadbeefdeadbeefULL;
79 uint64_t *ptr2;
80 TSS2_RC rc;
81
82 memcpy(dgst.buffer, &value, sizeof(value));
83 memcpy(point.point.x.buffer, &value, sizeof(value));
84 point.point.x.size = sizeof(value);
85 memcpy(point.point.y.buffer, &value2, sizeof(value2));
86 point.point.y.size = sizeof(value2);
87
88 rc = Tss2_MU_TPM2B_DIGEST_Marshal(&dgst, buffer, buffer_size, &offset);
89 assert_int_equal (rc, TSS2_RC_SUCCESS);
90 assert_int_equal (*size_ptr, HOST_TO_BE_16(4));
91 assert_int_equal (*ptr, value);
92 /* check the offset */
93 assert_int_equal (offset, 10 + 2 + 4);
94
95 size_ptr = (uint16_t *) (buffer + offset);
96 ptr = (uint32_t *) (buffer + offset + 4);
97 rc = Tss2_MU_TPM2B_ECC_POINT_Marshal(&point, buffer, buffer_size, &offset);
98 assert_int_equal (rc, TSS2_RC_SUCCESS);
99 /*
100 * size_ptr points to the size of the whole TPMS_ECC_POINT:
101 * sizeof(unit16) + sizeof(value) + sizeof(unit16) + sizeof(value2)
102 */
103 assert_int_equal (*size_ptr, HOST_TO_BE_16(2 + 4 + 2 + 8));
104 /* check point.x: */
105 assert_int_equal (*(size_ptr + 1), HOST_TO_BE_16(4));
106 assert_int_equal (*ptr, value);
107 size_ptr = (uint16_t *) (buffer + 10 + 2 + 4 + 2 + 2 + 4);
108 ptr2 = (uint64_t *) (buffer + 10 + 2 + 4 + 2 + 2 + 4 + 2);
109
110 /* check point.y: */
111 assert_int_equal (*size_ptr, HOST_TO_BE_16(8));
112 assert_int_equal (*ptr2, value2);
113 /* check the offset */
114 assert_int_equal (offset, 10 + 2 + 4 + 2 + 2 + 4 + 2 + 8);
115 }
116
117 /*
118 * Success case with a null buffer
119 */
120 static void
tpm2b_marshal_buffer_null_with_offset(void ** state)121 tpm2b_marshal_buffer_null_with_offset(void **state)
122 {
123 TPM2B_DIGEST dgst = {4, {0}};
124 TPM2B_ECC_POINT point = {0};
125 size_t offset = 10;
126 size_t buffer_size = sizeof(dgst) + sizeof(point) + 10;
127 uint32_t value = 0xdeadbeef;
128 uint64_t value2 = 0xdeadbeefdeadbeefULL;
129
130 TSS2_RC rc;
131
132 memcpy(dgst.buffer, &value, sizeof(value));
133 memcpy(point.point.x.buffer, &value, sizeof(value));
134 point.point.x.size = sizeof(value);
135 memcpy(point.point.y.buffer, &value2, sizeof(value2));
136 point.point.y.size = sizeof(value2);
137
138 rc = Tss2_MU_TPM2B_DIGEST_Marshal(&dgst, NULL, buffer_size, &offset);
139 assert_int_equal (rc, TSS2_RC_SUCCESS);
140 assert_int_equal (offset, 10 + 2 + 4);
141
142 offset = 10;
143 rc = Tss2_MU_TPM2B_ECC_POINT_Marshal(&point, NULL, buffer_size, &offset);
144 assert_int_equal (rc, TSS2_RC_SUCCESS);
145 assert_int_equal (offset, 10 + 2 + 2 + sizeof(value) + 2 + sizeof(value2));
146 offset = 0;
147 rc = Tss2_MU_TPM2B_DIGEST_Marshal(&dgst, NULL, buffer_size, &offset);
148 assert_int_equal (rc, TSS2_RC_SUCCESS);
149 /*
150 * TSS MU spec states:
151 * If the 'buffer' parameter is NULL the implementation shall not write
152 * any marshaled data but the 'offset' parameter shall be updated as
153 * though it had.
154 * The offset of call with NULL and not NULL buffer will be compared.
155 */
156 uint8_t buffer[offset];
157
158 size_t offset1 = 0;
159 rc = Tss2_MU_TPM2B_DIGEST_Marshal(&dgst, NULL, buffer_size, &offset1);
160 assert_int_equal (rc, TSS2_RC_SUCCESS);
161
162 size_t offset2 = 0;
163 rc = Tss2_MU_TPM2B_DIGEST_Marshal(&dgst, buffer, buffer_size, &offset2);
164 assert_int_equal (rc, TSS2_RC_SUCCESS);
165 assert_int_equal(offset1, offset2);
166
167 }
168
169 /*
170 * Invalid case with a null buffer and a null offset
171 */
172 static void
tpm2b_marshal_buffer_null_offset_null(void ** state)173 tpm2b_marshal_buffer_null_offset_null(void **state)
174 {
175 TPM2B_DIGEST dgst = {4, {0}};
176 TPM2B_ECC_POINT point = {0};
177 size_t buffer_size = 1024;
178 TSS2_RC rc;
179
180 rc = Tss2_MU_TPM2B_DIGEST_Marshal(&dgst, NULL, buffer_size, NULL);
181 assert_int_equal (rc, TSS2_MU_RC_BAD_REFERENCE);
182
183 rc = Tss2_MU_TPM2B_ECC_POINT_Marshal(&point, NULL, buffer_size, NULL);
184 assert_int_equal (rc, TSS2_MU_RC_BAD_REFERENCE);
185 }
186
187 /*
188 * Invalid case with not big enough buffer
189 */
190 static void
tpm2b_marshal_buffer_size_lt_data_nad_lt_offset(void ** state)191 tpm2b_marshal_buffer_size_lt_data_nad_lt_offset(void **state) {
192 TPM2B_DIGEST dgst = {4, {0}};
193 TPM2B_ECC_POINT point = {0};
194 size_t offset = 10;
195 uint8_t buffer[sizeof(dgst) + sizeof(point)] = {0};
196 size_t buffer_size = sizeof(buffer);
197 uint32_t value = 0xdeadbeef;
198 uint64_t value2 = 0xdeadbeefdeadbeefULL;
199 TSS2_RC rc;
200
201 memcpy(dgst.buffer, &value, sizeof(value));
202 memcpy(point.point.x.buffer, &value, sizeof(value));
203 point.point.x.size = sizeof(value);
204 memcpy(point.point.y.buffer, &value2, sizeof(value2));
205 point.point.y.size = sizeof(value2);
206
207 rc = Tss2_MU_TPM2B_DIGEST_Marshal(&dgst, buffer, buffer_size, &offset);
208 assert_int_equal (rc, TSS2_RC_SUCCESS);
209
210 rc = Tss2_MU_TPM2B_ECC_POINT_Marshal(&point, buffer, buffer_size, &offset);
211 assert_int_equal (rc, TSS2_RC_SUCCESS);
212 }
213
214 /*
215 * Unmarshal success case
216 */
217 static void
tpm2b_unmarshal_success(void ** state)218 tpm2b_unmarshal_success(void **state)
219 {
220 TPM2B_DIGEST dgst = {0};
221 TPM2B_ECC_POINT point = {0};
222 size_t offset = 0;
223 uint8_t buffer[] = { 0x00, 0x04, 0xef, 0xbe, 0xad, 0xde, /* digest of 4 bytes */
224 0x00, 0x0c, /* size of TPM2B_ECC_POINT */
225 0x00, 0x04, 0xef, 0xbe, 0xad, 0xde, /* ECC_POINT.x - 4 bytes */
226 0x00, 0x04, 0x44, 0x33, 0x22, 0x11 }; /* ECC_POINT.y - 4 bytes */
227
228 size_t buffer_size = sizeof(buffer);
229 uint32_t value = 0xdeadbeef;
230 uint32_t value2 = 0x11223344;
231 uint32_t val;
232 TSS2_RC rc;
233
234 rc = Tss2_MU_TPM2B_DIGEST_Unmarshal(buffer, buffer_size, &offset, &dgst);
235 assert_int_equal (rc, TSS2_RC_SUCCESS);
236 assert_int_equal (dgst.size, 4);
237 memcpy(&val, dgst.buffer, sizeof(val));
238 assert_int_equal (le32toh(val), value);
239 assert_int_equal (offset, 6);
240
241 rc = Tss2_MU_TPM2B_ECC_POINT_Unmarshal(buffer, buffer_size, &offset, &point);
242 assert_int_equal (rc, TSS2_RC_SUCCESS);
243 assert_int_equal (point.point.x.size, 4);
244 memcpy(&val, point.point.x.buffer, sizeof(val));
245 assert_int_equal (le32toh(val), value);
246 assert_int_equal (point.point.y.size, 4);
247 memcpy(&val, point.point.y.buffer, sizeof(val));
248 assert_int_equal (le32toh(val), value2);
249 assert_int_equal (offset, 20);
250 }
251
252 /*
253 * Unmarshal success case with offset
254 */
255 static void
tpm2b_unmarshal_success_offset(void ** state)256 tpm2b_unmarshal_success_offset(void **state)
257 {
258 TPM2B_DIGEST dgst = {0};
259 TPM2B_ECC_POINT point = {0};
260 size_t offset = 6;
261 uint8_t buffer[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, /* random 6 bytes offset */
262 0x00, 0x04, 0xef, 0xbe, 0xad, 0xde, /* digest of 4 bytes */
263 0x00, 0x10, /* size of TPM2B_ECC_POINT - 16 bytes */
264 0x00, 0x08, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, /* ECC_POINT.x - 8 bytes */
265 0x00, 0x04, 0x44, 0x33, 0x22, 0x11 }; /* ECC_POINT.y - 4 bytes */
266
267 size_t buffer_size = sizeof(buffer);
268 uint32_t value = 0xdeadbeef;
269 uint64_t value2 = 0xdeadbeefdeadbeefULL;
270 uint32_t value3 = 0x11223344;
271 uint32_t val;
272 uint64_t val2;
273 TSS2_RC rc;
274
275 rc = Tss2_MU_TPM2B_DIGEST_Unmarshal(buffer, buffer_size, &offset, &dgst);
276 assert_int_equal (rc, TSS2_RC_SUCCESS);
277 assert_int_equal (dgst.size, 4);
278 memcpy(&val, dgst.buffer, sizeof(val));
279 assert_int_equal (le32toh(val), value);
280 assert_int_equal (offset, 12);
281
282 rc = Tss2_MU_TPM2B_ECC_POINT_Unmarshal(buffer, buffer_size, &offset, &point);
283 assert_int_equal (rc, TSS2_RC_SUCCESS);
284 assert_int_equal (point.point.x.size, 8);
285 memcpy(&val2, point.point.x.buffer, sizeof(val2));
286 assert_int_equal (le64toh(val2), value2);
287 assert_int_equal (point.point.y.size, 4);
288 memcpy(&val, point.point.y.buffer, sizeof(val));
289 assert_int_equal (le32toh(val), value3);
290 assert_int_equal (offset, 30);
291 }
292
293 /*
294 * Test case ensures a NULL buffer parameter produces a BAD_REFERENCE RC.
295 */
296 void
tpm2b_unmarshal_buffer_null(void ** state)297 tpm2b_unmarshal_buffer_null (void **state)
298 {
299 TPM2B_DIGEST dgst = {0};
300 TPM2B_ECC_POINT point = {0};
301 TSS2_RC rc;
302 size_t offset = 0;
303
304 rc = Tss2_MU_TPM2B_DIGEST_Unmarshal (NULL, 1, NULL, NULL);
305 assert_int_equal (rc, TSS2_MU_RC_BAD_REFERENCE);
306
307 rc = Tss2_MU_TPM2B_ECC_POINT_Unmarshal (NULL, 1, NULL, NULL);
308 assert_int_equal (rc, TSS2_MU_RC_BAD_REFERENCE);
309
310 rc = Tss2_MU_TPM2B_DIGEST_Unmarshal (NULL, 1, &offset, NULL);
311 assert_int_equal (rc, TSS2_MU_RC_BAD_REFERENCE);
312
313 rc = Tss2_MU_TPM2B_ECC_POINT_Unmarshal (NULL, 1, &offset, NULL);
314 assert_int_equal (rc, TSS2_MU_RC_BAD_REFERENCE);
315
316 rc = Tss2_MU_TPM2B_DIGEST_Unmarshal (NULL, 1, NULL, &dgst);
317 assert_int_equal (rc, TSS2_MU_RC_BAD_REFERENCE);
318
319 rc = Tss2_MU_TPM2B_ECC_POINT_Unmarshal (NULL, 1, NULL, &point);
320 assert_int_equal (rc, TSS2_MU_RC_BAD_REFERENCE);
321 }
322 /*
323 * Test case ensures a NULL dest and offset parameters produce an
324 * INSUFFICIENT_BUFFER RC.
325 */
326 void
tpm2b_unmarshal_dest_null(void ** state)327 tpm2b_unmarshal_dest_null (void **state)
328 {
329 uint8_t buffer [1];
330 TSS2_RC rc;
331
332 rc = Tss2_MU_TPM2B_DIGEST_Unmarshal (buffer, sizeof (buffer), NULL, NULL);
333 assert_int_equal (rc, TSS2_MU_RC_BAD_REFERENCE);
334
335 rc = Tss2_MU_TPM2B_ECC_POINT_Unmarshal (buffer, 1, NULL, NULL);
336 assert_int_equal (rc, TSS2_MU_RC_BAD_REFERENCE);
337 }
338
339 /*
340 * Test case ensures the offset is updated when dest is NULL
341 * and offset is valid
342 */
343 void
tpm2b_unmarshal_dest_null_offset_valid(void ** state)344 tpm2b_unmarshal_dest_null_offset_valid (void **state)
345 {
346 size_t offset = 0;
347 uint8_t buffer[] = { 0x00, 0x04, 0xef, 0xbe, 0xad, 0xde, /* digest of 4 bytes */
348 0x00, 0x10, /* size of TPM2B_ECC_POINT - 16 bytes */
349 0x00, 0x08, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, /* ECC_POINT.x - 8 bytes */
350 0x00, 0x04, 0x44, 0x33, 0x22, 0x11 }; /* ECC_POINT.y - 4 bytes */
351 TSS2_RC rc;
352
353 rc = Tss2_MU_TPM2B_DIGEST_Unmarshal (buffer, sizeof (buffer), &offset, NULL);
354 assert_int_equal (rc, TSS2_RC_SUCCESS);
355 assert_int_equal (offset, 6);
356
357 rc = Tss2_MU_TPM2B_ECC_POINT_Unmarshal (buffer, sizeof (buffer), &offset, NULL);
358 assert_int_equal (rc, TSS2_RC_SUCCESS);
359 assert_int_equal (offset, 24);
360 }
361
362 /*
363 * Invalid case with not big enough buffer
364 */
365 static void
tpm2b_unmarshal_buffer_size_lt_data_nad_lt_offset(void ** state)366 tpm2b_unmarshal_buffer_size_lt_data_nad_lt_offset(void **state)
367 {
368 TPM2B_DIGEST dgst = {4, {0x00, 0x01, 0x02, 0x03}};
369 TPM2B_ECC_POINT point = {0};
370 uint8_t buffer[sizeof(dgst) + sizeof(point)] = { 0 };
371 size_t offset = sizeof(dgst) - 5;
372 TSS2_RC rc;
373
374 rc = Tss2_MU_TPM2B_DIGEST_Unmarshal (buffer, 6, &offset, &dgst);
375 assert_int_equal (rc, TSS2_MU_RC_INSUFFICIENT_BUFFER);
376 assert_int_equal (offset, sizeof(dgst) - 5);
377
378 rc = Tss2_MU_TPM2B_ECC_POINT_Unmarshal (buffer, 1, &offset, &point);
379 assert_int_equal (rc, TSS2_MU_RC_INSUFFICIENT_BUFFER);
380 assert_int_equal (offset, sizeof(dgst) - 5);
381 }
382
383 /*
384 * Success case
385 */
386 static void
tpm2b_public_rsa_marshal_success(void ** state)387 tpm2b_public_rsa_marshal_success(void **state) {
388 TPM2B_PUBLIC pub2b = {0};
389 TPMT_PUBLIC *pub = &pub2b.publicArea;
390 uint8_t buffer[sizeof(pub2b)] = { 0 };
391 size_t buffer_size = sizeof(buffer);
392 TPM2B_PUBLIC *ptr1;
393 TSS2_RC rc;
394
395 pub->type = TPM2_ALG_RSA;
396 pub->parameters.rsaDetail.symmetric.algorithm = TPM2_ALG_AES;
397 pub->parameters.rsaDetail.symmetric.keyBits.aes = 128;
398 pub->parameters.rsaDetail.symmetric.mode.aes = TPM2_ALG_CBC;
399 rc = Tss2_MU_TPM2B_PUBLIC_Marshal(&pub2b, buffer, buffer_size, NULL);
400 assert_int_equal (rc, TSS2_RC_SUCCESS);
401 ptr1 = (TPM2B_PUBLIC *)buffer;
402 assert_int_equal (ptr1->size, HOST_TO_BE_16(0x1a));
403 }
404
405 /*
406 * Success case
407 */
408 static void
tpm2b_public_rsa_unique_size_marshal_success(void ** state)409 tpm2b_public_rsa_unique_size_marshal_success(void **state) {
410 TPM2B_PUBLIC pub2b = {0};
411 TPMT_PUBLIC *pub = &pub2b.publicArea;
412 uint8_t buffer[sizeof(pub2b)] = { 0 };
413 size_t buffer_size = sizeof(buffer);
414 TPM2B_PUBLIC *ptr1;
415 TSS2_RC rc;
416
417 pub->type = TPM2_ALG_RSA;
418 pub->parameters.rsaDetail.symmetric.algorithm = TPM2_ALG_AES;
419 pub->parameters.rsaDetail.symmetric.keyBits.aes = 128;
420 pub->parameters.rsaDetail.symmetric.mode.aes = TPM2_ALG_CBC;
421 pub->unique.rsa.size = 0x100;
422 rc = Tss2_MU_TPM2B_PUBLIC_Marshal(&pub2b, buffer, buffer_size, NULL);
423 assert_int_equal (rc, TSS2_RC_SUCCESS);
424 ptr1 = (TPM2B_PUBLIC *)buffer;
425 assert_int_equal (ptr1->size, HOST_TO_BE_16(0x11a));
426 }
427
main(void)428 int main(void) {
429 const struct CMUnitTest tests[] = {
430 cmocka_unit_test(tpm2b_marshal_success),
431 cmocka_unit_test(tpm2b_marshal_success_offset),
432 cmocka_unit_test(tpm2b_marshal_buffer_null_with_offset),
433 cmocka_unit_test(tpm2b_marshal_buffer_null_offset_null),
434 cmocka_unit_test(tpm2b_marshal_buffer_size_lt_data_nad_lt_offset),
435 cmocka_unit_test(tpm2b_unmarshal_success),
436 cmocka_unit_test(tpm2b_unmarshal_success_offset),
437 cmocka_unit_test(tpm2b_unmarshal_buffer_null),
438 cmocka_unit_test(tpm2b_unmarshal_dest_null),
439 cmocka_unit_test(tpm2b_unmarshal_dest_null_offset_valid),
440 cmocka_unit_test(tpm2b_unmarshal_buffer_size_lt_data_nad_lt_offset),
441 cmocka_unit_test(tpm2b_public_rsa_marshal_success),
442 cmocka_unit_test(tpm2b_public_rsa_unique_size_marshal_success),
443 };
444 return cmocka_run_group_tests(tests, NULL, NULL);
445 }
446