• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * SPDX-License-Identifier: BSD-2-Clause
3  * Copyright (c) 2019, Intel Corporation
4  */
5 
6 #ifdef HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9 
10 #include <assert.h>
11 #include <inttypes.h>
12 #include <stdbool.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include "tss2_sys.h"
18 
19 #include "context-util.h"
20 #include "sapi-util.h"
21 #include "util/aux_util.h"
22 #define LOGMODULE test
23 #include "util/log.h"
24 
25 #define NV_INDEX 0x01800003
26 #define NV_SIZE 96
27 
28 #define TPM2B_SIZE_MAX(type) (sizeof (type) - 2)
29 
30 /*
31  * This test creates an NV index governed by a policy and then performs
32  * several operations on the NV region to exercise this policy. The NV
33  * region created is modeled after the TXT AUX region as defined by the
34  * Intel TXT software developers guide:
35  * https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
36  * Read is controlled by authValue and is unrestricted since authValue is
37  * set to emptyBuffer.
38  * Write is controlled by policy that allows writes from locality 3 and 4.
39  */
40 /*
41  * This function creates a policy session asserting that the locality is
42  * either 3 or 4. If this policy is used when executing a command and the
43  * policy is not satisfied (locality is not 3 or 4) then the command will
44  * fail.
45  */
46 static TSS2_RC
create_policy_session(TSS2_SYS_CONTEXT * sys_ctx,TPMI_SH_AUTH_SESSION * handle)47 create_policy_session (TSS2_SYS_CONTEXT *sys_ctx,
48                        TPMI_SH_AUTH_SESSION *handle)
49 {
50     TPMA_LOCALITY locality = TPMA_LOCALITY_TPM2_LOC_THREE |
51         TPMA_LOCALITY_TPM2_LOC_FOUR;
52     TPM2B_NONCE nonce = { .size = GetDigestSize (TPM2_ALG_SHA1), };
53     TPM2B_NONCE nonce_tpm = { 0, };
54     TSS2_RC rc;
55     TPM2B_ENCRYPTED_SECRET salt = { 0, };
56     TPMT_SYM_DEF symmetric = { .algorithm = TPM2_ALG_NULL, };
57 
58     rc = Tss2_Sys_StartAuthSession (sys_ctx,
59                                     TPM2_RH_NULL,
60                                     TPM2_RH_NULL,
61                                     0,
62                                     &nonce,
63                                     &salt,
64                                     TPM2_SE_POLICY,
65                                     &symmetric,
66                                     TPM2_ALG_SHA1,
67                                     handle,
68                                     &nonce_tpm,
69                                     0);
70     return_if_error (rc, "Tss2_Sys_StartAuthSession");
71 
72     rc = Tss2_Sys_PolicyLocality (sys_ctx,
73                                   *handle,
74                                   0,
75                                   locality,
76                                   0);
77     return_if_error (rc, "Tss2_Sys_PolicyLocality");
78     return rc;
79 }
80 /*
81  * This function creates the NV region used in this test. The appropriate
82  * attributes are applied using the nvPublic member of the TPM2B_NV_PUBLIC
83  * structure.
84  */
85 static TSS2_RC
setup_nv(TSS2_SYS_CONTEXT * sys_ctx)86 setup_nv (TSS2_SYS_CONTEXT *sys_ctx)
87 {
88     TSS2_RC rc;
89     TPMI_SH_AUTH_SESSION auth_handle = 0;
90     TPM2B_DIGEST policy_hash = { 0, };
91     TPM2B_AUTH nv_auth = { 0, };
92     TSS2L_SYS_AUTH_RESPONSE auth_rsp = { 0, };
93     TPM2B_NV_PUBLIC public_info = {
94         .nvPublic = {
95             .attributes = TPMA_NV_AUTHREAD | TPMA_NV_POLICYWRITE |
96                 TPMA_NV_PLATFORMCREATE, /* POLICYDELETE? */
97             .authPolicy = { .size = GetDigestSize (TPM2_ALG_SHA1), },
98             .dataSize = NV_SIZE,
99             .nameAlg = TPM2_ALG_SHA1,
100             .nvIndex = NV_INDEX,
101         },
102     };
103     const TSS2L_SYS_AUTH_COMMAND auth_cmd = {
104         .count = 1,
105         .auths= {
106             {
107                 .sessionHandle = TPM2_RS_PW,
108             }
109         }
110     };
111 
112     rc = create_policy_session (sys_ctx, &auth_handle);
113     return_if_error (rc, "create_policy_session");
114 
115     rc = Tss2_Sys_PolicyGetDigest (sys_ctx,
116                                    auth_handle,
117                                    0,
118                                    &policy_hash,
119                                    0);
120     return_if_error (rc, "Tss2_Sys_PolicyGetDigest");
121 
122     LOGBLOB_DEBUG (policy_hash.buffer, policy_hash.size, "policy_hash");
123     memcpy (public_info.nvPublic.authPolicy.buffer,
124             policy_hash.buffer,
125             policy_hash.size);
126 
127     rc = Tss2_Sys_NV_DefineSpace (sys_ctx,
128                                   TPM2_RH_PLATFORM,
129                                   &auth_cmd,
130                                   &nv_auth,
131                                   &public_info,
132                                   &auth_rsp);
133     Tss2_Sys_FlushContext (sys_ctx, auth_handle);
134     return_if_error (rc, "Tss2_Sys_NV_DefineSpace");
135 
136     return rc;
137 }
138 
139 static TSS2_RC
teardown_nv(TSS2_SYS_CONTEXT * sys_ctx)140 teardown_nv (TSS2_SYS_CONTEXT *sys_ctx)
141 {
142     TSS2_RC rc;
143     const TSS2L_SYS_AUTH_COMMAND auth_cmd = {
144         .count = 1,
145         .auths = {
146             {
147                 .sessionHandle = TPM2_RS_PW,
148             },
149         },
150     };
151     TSS2L_SYS_AUTH_RESPONSE auth_rsp = { 0, };
152 
153     rc = Tss2_Sys_NV_UndefineSpace (sys_ctx,
154                                     TPM2_RH_PLATFORM,
155                                     NV_INDEX,
156                                     &auth_cmd,
157                                     &auth_rsp);
158     return_if_error (rc, "Tss2_Sys_NV_UndefineSpace");
159 
160     return rc;
161 }
162 
163 /*
164  * This function performs a single write operation to the NV region. This
165  * requires we first create a policy session that satisfies the policy
166  * governing the region. If the write fails we must manually flush the
167  * session since the continueSession flag only guarantees the policy is
168  * flushed after successful command execution.
169  */
170 static TSS2_RC
nv_write(TSS2_SYS_CONTEXT * sys_ctx)171 nv_write (TSS2_SYS_CONTEXT *sys_ctx)
172 {
173     TSS2_RC rc;
174     TSS2L_SYS_AUTH_COMMAND auth_cmd = {
175         .count = 1,
176     };
177     TSS2L_SYS_AUTH_RESPONSE auth_rsp = { 0, };
178     TPM2B_MAX_NV_BUFFER write_data = {
179         .size = 4,
180         .buffer = { 0xff, 0xfe, 0xfd, 0xfc, },
181     };
182 
183     rc = create_policy_session (sys_ctx,
184                                 &auth_cmd.auths[0].sessionHandle);
185     return_if_error (rc, "create_policy_session");
186 
187     rc = Tss2_Sys_NV_Write (sys_ctx,
188                             NV_INDEX,
189                             NV_INDEX,
190                             &auth_cmd,
191                             &write_data,
192                             0,
193                             &auth_rsp);
194     Tss2_Sys_FlushContext (sys_ctx, auth_cmd.auths [0].sessionHandle);
195     return_if_error (rc, "Tss2_Sys_NV_Write");
196 
197     return rc;
198 }
199 /*
200  * This function executes a write operation on the NV region from each
201  * locality. Per the policy applied to the region @ provisioning, the
202  * write command will fail for all localities except 3 and 4.
203  */
204 static TSS2_RC
nv_write_test(TSS2_SYS_CONTEXT * sys_ctx)205 nv_write_test (TSS2_SYS_CONTEXT *sys_ctx)
206 {
207     TSS2_RC rc;
208     uint8_t locality;
209     TSS2_TCTI_CONTEXT *tcti_ctx;
210 
211     LOG_INFO ("TPM NV write with locality policy test");
212 
213     rc = Tss2_Sys_GetTctiContext (sys_ctx, &tcti_ctx);
214     return_if_error (rc, "Tss2_Sys_GetTctiContext");
215 
216     for (locality = 0; locality < 5; ++locality)
217     {
218         LOG_INFO ("%s: writing NV from locality %" PRIu8, __func__, locality);
219         rc = Tss2_Tcti_SetLocality (tcti_ctx, locality);
220         return_if_error (rc, "Tss2_Tcti_SetLocality");
221 
222         rc = nv_write (sys_ctx);
223         switch (locality) {
224             case 0:
225             case 1:
226             case 2:
227                 if (rc != TPM2_RC_LOCALITY) {
228                     LOG_ERROR ("nv_write: Expecting TPM2_RC_LOCALITY, got "
229                                "0x%08" PRIu32, rc);
230                     return 1;
231                 }
232                 break;
233             case 3:
234             case 4:
235                 return_if_error (rc, "nv_write");
236                 break;
237             default: /* locality can only be 0-4 */
238                 assert (false);
239                 break;
240         }
241     }
242     return TSS2_RC_SUCCESS;
243 }
244 /*
245  * This function executes a read command on the NV region from each
246  * locality providing the required auth value (empty). Per the policy
247  * defined a provisioning all should succeed.
248  */
249 static TSS2_RC
nv_read_test(TSS2_SYS_CONTEXT * sys_ctx)250 nv_read_test (TSS2_SYS_CONTEXT *sys_ctx)
251 {
252     TSS2_RC rc;
253     uint8_t locality;
254     TPM2B_MAX_NV_BUFFER nv_buf;
255     TSS2_TCTI_CONTEXT *tcti_ctx;
256     TSS2L_SYS_AUTH_RESPONSE auth_rsp = { 0, };
257     const TSS2L_SYS_AUTH_COMMAND auth_cmd = {
258         .count = 1,
259         .auths = {
260             {
261                 .sessionHandle = TPM2_RS_PW,
262             },
263         },
264     };
265 
266     rc = Tss2_Sys_GetTctiContext (sys_ctx, &tcti_ctx);
267     return_if_error (rc, "Tss2_Sys_GetTctiContext");
268 
269     LOG_INFO ("TPM NV read with auth test");
270     for (locality = 0; locality < 5; ++locality)
271     {
272         rc = Tss2_Tcti_SetLocality (tcti_ctx, locality);
273         return_if_error (rc, "Tss2_Tcti_SetLocality");
274 
275         nv_buf.size = TPM2B_SIZE_MAX (nv_buf);
276         rc = TSS2_RETRY_EXP (Tss2_Sys_NV_Read (sys_ctx,
277                                                NV_INDEX,
278                                                NV_INDEX,
279                                                &auth_cmd,
280                                                4,
281                                                0,
282                                                &nv_buf,
283                                                &auth_rsp));
284         return_if_error (rc, "Tss2_Sys_NV_Read");
285     }
286 
287     rc = Tss2_Tcti_SetLocality (tcti_ctx, 3);
288     return_if_error (rc, "Tss2_Tcti_SetLocality");
289 
290     return rc;
291 }
292 
293 int
test_invoke(TSS2_SYS_CONTEXT * sys_ctx)294 test_invoke (TSS2_SYS_CONTEXT *sys_ctx)
295 {
296     TSS2_RC rc, rc_teardown;
297 
298     rc = setup_nv (sys_ctx);
299     return_if_error (rc, "setup_nv");
300     rc = nv_write_test (sys_ctx);
301     goto_if_error (rc, "nv_write_test", teardown);
302     rc = nv_read_test (sys_ctx);
303     goto_if_error (rc, "nv_read_test", teardown);
304 teardown:
305     rc_teardown = teardown_nv (sys_ctx);
306     return_if_error (rc, "NV policy locality test failed");
307     return_if_error (rc_teardown, "teardown_nv");
308 
309     return rc;
310 }
311