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 <inttypes.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include "tss2_sys.h"
16 
17 #include "context-util.h"
18 #include "sys-util.h"
19 #include "session-util.h"
20 #include "util/aux_util.h"
21 #define LOGMODULE test
22 #include "util/log.h"
23 
24 #define NV_PS_INDEX_SIZE 34
25 #define INDEX_LCP_OWN 0x01400001
26 #define INDEX_LCP_SUP 0x01800001
27 
28 #define TPM2B_SIZE_MAX(type) (sizeof (type) - 2)
29 
30 const TSS2L_SYS_AUTH_COMMAND auth_cmd_null_pwd = {
31     .count = 1,
32     .auths = {
33         {
34             .sessionHandle = TPM2_RS_PW,
35         },
36     },
37 };
38 
39 static TSS2_RC
create_policy_session(TSS2_SYS_CONTEXT * sys_ctx,TPMI_SH_AUTH_SESSION * handle)40 create_policy_session (
41     TSS2_SYS_CONTEXT *sys_ctx,
42     TPMI_SH_AUTH_SESSION *handle)
43 {
44     TSS2_RC rc;
45     TPM2B_ENCRYPTED_SECRET salt = { 0 };
46     TPM2B_NONCE nonce = {
47         .size = GetDigestSize (TPM2_ALG_SHA1),
48     };
49     TPM2B_NONCE nonce_tpm = { 0, };
50     TPMT_SYM_DEF symmetric = {
51         .algorithm = TPM2_ALG_NULL,
52     };
53 
54     rc = Tss2_Sys_StartAuthSession (sys_ctx,
55                                     TPM2_RH_NULL,
56                                     TPM2_RH_NULL,
57                                     0,
58                                     &nonce,
59                                     &salt,
60                                     TPM2_SE_POLICY,
61                                     &symmetric,
62                                     TPM2_ALG_SHA1,
63                                     handle,
64                                     &nonce_tpm,
65                                     0);
66     return_if_error (rc, "Tss2_Sys_StartAuthSession");
67     return TSS2_RC_SUCCESS;
68 }
69 
70 static TSS2_RC
setup_nv(TSS2_SYS_CONTEXT * sys_ctx,TPMI_RH_NV_INDEX index)71 setup_nv (TSS2_SYS_CONTEXT *sys_ctx,
72           TPMI_RH_NV_INDEX index)
73 {
74     TSS2_RC rc;
75     TPMI_SH_AUTH_SESSION auth_handle;
76     TPM2B_DIGEST  policy_hash = {
77         .size = TPM2B_SIZE_MAX (policy_hash),
78     };
79     TPM2B_AUTH  nv_auth = { 0, };
80     TSS2L_SYS_AUTH_RESPONSE auth_rsp;
81     TPM2B_NV_PUBLIC public_info = {
82         .nvPublic = {
83             .nameAlg = TPM2_ALG_SHA1,
84             .attributes = TPMA_NV_AUTHREAD | TPMA_NV_AUTHWRITE |
85                 TPMA_NV_PLATFORMCREATE | TPMA_NV_WRITEDEFINE | TPMA_NV_ORDERLY,
86             .dataSize = NV_PS_INDEX_SIZE,
87             .nvIndex = index,
88         },
89     };
90 
91     rc = create_policy_session (sys_ctx, &auth_handle);
92     return_if_error (rc, "create_policy_session");
93 
94     rc = Tss2_Sys_PolicyGetDigest (sys_ctx, auth_handle, 0, &policy_hash, 0);
95     return_if_error (rc, "Tss2_Sys_PolicyGetDigest");
96     LOGBLOB_INFO (policy_hash.buffer, policy_hash.size, "policy_hash");
97 
98     rc = Tss2_Sys_NV_DefineSpace (sys_ctx,
99                                   TPM2_RH_PLATFORM,
100                                   &auth_cmd_null_pwd,
101                                   &nv_auth,
102                                   &public_info,
103                                   &auth_rsp);
104     return_if_error (rc, "Tss2_Sys_NV_DefineSpace");
105 
106     rc = Tss2_Sys_FlushContext (sys_ctx, auth_handle);
107     return_if_error (rc, "Tss2_Sys_FlushContext");
108 
109     return TSS2_RC_SUCCESS;
110 }
111 
112 static TSS2_RC
nv_write_read_test(TSS2_SYS_CONTEXT * sys_ctx,TPMI_RH_NV_INDEX index)113 nv_write_read_test (TSS2_SYS_CONTEXT *sys_ctx,
114                     TPMI_RH_NV_INDEX index)
115 {
116     TSS2_RC rc;
117     TPM2B_MAX_NV_BUFFER write_data = {
118         .size = 4,
119         .buffer = { 0xde, 0xad, 0xbe, 0xef },
120     };
121     TPM2B_MAX_NV_BUFFER nv_buf = { 0, };
122     TSS2L_SYS_AUTH_RESPONSE auth_resp = { 0, };
123 
124     rc = TSS2_RETRY_EXP (Tss2_Sys_NV_Write (sys_ctx,
125                                             index,
126                                             index,
127                                             &auth_cmd_null_pwd,
128                                             &write_data,
129                                             0,
130                                             &auth_resp));
131     return_if_error (rc, "Tss2_Sys_NV_Write");
132 
133     rc = Tss2_Sys_NV_Read (sys_ctx,
134                            index,
135                            index,
136                            &auth_cmd_null_pwd,
137                            4,
138                            0,
139                            &nv_buf,
140                            &auth_resp);
141     return_if_error (rc, "Tss2_Sys_NV_Read");
142 
143     if (memcmp (nv_buf.buffer, write_data.buffer, write_data.size) != 0) {
144         LOG_ERROR ("%s: data read from NV is different from data written",
145                    __func__);
146         LOGBLOB_DEBUG (write_data.buffer, write_data.size, "write_data");
147         LOGBLOB_DEBUG (nv_buf.buffer, nv_buf.size, "nv_buf");
148         return 1;
149     }
150 
151     return TSS2_RC_SUCCESS;
152 }
153 
154 static TSS2_RC
teardown_nv(TSS2_SYS_CONTEXT * sys_ctx,TPMI_RH_NV_INDEX index)155 teardown_nv (TSS2_SYS_CONTEXT *sys_ctx,
156              TPMI_RH_NV_INDEX index)
157 {
158     TSS2_RC rc;
159     TSS2L_SYS_AUTH_RESPONSE auth_resp = { 0, };
160 
161     rc = Tss2_Sys_NV_UndefineSpace (sys_ctx,
162                                     TPM2_RH_PLATFORM,
163                                     index,
164                                     &auth_cmd_null_pwd,
165                                     &auth_resp);
166     return_if_error (rc, "Tss2_Sys_NV_UndefineSpace");
167 
168     return TSS2_RC_SUCCESS;
169 }
170 
171 int
test_invoke(TSS2_SYS_CONTEXT * sys_ctx)172 test_invoke (TSS2_SYS_CONTEXT *sys_ctx)
173 {
174     TSS2_RC rc, rc_teardown;
175 
176     rc = setup_nv (sys_ctx, INDEX_LCP_OWN);
177     return_if_error (rc, "setup_nv for INDEX_LCP_OWN");
178     rc = nv_write_read_test (sys_ctx, INDEX_LCP_OWN);
179     LOG_ERROR ("nv_write_read_test for INDEX_LCP_OWN");
180     rc_teardown = teardown_nv (sys_ctx, INDEX_LCP_OWN);
181     return_if_error (rc, "INDEX_LCP_OWN test");
182     return_if_error (rc_teardown, "teardown_nv for INDEX_LCP_OWN");
183 
184     rc = setup_nv (sys_ctx, INDEX_LCP_SUP);
185     return_if_error (rc, "setup_nv for INDEX_LCP_SUP");
186     rc = nv_write_read_test (sys_ctx, INDEX_LCP_SUP);
187     LOG_ERROR ("nv_write_read_test for INDEX_LCP_SUP");
188     rc_teardown = teardown_nv (sys_ctx, INDEX_LCP_SUP);
189     return_if_error (rc, "INDEX_LCP_SUP test");
190     return_if_error (rc_teardown, "teardown_nv for INDEX_LCP_SUP");
191 
192     return 0;
193 }
194