1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved
4 * Author: Jorge Ramirez <jorge@foundries.io>
5 */
6
7 #include <config.h>
8 #include <crypto/crypto.h>
9 #include <se050.h>
10 #include <se050_utils.h>
11 #include <string.h>
12 #include <string_ext.h>
13
14 static const sss_policy_u asym_key = {
15 .type = KPolicy_Asym_Key,
16 .auth_obj_id = 0,
17 .policy = {
18 .asymmkey = {
19 .can_Sign = 1,
20 .can_Verify = 1,
21 .can_Encrypt = 1,
22 .can_Decrypt = 1,
23 .can_KD = 1,
24 .can_Wrap = 1,
25 .can_Write = 1,
26 .can_Gen = 1,
27 .can_Import_Export = 1,
28 .can_KA = 1,
29 .can_Read = 1,
30 .can_Attest = 1,
31 }
32 }
33 };
34
35 static const sss_policy_u common = {
36 .type = KPolicy_Common,
37 .auth_obj_id = 0,
38 .policy = {
39 .common = {
40 .can_Delete = 1,
41 .can_Read = 1,
42 .can_Write = 1,
43 .req_Sm = 1,
44 },
45 },
46 };
47
48 sss_policy_t se050_asym_policy = {
49 .nPolicies = 2,
50 .policies = { &asym_key, &common },
51 };
52
se050_rotate_scp03_keys(struct sss_se05x_ctx * ctx)53 sss_status_t se050_rotate_scp03_keys(struct sss_se05x_ctx *ctx)
54 {
55 struct s050_scp_rotate_cmd cmd = { };
56 sss_status_t status = kStatus_SSS_Fail;
57 struct se050_scp_key cur_keys = { };
58 struct se050_scp_key new_keys = { };
59 SE_Connect_Ctx_t *connect_ctx = NULL;
60 sss_se05x_session_t *session = NULL;
61
62 if (!ctx)
63 return kStatus_SSS_Fail;
64
65 if (IS_ENABLED(CFG_CORE_SE05X_SCP03_PROVISION_WITH_FACTORY_KEYS)) {
66 /* Public */
67 status = se050_scp03_get_keys(&new_keys, SCP03_OFID);
68 if (status != kStatus_SSS_Success)
69 return status;
70 } else {
71 /* Secret */
72 status = se050_scp03_subkey_derive(&new_keys);
73 if (status != kStatus_SSS_Success)
74 return status;
75 }
76
77 status = se050_scp03_get_current_keys(&cur_keys);
78 if (status != kStatus_SSS_Success)
79 return status;
80
81 if (IS_ENABLED(CFG_CORE_SE05X_DISPLAY_SCP03_KEYS)) {
82 IMSG("scp03: current keys");
83 nLog_au8("scp03", 0xff, "dek: ",
84 cur_keys.dek, SE050_SCP03_KEY_SZ);
85 nLog_au8("scp03", 0xff, "mac: ",
86 cur_keys.mac, SE050_SCP03_KEY_SZ);
87 nLog_au8("scp03", 0xff, "enc: ",
88 cur_keys.enc, SE050_SCP03_KEY_SZ);
89 IMSG("scp03: proposed new keys");
90 nLog_au8("scp03", 0xff, "dek: ",
91 new_keys.dek, SE050_SCP03_KEY_SZ);
92 nLog_au8("scp03", 0xff, "mac: ",
93 new_keys.mac, SE050_SCP03_KEY_SZ);
94 nLog_au8("scp03", 0xff, "enc: ",
95 new_keys.enc, SE050_SCP03_KEY_SZ);
96 }
97
98 if (!consttime_memcmp(new_keys.enc, cur_keys.enc, SE050_SCP03_KEY_SZ) &&
99 !consttime_memcmp(new_keys.mac, cur_keys.mac, SE050_SCP03_KEY_SZ) &&
100 !consttime_memcmp(new_keys.dek, cur_keys.dek, SE050_SCP03_KEY_SZ))
101 return kStatus_SSS_Success;
102
103 connect_ctx = &ctx->open_ctx;
104 session = &ctx->session;
105
106 status = se050_scp03_prepare_rotate_cmd(ctx, &cmd, &new_keys);
107 if (status != kStatus_SSS_Success)
108 return status;
109
110 sss_se05x_refresh_session(se050_session, NULL);
111 sss_se05x_session_close(session);
112
113 /* re-open session with same keys */
114 connect_ctx->skip_select_applet = 1;
115 status = sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0,
116 kSSS_ConnectionType_Encrypted,
117 connect_ctx);
118 if (status != kStatus_SSS_Success) {
119 se050_scp03_set_disable();
120 EMSG("scp03 re-open failed, session lost");
121 return kStatus_SSS_Fail;
122 }
123
124 status = se050_scp03_send_rotate_cmd(&session->s_ctx, &cmd);
125 if (status != kStatus_SSS_Success) {
126 EMSG("scp03 keys not updated");
127 return kStatus_SSS_Fail;
128 }
129
130 sss_host_session_close(&ctx->host_session);
131 sss_se05x_session_close(se050_session);
132 memset(ctx, 0, sizeof(*ctx));
133
134 /* open session with new keys */
135 if (IS_ENABLED(CFG_CORE_SE05X_SCP03_PROVISION_WITH_FACTORY_KEYS))
136 se050_scp03_set_enable(SCP03_OFID);
137 else
138 se050_scp03_set_enable(SCP03_DERIVED);
139
140 if (se050_core_early_init(&new_keys)) {
141 se050_scp03_set_disable();
142 EMSG("scp03 keys rejected, session lost");
143 return kStatus_SSS_Fail;
144 }
145
146 return kStatus_SSS_Success;
147 }
148
se050_enable_scp03(sss_se05x_session_t * session)149 sss_status_t se050_enable_scp03(sss_se05x_session_t *session)
150 {
151 struct se050_scp_key keys = { };
152 sss_status_t status = kStatus_SSS_Success;
153 enum se050_scp03_ksrc key_src[] = { SCP03_DERIVED, SCP03_CFG,
154 SCP03_OFID };
155 size_t i = 0;
156
157 if (se050_scp03_enabled())
158 return kStatus_SSS_Success;
159
160 for (i = 0; i < ARRAY_SIZE(key_src); i++) {
161 status = se050_scp03_get_keys(&keys, key_src[i]);
162 if (status != kStatus_SSS_Success)
163 continue;
164
165 if (session->subsystem)
166 sss_se05x_session_close(session);
167
168 if (!se050_core_early_init(&keys)) {
169 se050_scp03_set_enable(key_src[i]);
170 goto out;
171 }
172
173 sss_host_session_close(&se050_ctx.host_session);
174 }
175
176 return kStatus_SSS_Fail;
177 out:
178 if (IS_ENABLED(CFG_CORE_SE05X_SCP03_PROVISION_ON_INIT))
179 return se050_rotate_scp03_keys(&se050_ctx);
180
181 return kStatus_SSS_Success;
182 }
183
se050_session_open(struct sss_se05x_ctx * ctx,struct se050_scp_key * current_keys)184 sss_status_t se050_session_open(struct sss_se05x_ctx *ctx,
185 struct se050_scp_key *current_keys)
186 {
187 sss_status_t status = kStatus_SSS_Fail;
188 SE_Connect_Ctx_t *connect_ctx = NULL;
189 sss_se05x_session_t *session = NULL;
190
191 if (!ctx)
192 return kStatus_SSS_Fail;
193
194 connect_ctx = &ctx->open_ctx;
195 session = &ctx->session;
196 connect_ctx->connType = kType_SE_Conn_Type_T1oI2C;
197 connect_ctx->portName = NULL;
198
199 if (!current_keys) {
200 return sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0,
201 kSSS_ConnectionType_Plain,
202 connect_ctx);
203 }
204
205 status = se050_configure_host(&ctx->host_session,
206 &ctx->host_ks,
207 &ctx->open_ctx,
208 &ctx->se05x_auth,
209 kSSS_AuthType_SCP03,
210 current_keys);
211 if (status != kStatus_SSS_Success)
212 return status;
213
214 return sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0,
215 kSSS_ConnectionType_Encrypted,
216 connect_ctx);
217 }
218
se050_key_store_and_object_init(struct sss_se05x_ctx * ctx)219 sss_status_t se050_key_store_and_object_init(struct sss_se05x_ctx *ctx)
220 {
221 if (!ctx)
222 return kStatus_SSS_Fail;
223
224 return sss_se05x_key_store_context_init(&ctx->ks, &ctx->session);
225 }
226