1 /*
2  * Copyright (c) 2017, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 #include <inttypes.h>
28 
29 #include <tee_internal_api.h>
30 #include <tee_internal_api_extensions.h>
31 
32 #include <aes_ta.h>
33 
34 #define AES128_KEY_BIT_SIZE		128
35 #define AES128_KEY_BYTE_SIZE		(AES128_KEY_BIT_SIZE / 8)
36 #define AES256_KEY_BIT_SIZE		256
37 #define AES256_KEY_BYTE_SIZE		(AES256_KEY_BIT_SIZE / 8)
38 
39 /*
40  * Ciphering context: each opened session relates to a cipehring operation.
41  * - configure the AES flavour from a command.
42  * - load key from a command (here the key is provided by the REE)
43  * - reset init vector (here IV is provided by the REE)
44  * - cipher a buffer frame (here input and output buffers are non-secure)
45  */
46 struct aes_cipher {
47 	uint32_t algo;			/* AES flavour */
48 	uint32_t mode;			/* Encode or decode */
49 	uint32_t key_size;		/* AES key size in byte */
50 	TEE_OperationHandle op_handle;	/* AES ciphering operation */
51 	TEE_ObjectHandle key_handle;	/* transient object to load the key */
52 };
53 
54 /*
55  * Few routines to convert IDs from TA API into IDs from OP-TEE.
56  */
ta2tee_algo_id(uint32_t param,uint32_t * algo)57 static TEE_Result ta2tee_algo_id(uint32_t param, uint32_t *algo)
58 {
59 	switch (param) {
60 	case TA_AES_ALGO_ECB:
61 		*algo = TEE_ALG_AES_ECB_NOPAD;
62 		return TEE_SUCCESS;
63 	case TA_AES_ALGO_CBC:
64 		*algo = TEE_ALG_AES_CBC_NOPAD;
65 		return TEE_SUCCESS;
66 	case TA_AES_ALGO_CTR:
67 		*algo = TEE_ALG_AES_CTR;
68 		return TEE_SUCCESS;
69 	default:
70 		EMSG("Invalid algo %u", param);
71 		return TEE_ERROR_BAD_PARAMETERS;
72 	}
73 }
ta2tee_key_size(uint32_t param,uint32_t * key_size)74 static TEE_Result ta2tee_key_size(uint32_t param, uint32_t *key_size)
75 {
76 	switch (param) {
77 	case AES128_KEY_BYTE_SIZE:
78 	case AES256_KEY_BYTE_SIZE:
79 		*key_size = param;
80 		return TEE_SUCCESS;
81 	default:
82 		EMSG("Invalid key size %u", param);
83 		return TEE_ERROR_BAD_PARAMETERS;
84 	}
85 }
ta2tee_mode_id(uint32_t param,uint32_t * mode)86 static TEE_Result ta2tee_mode_id(uint32_t param, uint32_t *mode)
87 {
88 	switch (param) {
89 	case TA_AES_MODE_ENCODE:
90 		*mode = TEE_MODE_ENCRYPT;
91 		return TEE_SUCCESS;
92 	case TA_AES_MODE_DECODE:
93 		*mode = TEE_MODE_DECRYPT;
94 		return TEE_SUCCESS;
95 	default:
96 		EMSG("Invalid mode %u", param);
97 		return TEE_ERROR_BAD_PARAMETERS;
98 	}
99 }
100 
101 /*
102  * Process command TA_AES_CMD_PREPARE. API in aes_ta.h
103  *
104  * Allocate resources required for the ciphering operation.
105  * During ciphering operation, when expect client can:
106  * - update the key materials (provided by client)
107  * - reset the initial vector (provided by client)
108  * - cipher an input buffer into an output buffer (provided by client)
109  */
alloc_resources(void * session,uint32_t param_types,TEE_Param params[4])110 static TEE_Result alloc_resources(void *session, uint32_t param_types,
111 				  TEE_Param params[4])
112 {
113 	const uint32_t exp_param_types =
114 		TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
115 				TEE_PARAM_TYPE_VALUE_INPUT,
116 				TEE_PARAM_TYPE_VALUE_INPUT,
117 				TEE_PARAM_TYPE_NONE);
118 	struct aes_cipher *sess;
119 	TEE_Attribute attr;
120 	TEE_Result res;
121 	char *key;
122 
123 	/* Get ciphering context from session ID */
124 	DMSG("Session %p: get ciphering resources", session);
125 	sess = (struct aes_cipher *)session;
126 
127 	/* Safely get the invocation parameters */
128 	if (param_types != exp_param_types)
129 		return TEE_ERROR_BAD_PARAMETERS;
130 
131 	res = ta2tee_algo_id(params[0].value.a, &sess->algo);
132 	if (res != TEE_SUCCESS)
133 		return res;
134 
135 	res = ta2tee_key_size(params[1].value.a, &sess->key_size);
136 	if (res != TEE_SUCCESS)
137 		return res;
138 
139 	res = ta2tee_mode_id(params[2].value.a, &sess->mode);
140 	if (res != TEE_SUCCESS)
141 		return res;
142 
143 	/*
144 	 * Ready to allocate the resources which are:
145 	 * - an operation handle, for an AES ciphering of given configuration
146 	 * - a transient object that will be use to load the key materials
147 	 *   into the AES ciphering operation.
148 	 */
149 
150 	/* Free potential previous operation */
151 	if (sess->op_handle != TEE_HANDLE_NULL)
152 		TEE_FreeOperation(sess->op_handle);
153 
154 	/* Allocate operation: AES/CTR, mode and size from params */
155 	res = TEE_AllocateOperation(&sess->op_handle,
156 				    sess->algo,
157 				    sess->mode,
158 				    sess->key_size * 8);
159 	if (res != TEE_SUCCESS) {
160 		EMSG("Failed to allocate operation");
161 		sess->op_handle = TEE_HANDLE_NULL;
162 		goto err;
163 	}
164 
165 	/* Free potential previous transient object */
166 	if (sess->key_handle != TEE_HANDLE_NULL)
167 		TEE_FreeTransientObject(sess->key_handle);
168 
169 	/* Allocate transient object according to target key size */
170 	res = TEE_AllocateTransientObject(TEE_TYPE_AES,
171 					  sess->key_size * 8,
172 					  &sess->key_handle);
173 	if (res != TEE_SUCCESS) {
174 		EMSG("Failed to allocate transient object");
175 		sess->key_handle = TEE_HANDLE_NULL;
176 		goto err;
177 	}
178 
179 	/*
180 	 * When loading a key in the cipher session, set_aes_key()
181 	 * will reset the operation and load a key. But we cannot
182 	 * reset and operation that has no key yet (GPD TEE Internal
183 	 * Core API Specification – Public Release v1.1.1, section
184 	 * 6.2.5 TEE_ResetOperation). In consequence, we will load a
185 	 * dummy key in the operation so that operation can be reset
186 	 * when updating the key.
187 	 */
188 	key = TEE_Malloc(sess->key_size, 0);
189 	if (!key) {
190 		res = TEE_ERROR_OUT_OF_MEMORY;
191 		goto err;
192 	}
193 
194 	TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, sess->key_size);
195 
196 	res = TEE_PopulateTransientObject(sess->key_handle, &attr, 1);
197 	if (res != TEE_SUCCESS) {
198 		EMSG("TEE_PopulateTransientObject failed, %x", res);
199 		goto err;
200 	}
201 
202 	res = TEE_SetOperationKey(sess->op_handle, sess->key_handle);
203 	if (res != TEE_SUCCESS) {
204 		EMSG("TEE_SetOperationKey failed %x", res);
205 		goto err;
206 	}
207 
208 	return res;
209 
210 err:
211 	if (sess->op_handle != TEE_HANDLE_NULL)
212 		TEE_FreeOperation(sess->op_handle);
213 	sess->op_handle = TEE_HANDLE_NULL;
214 
215 	if (sess->key_handle != TEE_HANDLE_NULL)
216 		TEE_FreeTransientObject(sess->key_handle);
217 	sess->key_handle = TEE_HANDLE_NULL;
218 
219 	return res;
220 }
221 
222 /*
223  * Process command TA_AES_CMD_SET_KEY. API in aes_ta.h
224  */
set_aes_key(void * session,uint32_t param_types,TEE_Param params[4])225 static TEE_Result set_aes_key(void *session, uint32_t param_types,
226 				TEE_Param params[4])
227 {
228 	const uint32_t exp_param_types =
229 		TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
230 				TEE_PARAM_TYPE_NONE,
231 				TEE_PARAM_TYPE_NONE,
232 				TEE_PARAM_TYPE_NONE);
233 	struct aes_cipher *sess;
234 	TEE_Attribute attr;
235 	TEE_Result res;
236 	uint32_t key_sz;
237 	char *key;
238 
239 	/* Get ciphering context from session ID */
240 	DMSG("Session %p: load key material", session);
241 	sess = (struct aes_cipher *)session;
242 
243 	/* Safely get the invocation parameters */
244 	if (param_types != exp_param_types)
245 		return TEE_ERROR_BAD_PARAMETERS;
246 
247 	key = params[0].memref.buffer;
248 	key_sz = params[0].memref.size;
249 
250 	if (key_sz != sess->key_size) {
251 		EMSG("Wrong key size %" PRIu32 ", expect %" PRIu32 " bytes",
252 		     key_sz, sess->key_size);
253 		return TEE_ERROR_BAD_PARAMETERS;
254 	}
255 
256 	/*
257 	 * Load the key material into the configured operation
258 	 * - create a secret key attribute with the key material
259 	 *   TEE_InitRefAttribute()
260 	 * - reset transient object and load attribute data
261 	 *   TEE_ResetTransientObject()
262 	 *   TEE_PopulateTransientObject()
263 	 * - load the key (transient object) into the ciphering operation
264 	 *   TEE_SetOperationKey()
265 	 *
266 	 * TEE_SetOperationKey() requires operation to be in "initial state".
267 	 * We can use TEE_ResetOperation() to reset the operation but this
268 	 * API cannot be used on operation with key(s) not yet set. Hence,
269 	 * when allocating the operation handle, we load a dummy key.
270 	 * Thus, set_key sequence always reset then set key on operation.
271 	 */
272 
273 	TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_sz);
274 
275 	TEE_ResetTransientObject(sess->key_handle);
276 	res = TEE_PopulateTransientObject(sess->key_handle, &attr, 1);
277 	if (res != TEE_SUCCESS) {
278 		EMSG("TEE_PopulateTransientObject failed, %x", res);
279 		return res;
280 	}
281 
282 	TEE_ResetOperation(sess->op_handle);
283 	res = TEE_SetOperationKey(sess->op_handle, sess->key_handle);
284 	if (res != TEE_SUCCESS) {
285 		EMSG("TEE_SetOperationKey failed %x", res);
286 		return res;
287 	}
288 
289 	return res;
290 }
291 
292 /*
293  * Process command TA_AES_CMD_SET_IV. API in aes_ta.h
294  */
reset_aes_iv(void * session,uint32_t param_types,TEE_Param params[4])295 static TEE_Result reset_aes_iv(void *session, uint32_t param_types,
296 				TEE_Param params[4])
297 {
298 	const uint32_t exp_param_types =
299 		TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
300 				TEE_PARAM_TYPE_NONE,
301 				TEE_PARAM_TYPE_NONE,
302 				TEE_PARAM_TYPE_NONE);
303 	struct aes_cipher *sess;
304 	size_t iv_sz;
305 	char *iv;
306 
307 	/* Get ciphering context from session ID */
308 	DMSG("Session %p: reset initial vector", session);
309 	sess = (struct aes_cipher *)session;
310 
311 	/* Safely get the invocation parameters */
312 	if (param_types != exp_param_types)
313 		return TEE_ERROR_BAD_PARAMETERS;
314 
315 	iv = params[0].memref.buffer;
316 	iv_sz = params[0].memref.size;
317 
318 	/*
319 	 * Init cipher operation with the initialization vector.
320 	 */
321 	TEE_CipherInit(sess->op_handle, iv, iv_sz);
322 
323 	return TEE_SUCCESS;
324 }
325 
326 /*
327  * Process command TA_AES_CMD_CIPHER. API in aes_ta.h
328  */
cipher_buffer(void * session,uint32_t param_types,TEE_Param params[4])329 static TEE_Result cipher_buffer(void *session, uint32_t param_types,
330 				TEE_Param params[4])
331 {
332 	const uint32_t exp_param_types =
333 		TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
334 				TEE_PARAM_TYPE_MEMREF_OUTPUT,
335 				TEE_PARAM_TYPE_NONE,
336 				TEE_PARAM_TYPE_NONE);
337 	struct aes_cipher *sess;
338 
339 	/* Get ciphering context from session ID */
340 	DMSG("Session %p: cipher buffer", session);
341 	sess = (struct aes_cipher *)session;
342 
343 	/* Safely get the invocation parameters */
344 	if (param_types != exp_param_types)
345 		return TEE_ERROR_BAD_PARAMETERS;
346 
347 	if (params[1].memref.size < params[0].memref.size) {
348 		EMSG("Bad sizes: in %d, out %d", params[0].memref.size,
349 						 params[1].memref.size);
350 		return TEE_ERROR_BAD_PARAMETERS;
351 	}
352 
353 	if (sess->op_handle == TEE_HANDLE_NULL)
354 		return TEE_ERROR_BAD_STATE;
355 
356 	/*
357 	 * Process ciphering operation on provided buffers
358 	 */
359 	return TEE_CipherUpdate(sess->op_handle,
360 				params[0].memref.buffer, params[0].memref.size,
361 				params[1].memref.buffer, &params[1].memref.size);
362 }
363 
TA_CreateEntryPoint(void)364 TEE_Result TA_CreateEntryPoint(void)
365 {
366 	/* Nothing to do */
367 	return TEE_SUCCESS;
368 }
369 
TA_DestroyEntryPoint(void)370 void TA_DestroyEntryPoint(void)
371 {
372 	/* Nothing to do */
373 }
374 
TA_OpenSessionEntryPoint(uint32_t __unused param_types,TEE_Param __unused params[4],void __unused ** session)375 TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types,
376 					TEE_Param __unused params[4],
377 					void __unused **session)
378 {
379 	struct aes_cipher *sess;
380 
381 	/*
382 	 * Allocate and init ciphering materials for the session.
383 	 * The address of the structure is used as session ID for
384 	 * the client.
385 	 */
386 	sess = TEE_Malloc(sizeof(*sess), 0);
387 	if (!sess)
388 		return TEE_ERROR_OUT_OF_MEMORY;
389 
390 	sess->key_handle = TEE_HANDLE_NULL;
391 	sess->op_handle = TEE_HANDLE_NULL;
392 
393 	*session = (void *)sess;
394 	DMSG("Session %p: newly allocated", *session);
395 
396 	return TEE_SUCCESS;
397 }
398 
TA_CloseSessionEntryPoint(void * session)399 void TA_CloseSessionEntryPoint(void *session)
400 {
401 	struct aes_cipher *sess;
402 
403 	/* Get ciphering context from session ID */
404 	DMSG("Session %p: release session", session);
405 	sess = (struct aes_cipher *)session;
406 
407 	/* Release the session resources */
408 	if (sess->key_handle != TEE_HANDLE_NULL)
409 		TEE_FreeTransientObject(sess->key_handle);
410 	if (sess->op_handle != TEE_HANDLE_NULL)
411 		TEE_FreeOperation(sess->op_handle);
412 	TEE_Free(sess);
413 }
414 
TA_InvokeCommandEntryPoint(void * session,uint32_t cmd,uint32_t param_types,TEE_Param params[4])415 TEE_Result TA_InvokeCommandEntryPoint(void *session,
416 					uint32_t cmd,
417 					uint32_t param_types,
418 					TEE_Param params[4])
419 {
420 	switch (cmd) {
421 	case TA_AES_CMD_PREPARE:
422 		return alloc_resources(session, param_types, params);
423 	case TA_AES_CMD_SET_KEY:
424 		return set_aes_key(session, param_types, params);
425 	case TA_AES_CMD_SET_IV:
426 		return reset_aes_iv(session, param_types, params);
427 	case TA_AES_CMD_CIPHER:
428 		return cipher_buffer(session, param_types, params);
429 	default:
430 		EMSG("Command ID 0x%x is not supported", cmd);
431 		return TEE_ERROR_NOT_SUPPORTED;
432 	}
433 }
434