xref: /optee_os/ta/trusted_keys/entry.c (revision c84eee6397bb8ae0745d9aa24b5228a58793378b)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2019-2020, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <pta_system.h>
8 #include <string.h>
9 #include <string_ext.h>
10 #include <tee_internal_api.h>
11 #include <tee_internal_api_extensions.h>
12 #include <trusted_keys.h>
13 #include <util.h>
14 
15 #define IV_SIZE			16
16 #define TAG_SIZE		16
17 #define MAX_BUF_SIZE		512
18 
19 /*
20  * Acronym:
21  *
22  * TK - Trusted Key
23  */
24 
25 struct tk_blob_hdr {
26 	uint8_t reserved;
27 	uint8_t iv[IV_SIZE];
28 	uint8_t tag[TAG_SIZE];
29 	uint8_t enc_key[];
30 };
31 
32 static TEE_Result get_random(uint32_t types, TEE_Param params[TEE_NUM_PARAMS])
33 {
34 	DMSG("Invoked TA_CMD_GET_RANDOM");
35 
36 	if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
37 				     TEE_PARAM_TYPE_NONE,
38 				     TEE_PARAM_TYPE_NONE,
39 				     TEE_PARAM_TYPE_NONE))
40 		return TEE_ERROR_BAD_PARAMETERS;
41 
42 	if (!params[0].memref.buffer || !params[0].memref.size)
43 		return TEE_ERROR_BAD_PARAMETERS;
44 
45 	TEE_GenerateRandom(params[0].memref.buffer, params[0].memref.size);
46 
47 	return TEE_SUCCESS;
48 }
49 
50 static TEE_Result derive_unique_key(uint8_t *key, uint16_t key_size,
51 				    uint8_t *extra, uint16_t extra_size)
52 {
53 	TEE_TASessionHandle sess = TEE_HANDLE_NULL;
54 	TEE_Param params[TEE_NUM_PARAMS] = { };
55 	TEE_Result res = TEE_ERROR_GENERIC;
56 	uint32_t ret_orig = 0;
57 	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
58 					       TEE_PARAM_TYPE_MEMREF_OUTPUT,
59 					       TEE_PARAM_TYPE_NONE,
60 					       TEE_PARAM_TYPE_NONE);
61 
62 	res = TEE_OpenTASession(&(const TEE_UUID)PTA_SYSTEM_UUID,
63 				TEE_TIMEOUT_INFINITE, 0, NULL, &sess,
64 				&ret_orig);
65 	if (res)
66 		return res;
67 
68 	if (extra && extra_size) {
69 		params[0].memref.buffer = extra;
70 		params[0].memref.size = extra_size;
71 	}
72 
73 	params[1].memref.buffer = key;
74 	params[1].memref.size = key_size;
75 
76 	res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
77 				  PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY,
78 				  param_types, params, &ret_orig);
79 
80 	TEE_CloseTASession(sess);
81 
82 	return res;
83 }
84 
85 static TEE_Result huk_ae_encrypt(TEE_OperationHandle crypto_op, uint8_t *in,
86 				 uint32_t in_sz, uint8_t *out, uint32_t *out_sz)
87 {
88 	TEE_Result res = TEE_ERROR_GENERIC;
89 	struct tk_blob_hdr *hdr = (struct tk_blob_hdr *)out;
90 	uint32_t enc_key_len = in_sz;
91 	uint32_t tag_len = TAG_SIZE;
92 
93 	hdr->reserved = 0;
94 	TEE_GenerateRandom(hdr->iv, IV_SIZE);
95 
96 	res = TEE_AEInit(crypto_op, hdr->iv, IV_SIZE, TAG_SIZE * 8, 0, 0);
97 	if (res)
98 		return res;
99 
100 	res = TEE_AEEncryptFinal(crypto_op, in, in_sz, hdr->enc_key,
101 				 &enc_key_len, hdr->tag, &tag_len);
102 	if (res || tag_len != TAG_SIZE)
103 		return TEE_ERROR_SECURITY;
104 
105 	if (ADD_OVERFLOW(enc_key_len, sizeof(*hdr), out_sz))
106 		return TEE_ERROR_SECURITY;
107 
108 	return res;
109 }
110 
111 static TEE_Result huk_ae_decrypt(TEE_OperationHandle crypto_op, uint8_t *in,
112 				 uint32_t in_sz, uint8_t *out, uint32_t *out_sz)
113 {
114 	TEE_Result res = TEE_ERROR_GENERIC;
115 	struct tk_blob_hdr *hdr = (struct tk_blob_hdr *)in;
116 	uint32_t enc_key_len = 0;
117 
118 	if (SUB_OVERFLOW(in_sz, sizeof(*hdr), &enc_key_len))
119 		return TEE_ERROR_SECURITY;
120 
121 	res = TEE_AEInit(crypto_op, hdr->iv, IV_SIZE, TAG_SIZE * 8, 0, 0);
122 	if (res)
123 		return res;
124 
125 	res = TEE_AEDecryptFinal(crypto_op, hdr->enc_key, enc_key_len, out,
126 				 out_sz, hdr->tag, TAG_SIZE);
127 	if (res)
128 		res = TEE_ERROR_SECURITY;
129 
130 	return res;
131 }
132 
133 static TEE_Result huk_crypt(TEE_OperationMode mode, uint8_t *in, uint32_t in_sz,
134 			    uint8_t *out, uint32_t *out_sz)
135 {
136 	TEE_Result res = TEE_ERROR_GENERIC;
137 	TEE_OperationHandle crypto_op = TEE_HANDLE_NULL;
138 	TEE_ObjectHandle hkey = TEE_HANDLE_NULL;
139 	uint8_t huk_key[TA_DERIVED_KEY_MAX_SIZE] = { };
140 	TEE_Attribute attr = { };
141 
142 	res = TEE_AllocateOperation(&crypto_op, TEE_ALG_AES_GCM, mode,
143 				    sizeof(huk_key) * 8);
144 	if (res)
145 		return res;
146 
147 	res = derive_unique_key(huk_key, sizeof(huk_key), NULL, 0);
148 	if (res) {
149 		EMSG("derive_unique_key failed: returned %#"PRIx32, res);
150 		goto out_op;
151 	}
152 
153 	res = TEE_AllocateTransientObject(TEE_TYPE_AES, sizeof(huk_key) * 8,
154 					  &hkey);
155 	if (res)
156 		goto out_op;
157 
158 	attr.attributeID = TEE_ATTR_SECRET_VALUE;
159 	attr.content.ref.buffer = huk_key;
160 	attr.content.ref.length = sizeof(huk_key);
161 
162 	res = TEE_PopulateTransientObject(hkey, &attr, 1);
163 	if (res)
164 		goto out_key;
165 
166 	res = TEE_SetOperationKey(crypto_op, hkey);
167 	if (res)
168 		goto out_key;
169 
170 	if (mode == TEE_MODE_ENCRYPT) {
171 		res = huk_ae_encrypt(crypto_op, in, in_sz, out, out_sz);
172 		if (res)
173 			EMSG("huk_AE_encrypt failed: returned %#"PRIx32, res);
174 	} else if (mode == TEE_MODE_DECRYPT) {
175 		res = huk_ae_decrypt(crypto_op, in, in_sz, out, out_sz);
176 		if (res)
177 			EMSG("huk_AE_decrypt failed: returned %#"PRIx32, res);
178 	} else {
179 		TEE_Panic(0);
180 	}
181 
182 out_key:
183 	TEE_FreeTransientObject(hkey);
184 out_op:
185 	TEE_FreeOperation(crypto_op);
186 	memzero_explicit(huk_key, sizeof(huk_key));
187 	return res;
188 }
189 
190 static TEE_Result seal_trusted_key(uint32_t types,
191 				   TEE_Param params[TEE_NUM_PARAMS])
192 {
193 	TEE_Result res = TEE_SUCCESS;
194 	uint8_t *in = NULL;
195 	uint32_t in_sz = 0;
196 	uint8_t *out = NULL;
197 	uint32_t out_sz = 0;
198 
199 	DMSG("Invoked TA_CMD_SEAL");
200 
201 	if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
202 				     TEE_PARAM_TYPE_MEMREF_OUTPUT,
203 				     TEE_PARAM_TYPE_NONE,
204 				     TEE_PARAM_TYPE_NONE))
205 		return TEE_ERROR_BAD_PARAMETERS;
206 
207 	in = params[0].memref.buffer;
208 	in_sz = params[0].memref.size;
209 	out = params[1].memref.buffer;
210 	out_sz = params[1].memref.size;
211 
212 	if (!in || !in_sz || in_sz > MAX_BUF_SIZE)
213 		return TEE_ERROR_BAD_PARAMETERS;
214 	if ((!out && out_sz) ||
215 	    (out && !ALIGNMENT_IS_OK(out, struct tk_blob_hdr)) ||
216 	    out_sz > MAX_BUF_SIZE)
217 		return TEE_ERROR_BAD_PARAMETERS;
218 
219 	if ((in_sz + sizeof(struct tk_blob_hdr)) > out_sz) {
220 		params[1].memref.size = in_sz + sizeof(struct tk_blob_hdr);
221 		return TEE_ERROR_SHORT_BUFFER;
222 	}
223 
224 	res = huk_crypt(TEE_MODE_ENCRYPT, in, in_sz, out, &out_sz);
225 	if (res == TEE_SUCCESS) {
226 		assert(out_sz == in_sz + sizeof(struct tk_blob_hdr));
227 		params[1].memref.size = out_sz;
228 	}
229 
230 	return res;
231 }
232 
233 static TEE_Result unseal_trusted_key(uint32_t types,
234 				     TEE_Param params[TEE_NUM_PARAMS])
235 {
236 	TEE_Result res = TEE_SUCCESS;
237 	uint8_t *in = NULL;
238 	uint32_t in_sz = 0;
239 	uint8_t *out = NULL;
240 	uint32_t out_sz = 0;
241 
242 	DMSG("Invoked TA_CMD_UNSEAL");
243 
244 	if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
245 				     TEE_PARAM_TYPE_MEMREF_OUTPUT,
246 				     TEE_PARAM_TYPE_NONE,
247 				     TEE_PARAM_TYPE_NONE))
248 		return TEE_ERROR_BAD_PARAMETERS;
249 
250 	in = params[0].memref.buffer;
251 	in_sz = params[0].memref.size;
252 	out = params[1].memref.buffer;
253 	out_sz = params[1].memref.size;
254 
255 	if (!in || !ALIGNMENT_IS_OK(in, struct tk_blob_hdr) ||
256 	    in_sz <= sizeof(struct tk_blob_hdr) || in_sz > MAX_BUF_SIZE)
257 		return TEE_ERROR_BAD_PARAMETERS;
258 	if ((!out && out_sz) || out_sz > MAX_BUF_SIZE)
259 		return TEE_ERROR_BAD_PARAMETERS;
260 
261 	if (in_sz > (out_sz + sizeof(struct tk_blob_hdr))) {
262 		params[1].memref.size = in_sz - sizeof(struct tk_blob_hdr);
263 		return TEE_ERROR_SHORT_BUFFER;
264 	}
265 
266 	res = huk_crypt(TEE_MODE_DECRYPT, in, in_sz, out, &out_sz);
267 	if (res == TEE_SUCCESS) {
268 		assert(out_sz == in_sz - sizeof(struct tk_blob_hdr));
269 		params[1].memref.size = out_sz;
270 	}
271 
272 	return res;
273 }
274 
275 TEE_Result TA_CreateEntryPoint(void)
276 {
277 	return TEE_SUCCESS;
278 }
279 
280 void TA_DestroyEntryPoint(void)
281 {
282 }
283 
284 TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused,
285 				    TEE_Param params[TEE_NUM_PARAMS] __unused,
286 				    void **session __unused)
287 {
288 	TEE_Result res = TEE_ERROR_GENERIC;
289 	TEE_PropSetHandle h = TEE_HANDLE_NULL;
290 	TEE_Identity id = { };
291 
292 	res = TEE_AllocatePropertyEnumerator(&h);
293 	if (res)
294 		goto out;
295 
296 	TEE_StartPropertyEnumerator(h, TEE_PROPSET_CURRENT_CLIENT);
297 
298 	res = TEE_GetPropertyAsIdentity(h, NULL, &id);
299 	if (res)
300 		goto out;
301 
302 	if (id.login != TEE_LOGIN_REE_KERNEL)
303 		res = TEE_ERROR_ACCESS_DENIED;
304 
305 out:
306 	if (h)
307 		TEE_FreePropertyEnumerator(h);
308 	return res;
309 }
310 
311 void TA_CloseSessionEntryPoint(void *sess __unused)
312 {
313 }
314 
315 TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd,
316 				      uint32_t pt,
317 				      TEE_Param params[TEE_NUM_PARAMS])
318 {
319 	switch (cmd) {
320 	case TA_CMD_GET_RANDOM:
321 		return get_random(pt, params);
322 	case TA_CMD_SEAL:
323 		return seal_trusted_key(pt, params);
324 	case TA_CMD_UNSEAL:
325 		return unseal_trusted_key(pt, params);
326 	default:
327 		EMSG("Command ID %#"PRIx32" is not supported", cmd);
328 		return TEE_ERROR_NOT_SUPPORTED;
329 	}
330 }
331