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