1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*******************************************************************************
3  * Copyright 2019, Intel Corporation
4  *
5  * All rights reserved.
6  ******************************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 
12 #include <stdarg.h>
13 #include <inttypes.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <setjmp.h>
17 #include <cmocka.h>
18 
19 #include "tss2_sys.h"
20 #include "sysapi_util.h"
21 #include "tss2-tcti/tcti-common.h"
22 
23 
24 #define LOGMODULE test
25 #include "util/log.h"
26 
27 /**
28  * Test calls Tss2_Sys_Execute() many times after receiving TPM2_RC_RETRY
29  */
30 
31 const uint8_t ok_response[] = {
32     0x80, 0x01,                 /* TPM_ST_NO_SESSION */
33     0x00, 0x00, 0x00, 0x2C,     /* Response Size 10 + 2 + 32 */
34     0x00, 0x00, 0x00, 0x00,     /* TPM_RC_SUCCESS */
35     0x00, 0x20,                 /* size of buffer */
36     0xde, 0xad, 0xbe, 0xef,
37     0xde, 0xad, 0xbe, 0xef,
38     0xde, 0xad, 0xbe, 0xef,
39     0xde, 0xad, 0xbe, 0xef,
40     0xde, 0xad, 0xbe, 0xef,
41     0xde, 0xad, 0xbe, 0xef,
42     0xde, 0xad, 0xbe, 0xef,
43     0xde, 0xad, 0xbe, 0xef,
44 };
45 
46 const uint8_t retry_response[] = {
47     0x80, 0x01,                 /* TPM_ST_NO_SESSION */
48     0x00, 0x00, 0x00, 0x0A,     /* Response Size 10 */
49     0x00, 0x00, 0x09, 0x22      /* TPM2_RC_RETRY */
50 };
51 
52 static TSS2_RC
tcti_transmit(TSS2_TCTI_CONTEXT * tctiContext,size_t size,uint8_t const * command)53 tcti_transmit(
54     TSS2_TCTI_CONTEXT *tctiContext,
55     size_t size,
56     uint8_t const *command)
57 {
58     TSS2_RC r = 0;
59     tpm_header_t hdr;
60 
61     LOG_DEBUG ("%s: transmiting %zu bytes", __func__, size);
62     r = header_unmarshal (command, &hdr);
63     if (r)
64         return r;
65 
66     LOG_DEBUG ("%s request_hdr.tag  = %x", __func__, hdr.tag);
67     LOG_DEBUG ("%s request_hdr.size  = %x", __func__, hdr.size);
68     LOG_DEBUG ("%s request_hdr.code  = %x", __func__, hdr.code);
69 
70     if (hdr.tag != TPM2_ST_NO_SESSIONS || hdr.size != 0xC || hdr.code != 0x17B)
71         return TSS2_TCTI_RC_BAD_VALUE;
72 
73     return r;
74 }
75 
76 #define NUM_OF_RETRIES 4
77 
78 static TSS2_RC
tcti_receive(TSS2_TCTI_CONTEXT * tctiContext,size_t * size,uint8_t * response,int32_t timeout)79 tcti_receive(
80     TSS2_TCTI_CONTEXT *tctiContext,
81     size_t *size,
82     uint8_t *response,
83     int32_t timeout)
84 {
85     static int i;
86 
87     LOG_DEBUG ("%s: receiving response, size %zu, buff %p",
88                __func__, sizeof(ok_response), response);
89 
90     if (response == NULL) {
91         *size = sizeof(ok_response);
92         return TPM2_RC_SUCCESS;
93     }
94 
95     if (i++ < NUM_OF_RETRIES) {
96         LOG_DEBUG ("%s: return RC_RETRY", __func__);
97         memcpy(response, retry_response, sizeof(retry_response));
98         *size = sizeof(retry_response);
99         return TPM2_RC_SUCCESS;
100     }
101     memcpy(response, ok_response, sizeof(ok_response));
102     *size = sizeof(ok_response);
103     return TPM2_RC_SUCCESS;
104 }
105 
106 static TSS2_ABI_VERSION ver = TSS2_ABI_VERSION_CURRENT;
107 static TSS2_TCTI_CONTEXT_COMMON_V1 _tcti_v1_ctx;
108 
109 static int
setup(void ** state)110 setup(void **state)
111 {
112     TSS2_SYS_CONTEXT  *sys_ctx;
113     TSS2_TCTI_CONTEXT *tcti_ctx = (TSS2_TCTI_CONTEXT *) &_tcti_v1_ctx;
114     UINT32 size_ctx;
115     TSS2_RC r;
116 
117     size_ctx = Tss2_Sys_GetContextSize(0);
118     sys_ctx = calloc (1, size_ctx);
119     assert_non_null (sys_ctx);
120     _tcti_v1_ctx.version = 1;
121     _tcti_v1_ctx.transmit = tcti_transmit;
122     _tcti_v1_ctx.receive = tcti_receive;
123 
124     r = Tss2_Sys_Initialize(sys_ctx, size_ctx, tcti_ctx, &ver);
125     assert_int_equal (r, TSS2_RC_SUCCESS);
126 
127     *state = sys_ctx;
128 
129     return 0;
130 }
131 
132 static int
teardown(void ** state)133 teardown(void **state)
134 {
135     TSS2_SYS_CONTEXT *sys_ctx = (TSS2_SYS_CONTEXT *)*state;
136 
137     if (sys_ctx)
138         free (sys_ctx);
139 
140     return 0;
141 }
142 
143 static void
test_resubmit(void ** state)144 test_resubmit(void **state)
145 {
146     TSS2_RC r = 0;
147     TSS2_SYS_CONTEXT *sys_ctx = (TSS2_SYS_CONTEXT *)*state;
148     int ctr = 0;
149 
150     r = Tss2_Sys_GetRandom_Prepare(sys_ctx, 32);
151     assert_int_equal(r, TSS2_RC_SUCCESS);
152     do {
153         r = Tss2_Sys_Execute(sys_ctx);
154     } while (r == TPM2_RC_RETRY && ctr++ < 10);
155 
156     assert_int_equal(r, TSS2_RC_SUCCESS);
157     assert_int_equal(ctr, NUM_OF_RETRIES);
158     return;
159 }
160 
161 int
main(int argc,char * argv[])162 main(int argc, char *argv[])
163 {
164     const struct CMUnitTest tests[] = {
165         cmocka_unit_test_setup_teardown(test_resubmit, setup, teardown),
166     };
167     return cmocka_run_group_tests(tests, NULL, NULL);
168 }
169