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