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