1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*******************************************************************************
3  * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
4  * All rights reserved.
5  *******************************************************************************/
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <stdlib.h>
12 
13 #include "tss2_esys.h"
14 
15 #include "esys_iutil.h"
16 #include "test-esys.h"
17 #define LOGMODULE test
18 #include "util/log.h"
19 #include "util/aux_util.h"
20 
21 /** This test is intended to test the ESYS commands  nv define space, nv write,
22  *  nv read command, nv lock write and nv lock read, and nv undefine.
23  *
24  * The names stored in the ESYS resource are compared
25  * with the names delivered from the TPM by the command ReadPublic.
26  * only one of the tests NV_ReadLock and NV_WriteLock can be activated
27  * by the defines TEST_READ_LOCK and TEST_WRITE_LOCK (-D option)
28  *
29  * Tested ESYS commands:
30  *  - Esys_FlushContext() (M)
31  *  - Esys_NV_DefineSpace() (M)
32  *  - Esys_NV_Read() (M)
33  *  - Esys_NV_ReadLock() (M)
34  *  - Esys_NV_ReadPublic() (M)
35  *  - Esys_NV_UndefineSpace() (M)
36  *  - Esys_NV_Write() (M)
37  *  - Esys_NV_WriteLock() (M)
38  *  - Esys_StartAuthSession() (M)
39  *
40  * Used compiler defines: TEST_READ_LOCK TEST_SESSION TEST_WRITE_LOCK
41  *
42  * @param[in,out] esys_context The ESYS_CONTEXT.
43  * @retval EXIT_FAILURE
44  * @retval EXIT_SUCCESS
45  */
46 
47 int
test_esys_nv_ram_ordinary_index(ESYS_CONTEXT * esys_context)48 test_esys_nv_ram_ordinary_index(ESYS_CONTEXT * esys_context)
49 {
50     TSS2_RC r;
51     ESYS_TR nvHandle = ESYS_TR_NONE;
52 
53     TPM2B_NV_PUBLIC *nvPublic = NULL;
54     TPM2B_NAME *nvName = NULL;
55     TPM2B_MAX_NV_BUFFER *nv_test_data2 = NULL;
56 
57 #ifdef TEST_SESSION
58     ESYS_TR session = ESYS_TR_NONE;
59     TPMT_SYM_DEF symmetric = {.algorithm = TPM2_ALG_AES,
60                               .keyBits = {.aes = 128},
61                               .mode = {.aes = TPM2_ALG_CFB}
62     };
63     TPMA_SESSION sessionAttributes;
64     TPM2B_NONCE nonceCaller = {
65         .size = 20,
66         .buffer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
67                    11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
68     };
69 
70     memset(&sessionAttributes, 0, sizeof sessionAttributes);
71 
72     r = Esys_StartAuthSession(esys_context, ESYS_TR_NONE, ESYS_TR_NONE,
73                               ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE,
74                               &nonceCaller,
75                               TPM2_SE_HMAC, &symmetric, TPM2_ALG_SHA256,
76                               &session);
77 
78     goto_if_error(r, "Error: During initialization of session", error);
79 #endif /* TEST_SESSION */
80 
81     TPM2B_AUTH auth = {.size = 20,
82                        .buffer={10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
83                                 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}};
84 
85     TPM2B_NV_PUBLIC publicInfo = {
86         .size = 0,
87         .nvPublic = {
88             .nvIndex =TPM2_NV_INDEX_FIRST,
89             .nameAlg = TPM2_ALG_SHA256,
90             .attributes = (
91                 TPMA_NV_OWNERWRITE |
92                 TPMA_NV_AUTHWRITE |
93                 TPMA_NV_WRITE_STCLEAR |
94                 TPMA_NV_READ_STCLEAR |
95                 TPMA_NV_AUTHREAD |
96                 TPMA_NV_OWNERREAD
97                 ),
98             .authPolicy = {
99                  .size = 0,
100                  .buffer = {},
101              },
102             .dataSize = 32,
103         }
104     };
105 
106     r = Esys_NV_DefineSpace(esys_context,
107                             ESYS_TR_RH_OWNER,
108 #ifdef TEST_SESSION
109                             session,
110 #else
111                             ESYS_TR_PASSWORD,
112 #endif
113                             ESYS_TR_NONE,
114                             ESYS_TR_NONE,
115                             &auth,
116                             &publicInfo,
117                             &nvHandle);
118 
119     goto_if_error(r, "Error esys define nv space", error);
120 
121     UINT16 offset = 0;
122     TPM2B_MAX_NV_BUFFER nv_test_data = { .size = 20,
123                                          .buffer={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
124                                                   1, 2, 3, 4, 5, 6, 7, 8, 9}};
125 
126     r = Esys_NV_ReadPublic(esys_context,
127                            nvHandle,
128                            ESYS_TR_NONE,
129                            ESYS_TR_NONE,
130                            ESYS_TR_NONE,
131                            &nvPublic,
132                            &nvName);
133     goto_if_error(r, "Error: nv read public", error);
134 
135     RSRC_NODE_T *nvHandleNode;
136 
137     r = esys_GetResourceObject(esys_context, nvHandle, &nvHandleNode);
138     goto_if_error(r, "Error: nv get resource object", error);
139 
140     if (nvName->size != nvHandleNode->rsrc.name.size ||
141         memcmp(&nvName->name, &nvHandleNode->rsrc.name.name, nvName->size) != 0) {
142         LOG_ERROR("Error: define space name not equal");
143         goto error;
144     }
145     r = Esys_NV_Write(esys_context,
146                       nvHandle,
147                       nvHandle,
148 #ifdef TEST_SESSION
149                       session,
150 #else
151                       ESYS_TR_PASSWORD,
152 #endif
153                       ESYS_TR_NONE,
154                       ESYS_TR_NONE,
155                       &nv_test_data,
156                       offset);
157 
158     goto_if_error(r, "Error esys nv write", error);
159 
160     Esys_Free(nvPublic);
161     Esys_Free(nvName);
162 
163     r = Esys_NV_ReadPublic(esys_context,
164                            nvHandle,
165                            ESYS_TR_NONE,
166                            ESYS_TR_NONE,
167                            ESYS_TR_NONE,
168                            &nvPublic,
169                            &nvName);
170     goto_if_error(r, "Error: nv read public", error);
171 
172     r = esys_GetResourceObject(esys_context, nvHandle, &nvHandleNode);
173     goto_if_error(r, "Error: nv get resource object", error);
174 
175     if (nvName->size != nvHandleNode->rsrc.name.size ||
176         memcmp(&nvName->name, &nvHandleNode->rsrc.name.name, nvName->size) != 0) {
177         LOG_ERROR("Error: nv write name not equal");
178         goto error;
179     }
180 
181     r = Esys_NV_Read(esys_context,
182                      nvHandle,
183                      nvHandle,
184 #ifdef TEST_SESSION
185                      session,
186 #else
187                      ESYS_TR_PASSWORD,
188 #endif
189                      ESYS_TR_NONE,
190                      ESYS_TR_NONE,
191                      20,
192                      0,
193                      &nv_test_data2);
194 
195     goto_if_error(r, "Error esys nv read", error);
196 
197     Esys_Free(nvPublic);
198     Esys_Free(nvName);
199     Esys_Free(nv_test_data2);
200 
201     r = Esys_NV_ReadPublic(esys_context,
202                            nvHandle,
203                            ESYS_TR_NONE,
204                            ESYS_TR_NONE,
205                            ESYS_TR_NONE,
206                            &nvPublic,
207                            &nvName);
208     goto_if_error(r, "Error: nv read public", error);
209 
210     r = esys_GetResourceObject(esys_context, nvHandle, &nvHandleNode);
211     goto_if_error(r, "Error: nv get resource object", error);
212 
213     if (nvName->size != nvHandleNode->rsrc.name.size ||
214         memcmp(&nvName->name, &nvHandleNode->rsrc.name.name, nvName->size) != 0) {
215         LOG_ERROR("Error: nv read name not equal");
216         goto error;
217     }
218 
219 #ifdef TEST_READ_LOCK
220     r = Esys_NV_ReadLock(esys_context,
221                          nvHandle,
222                          nvHandle,
223 #ifdef TEST_SESSION
224                          session,
225 #else
226                          ESYS_TR_PASSWORD,
227 #endif
228                          ESYS_TR_NONE,
229                          ESYS_TR_NONE
230                          );
231     goto_if_error(r, "Error: NV_ReadLock", error);
232 
233     Esys_Free(nvPublic);
234     Esys_Free(nvName);
235 
236     r = Esys_NV_ReadPublic(esys_context,
237                            nvHandle,
238                            ESYS_TR_NONE,
239                            ESYS_TR_NONE,
240                            ESYS_TR_NONE,
241                            &nvPublic,
242                            &nvName);
243     goto_if_error(r, "Error: nv read public", error);
244 
245     r = esys_GetResourceObject(esys_context, nvHandle, &nvHandleNode);
246     goto_if_error(r, "Error: nv get resource object", error);
247 
248     if (nvName->size != nvHandleNode->rsrc.name.size ||
249         memcmp(&nvName->name, &nvHandleNode->rsrc.name.name, nvName->size) != 0) {
250         LOG_ERROR("Error: nv read name not equal");
251         goto error;
252     }
253 
254     r = Esys_NV_Read(esys_context,
255                      nvHandle,
256                      nvHandle,
257 #ifdef TEST_SESSION
258                      session,
259 #else
260                      ESYS_TR_PASSWORD,
261 #endif
262                      ESYS_TR_NONE,
263                      ESYS_TR_NONE,
264                      20,
265                      0,
266                      &nv_test_data2);
267 
268     goto_error_if_not_failed(r, "Error esys nv write successful in write lock state", error);
269 #else /* TEST_READ_LOCK */
270 #ifdef TEST_WRITE_LOCK
271     r = Esys_NV_WriteLock(esys_context,
272                           nvHandle,
273                           nvHandle,
274 #ifdef TEST_SESSION
275                           session,
276 #else
277                           ESYS_TR_PASSWORD,
278 #endif
279                           ESYS_TR_NONE,
280                           ESYS_TR_NONE
281                           );
282     goto_if_error(r, "Error: NV_WriteLock", error);
283 
284     Esys_Free(nvPublic);
285     Esys_Free(nvName);
286 
287     r = Esys_NV_ReadPublic(esys_context,
288                            nvHandle,
289                            ESYS_TR_NONE,
290                            ESYS_TR_NONE,
291                            ESYS_TR_NONE,
292                            &nvPublic,
293                            &nvName);
294     goto_if_error(r, "Error: NV_ReadPublic", error);
295 
296     r = esys_GetResourceObject(esys_context, nvHandle, &nvHandleNode);
297     goto_if_error(r, "Error: nv get resource object", error);
298 
299     if (nvName->size != nvHandleNode->rsrc.name.size ||
300         memcmp(&nvName->name, &nvHandleNode->rsrc.name.name, nvName->size) != 0) {
301         LOG_ERROR("Error: nv read name not equal");
302         goto error;
303     }
304     r = Esys_NV_Write(esys_context,
305                       nvHandle,
306                       nvHandle,
307 #ifdef TEST_SESSION
308                       session,
309 #else
310                       ESYS_TR_PASSWORD,
311 #endif
312                       ESYS_TR_NONE,
313                       ESYS_TR_NONE,
314                       &nv_test_data,
315                       offset);
316     goto_error_if_not_failed(r, "Error esys nv write successful in write lock state", error);
317 #endif /* TEST_WRITE_LOCK */
318 #endif /* TEST_READ_LOCK */
319 
320     r = Esys_NV_UndefineSpace(esys_context,
321                               ESYS_TR_RH_OWNER,
322                               nvHandle,
323 #ifdef TEST_SESSION
324                               session,
325 #else
326                               ESYS_TR_PASSWORD,
327 #endif
328                               ESYS_TR_NONE,
329                               ESYS_TR_NONE
330                               );
331     goto_if_error(r, "Error: NV_UndefineSpace", error);
332 
333 #ifdef TEST_SESSION
334     r = Esys_FlushContext(esys_context, session);
335     goto_if_error(r, "Error: FlushContext", error);
336 #endif
337 
338     Esys_Free(nvPublic);
339     Esys_Free(nvName);
340     return EXIT_SUCCESS;
341 
342  error:
343 
344     if (nvHandle != ESYS_TR_NONE) {
345         if (Esys_NV_UndefineSpace(esys_context,
346                                   ESYS_TR_RH_OWNER,
347                                   nvHandle,
348 #ifdef TEST_SESSION
349                                   session,
350 #else
351                                   ESYS_TR_PASSWORD,
352 #endif
353                                   ESYS_TR_NONE,
354                                   ESYS_TR_NONE) != TSS2_RC_SUCCESS) {
355              LOG_ERROR("Cleanup nvHandle failed.");
356         }
357     }
358 
359 #ifdef TEST_SESSION
360     if (session != ESYS_TR_NONE) {
361         if (Esys_FlushContext(esys_context, session) != TSS2_RC_SUCCESS) {
362             LOG_ERROR("Cleanup session failed.");
363         }
364     }
365 #endif
366     Esys_Free(nvPublic);
367     Esys_Free(nvName);
368     Esys_Free(nv_test_data2);
369     return EXIT_FAILURE;
370 }
371 
372 int
test_invoke_esys(ESYS_CONTEXT * esys_context)373 test_invoke_esys(ESYS_CONTEXT * esys_context) {
374     return test_esys_nv_ram_ordinary_index(esys_context);
375 }
376