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 			.req_Sm = 1,
41 		},
42 	},
43 };
44 
45 sss_policy_t se050_asym_policy = {
46 	.nPolicies = 2,
47 	.policies = { &asym_key, &common },
48 };
49 
se050_rotate_scp03_keys(struct sss_se05x_ctx * ctx)50 sss_status_t se050_rotate_scp03_keys(struct sss_se05x_ctx *ctx)
51 {
52 	struct s050_scp_rotate_cmd cmd = { };
53 	sss_status_t status = kStatus_SSS_Fail;
54 	struct se050_scp_key cur_keys = { };
55 	struct se050_scp_key new_keys = { };
56 	SE_Connect_Ctx_t *connect_ctx = NULL;
57 	sss_se05x_session_t *session = NULL;
58 
59 	if (!ctx)
60 		return kStatus_SSS_Fail;
61 
62 	status = se050_scp03_subkey_derive(&new_keys);
63 	if (status != kStatus_SSS_Success)
64 		return status;
65 
66 	status = se050_scp03_get_current_keys(&cur_keys);
67 	if (status != kStatus_SSS_Success)
68 		return status;
69 
70 	if (IS_ENABLED(CFG_CORE_SE05X_DISPLAY_SCP03_KEYS)) {
71 		IMSG("scp03: current keys");
72 		nLog_au8("scp03", 0xff, "dek: ",
73 			 cur_keys.dek, SE050_SCP03_KEY_SZ);
74 		nLog_au8("scp03", 0xff, "mac: ",
75 			 cur_keys.mac, SE050_SCP03_KEY_SZ);
76 		nLog_au8("scp03", 0xff, "enc: ",
77 			 cur_keys.enc, SE050_SCP03_KEY_SZ);
78 		IMSG("scp03: proposed new keys");
79 		nLog_au8("scp03", 0xff, "dek: ",
80 			 new_keys.dek, SE050_SCP03_KEY_SZ);
81 		nLog_au8("scp03", 0xff, "mac: ",
82 			 new_keys.mac, SE050_SCP03_KEY_SZ);
83 		nLog_au8("scp03", 0xff, "enc: ",
84 			 new_keys.enc, SE050_SCP03_KEY_SZ);
85 	}
86 
87 	if (!memcmp(new_keys.enc, cur_keys.enc, SE050_SCP03_KEY_SZ) &&
88 	    !memcmp(new_keys.mac, cur_keys.mac, SE050_SCP03_KEY_SZ) &&
89 	    !memcmp(new_keys.dek, cur_keys.dek, SE050_SCP03_KEY_SZ))
90 		return kStatus_SSS_Success;
91 
92 	connect_ctx = &ctx->open_ctx;
93 	session = &ctx->session;
94 
95 	status = se050_scp03_prepare_rotate_cmd(ctx, &cmd, &new_keys);
96 	if (status != kStatus_SSS_Success)
97 		return status;
98 
99 	sss_se05x_refresh_session(se050_session, NULL);
100 	sss_se05x_session_close(session);
101 
102 	/* re-open session with same keys */
103 	connect_ctx->skip_select_applet = 1;
104 	status = sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0,
105 					kSSS_ConnectionType_Encrypted,
106 					connect_ctx);
107 	if (status != kStatus_SSS_Success) {
108 		se050_scp03_set_disable();
109 		EMSG("scp03 re-open failed, session lost");
110 		return kStatus_SSS_Fail;
111 	}
112 
113 	status = se050_scp03_send_rotate_cmd(&session->s_ctx, &cmd);
114 	if (status != kStatus_SSS_Success) {
115 		EMSG("scp03 keys not updated");
116 		return kStatus_SSS_Fail;
117 	}
118 
119 	sss_host_session_close(&ctx->host_session);
120 	sss_se05x_session_close(se050_session);
121 	memset(ctx, 0, sizeof(*ctx));
122 
123 	/* open session with new keys */
124 	se050_scp03_set_enable(SCP03_DERIVED);
125 	if (se050_core_early_init(&new_keys)) {
126 		se050_scp03_set_disable();
127 		EMSG("scp03 keys rejected, session lost");
128 		return kStatus_SSS_Fail;
129 	}
130 
131 	return kStatus_SSS_Success;
132 }
133 
se050_enable_scp03(sss_se05x_session_t * session)134 sss_status_t se050_enable_scp03(sss_se05x_session_t *session)
135 {
136 	struct se050_scp_key keys = { };
137 	sss_status_t status = kStatus_SSS_Success;
138 	enum se050_scp03_ksrc key_src[] = { SCP03_CFG, SCP03_DERIVED,
139 		SCP03_OFID };
140 	size_t i = 0;
141 
142 	if (se050_scp03_enabled())
143 		return kStatus_SSS_Success;
144 
145 	for (i = 0; i < ARRAY_SIZE(key_src); i++) {
146 		status = se050_scp03_get_keys(&keys, key_src[i]);
147 		if (status != kStatus_SSS_Success)
148 			continue;
149 
150 		if (session->subsystem)
151 			sss_se05x_session_close(session);
152 
153 		if (!se050_core_early_init(&keys)) {
154 			se050_scp03_set_enable(key_src[i]);
155 			return kStatus_SSS_Success;
156 		}
157 
158 		sss_host_session_close(&se050_ctx.host_session);
159 	}
160 
161 	return kStatus_SSS_Fail;
162 }
163 
se050_session_open(struct sss_se05x_ctx * ctx,struct se050_scp_key * current_keys)164 sss_status_t se050_session_open(struct sss_se05x_ctx *ctx,
165 				struct se050_scp_key *current_keys)
166 {
167 	sss_status_t status = kStatus_SSS_Fail;
168 	SE_Connect_Ctx_t *connect_ctx = NULL;
169 	sss_se05x_session_t *session = NULL;
170 
171 	if (!ctx)
172 		return kStatus_SSS_Fail;
173 
174 	connect_ctx = &ctx->open_ctx;
175 	session = &ctx->session;
176 	connect_ctx->connType = kType_SE_Conn_Type_T1oI2C;
177 	connect_ctx->portName = NULL;
178 
179 	if (!current_keys) {
180 		return sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0,
181 					      kSSS_ConnectionType_Plain,
182 					      connect_ctx);
183 	}
184 
185 	status = se050_configure_host(&ctx->host_session,
186 				      &ctx->host_ks,
187 				      &ctx->open_ctx,
188 				      &ctx->se05x_auth,
189 				      kSSS_AuthType_SCP03,
190 				      current_keys);
191 	if (status != kStatus_SSS_Success)
192 		return status;
193 
194 	return sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0,
195 				      kSSS_ConnectionType_Encrypted,
196 				      connect_ctx);
197 }
198 
se050_key_store_and_object_init(struct sss_se05x_ctx * ctx)199 sss_status_t se050_key_store_and_object_init(struct sss_se05x_ctx *ctx)
200 {
201 	if (!ctx)
202 		return kStatus_SSS_Fail;
203 
204 	return sss_se05x_key_store_context_init(&ctx->ks, &ctx->session);
205 }
206