blob: 96980d2f3b83492075dece1cb0b3fed25a931e12 [file] [log] [blame]
Antonio de Angelis8908f472018-08-31 15:44:25 +01001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <limits.h>
9
10#include "tfm_crypto_defs.h"
11
12/* Pre include Mbed TLS headers */
13#define LIB_PREFIX_NAME __tfm_crypto__
14#include "mbedtls_global_symbols.h"
15
16/* Include the Mbed TLS configuration file, the way Mbed TLS does it
17 * in each of its header files.
18 */
19#if !defined(MBEDTLS_CONFIG_FILE)
20#include "platform/ext/common/tfm_mbedtls_config.h"
21#else
22#include MBEDTLS_CONFIG_FILE
23#endif
24
25#include "psa_crypto.h"
26
27/* The file "psa_crypto_struct.h" contains definitions for
28 * implementation-specific structs that are declared in "psa_crypto.h".
29 */
30#include "psa_crypto_struct.h"
31
32#include "tfm_crypto_api.h"
33#include "crypto_utils.h"
34
35/**
36 * \brief For a TFM_CRYPTO_CIPHER_OPERATION, define the possible
37 * modes of configuration.
38 *
39 */
40enum tfm_crypto_cipher_mode_t {
41 TFM_CRYPTO_CIPHER_MODE_DECRYPT = 0,
42 TFM_CRYPTO_CIPHER_MODE_ENCRYPT = 1,
43};
44
45static enum tfm_crypto_err_t tfm_crypto_cipher_setup(
46 psa_cipher_operation_t *handle,
47 psa_key_slot_t key,
48 psa_algorithm_t alg,
49 enum tfm_crypto_cipher_mode_t c_mode)
50{
51 const mbedtls_cipher_info_t *info = NULL;
52 psa_algorithm_t padding_mode = PSA_ALG_BLOCK_CIPHER_PAD_NONE;
53 psa_key_type_t key_type;
54 size_t key_size;
55 enum tfm_crypto_err_t err;
56 uint8_t key_data[TFM_CRYPTO_MAX_KEY_LENGTH];
57 uint32_t ret;
58 mbedtls_cipher_type_t type = MBEDTLS_CIPHER_NONE;
59 mbedtls_cipher_padding_t mbedtls_padding_mode = MBEDTLS_PADDING_NONE;
60
61 struct psa_cipher_operation_s *operation = NULL;
62
63 /* Validate pointers */
64 err = tfm_crypto_memory_check(handle,
65 sizeof(psa_cipher_operation_t),
66 TFM_MEMORY_ACCESS_RW);
67 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
68 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
69 }
70
71 if (!PSA_ALG_IS_CIPHER(alg)) {
72 return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
73 }
74
75 /* FIXME: Check that key is compatible with alg */
76 err = tfm_crypto_get_key_information(key, &key_type, &key_size);
77 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
78 return err;
79 }
80
81 err = tfm_crypto_export_key(key, &key_data[0], TFM_CRYPTO_MAX_KEY_LENGTH,
82 &key_size);
83 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
84 return err;
85 }
86
87 /* Mbed TLS cipher setup */
88 if (PSA_BYTES_TO_BITS(key_size) == 128) {
89 if (alg == PSA_ALG_CBC_BASE) {
90 type = MBEDTLS_CIPHER_AES_128_CBC;
91 } else if (alg == PSA_ALG_CFB_BASE) {
92 if (c_mode == TFM_CRYPTO_CIPHER_MODE_ENCRYPT) {
93 type = MBEDTLS_CIPHER_AES_128_CFB128;
94 }
95 }
96 }
97
98 /* The requested alg/key/mode is not supported */
99 if (type == MBEDTLS_CIPHER_NONE) {
100 return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
101 }
102
103 /* Allocate the operation context in the TFM space */
104 err = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION, handle);
105 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
106 return err;
107 }
108
109
110
111 /* Look up the corresponding operation context */
112 err = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
113 handle,
114 (void **)&operation);
115
116 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
117 return err;
118 }
119
120 /* Bind the algorithm to the cipher operation */
121 operation->alg = alg;
122
123 /* Mbed TLS cipher init */
124 mbedtls_cipher_init(&(operation->ctx.cipher));
125 info = mbedtls_cipher_info_from_type(type);
126 ret = mbedtls_cipher_setup(&(operation->ctx.cipher), info);
127 if (ret != 0) {
128 /* Release the operation context */
129 tfm_crypto_operation_release(handle);
130 return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
131 }
132
133 /* FIXME: Check based on the algorithm, if we need to have an IV */
134 operation->iv_required = 1;
135
136 /* Bind the key to the cipher operation */
137 operation->key = key;
138 operation->key_set = 1;
139
140 /* Mbed TLS cipher set key */
141 if (c_mode == TFM_CRYPTO_CIPHER_MODE_ENCRYPT) {
142
143 ret = mbedtls_cipher_setkey(&(operation->ctx.cipher),
144 &key_data[0],
145 PSA_BYTES_TO_BITS(key_size),
146 MBEDTLS_ENCRYPT);
147
148 } else if (c_mode == TFM_CRYPTO_CIPHER_MODE_DECRYPT) {
149
150 ret = mbedtls_cipher_setkey(&(operation->ctx.cipher),
151 &key_data[0],
152 PSA_BYTES_TO_BITS(key_size),
153 MBEDTLS_DECRYPT);
154 } else {
155 /* Release the operation context */
156 tfm_crypto_operation_release(handle);
157 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
158 }
159
160 if (ret != 0) {
161 /* Release the operation context */
162 tfm_crypto_operation_release(handle);
163 return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
164 }
165
166 /* Mbed TLS cipher set padding mode in case of CBC */
167 if ((alg & ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK) == PSA_ALG_CBC_BASE) {
168
169 /* Check the value of padding field */
170 padding_mode = alg & PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
171
172 switch (padding_mode) {
173 case PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:
174 mbedtls_padding_mode = MBEDTLS_PADDING_PKCS7;
175 break;
176 case PSA_ALG_BLOCK_CIPHER_PAD_NONE:
177 mbedtls_padding_mode = MBEDTLS_PADDING_NONE;
178 break;
179 default:
180 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
181 }
182
183 ret = mbedtls_cipher_set_padding_mode(&(operation->ctx.cipher),
184 mbedtls_padding_mode);
185 if (ret != 0) {
186 /* Release the operation context */
187 tfm_crypto_operation_release(handle);
188 return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
189 }
190 }
191
192 return TFM_CRYPTO_ERR_PSA_SUCCESS;
193}
194
195/*!
196 * \defgroup public_psa Public functions, PSA
197 *
198 */
199
200/*!@{*/
201enum tfm_crypto_err_t tfm_crypto_encrypt_set_iv(
202 psa_cipher_operation_t *handle,
203 const unsigned char *iv,
204 size_t iv_length)
205{
206 int ret;
207 enum tfm_crypto_err_t err;
208 struct psa_cipher_operation_s *operation = NULL;
209
210 /* Validate pointers */
211 err = tfm_crypto_memory_check(handle,
212 sizeof(psa_cipher_operation_t),
213 TFM_MEMORY_ACCESS_RW);
214 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
215 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
216 }
217 err = tfm_crypto_memory_check((void *)iv, iv_length, TFM_MEMORY_ACCESS_RO);
218 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
219 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
220 }
221
222 /* Look up the corresponding operation context */
223 err = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
224 handle,
225 (void **)&operation);
226
227 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
228 return err;
229 }
230
231 if (operation->iv_required == 0) {
232 /* Release the operation context */
233 tfm_crypto_operation_release(handle);
234 return TFM_CRYPTO_ERR_PSA_ERROR_NOT_PERMITTED;
235 }
236
237 if (iv_length > PSA_CIPHER_IV_MAX_SIZE) {
238 /* Release the operation context */
239 tfm_crypto_operation_release(handle);
240 return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
241 }
242
243 /* Bind the IV to the cipher operation */
244 ret = mbedtls_cipher_set_iv(&(operation->ctx.cipher), iv, iv_length);
245 if (ret != 0) {
246 /* Release the operation context */
247 tfm_crypto_operation_release(handle);
248 return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
249 }
250 operation->iv_set = 1;
251 operation->iv_size = iv_length;
252
253 /* Reset the context after IV is set */
254 ret = mbedtls_cipher_reset(&(operation->ctx.cipher));
255 if (ret != 0) {
256 /* Release the operation context */
257 tfm_crypto_operation_release(handle);
258 return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
259 }
260
261 return TFM_CRYPTO_ERR_PSA_SUCCESS;
262}
263
264enum tfm_crypto_err_t tfm_crypto_encrypt_setup(
265 psa_cipher_operation_t *handle,
266 psa_key_slot_t key,
267 psa_algorithm_t alg)
268{
269 return tfm_crypto_cipher_setup(handle,
270 key,
271 alg,
272 TFM_CRYPTO_CIPHER_MODE_ENCRYPT);
273}
274
275enum tfm_crypto_err_t tfm_crypto_decrypt_setup(
276 psa_cipher_operation_t *handle,
277 psa_key_slot_t key,
278 psa_algorithm_t alg)
279{
280 return tfm_crypto_cipher_setup(handle,
281 key,
282 alg,
283 TFM_CRYPTO_CIPHER_MODE_DECRYPT);
284}
285
286enum tfm_crypto_err_t tfm_crypto_cipher_update(
287 psa_cipher_operation_t *handle,
288 const uint8_t *input,
289 size_t input_length,
290 unsigned char *output,
291 size_t output_size,
292 size_t *output_length)
293{
294 int ret;
295 enum tfm_crypto_err_t err;
296 size_t olen;
297 struct psa_cipher_operation_s *operation = NULL;
298
299 /* Validate pointers */
300 err = tfm_crypto_memory_check(handle,
301 sizeof(psa_cipher_operation_t),
302 TFM_MEMORY_ACCESS_RW);
303 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
304 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
305 }
306 err = tfm_crypto_memory_check((void *)input,
307 input_length,
308 TFM_MEMORY_ACCESS_RO);
309 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
310 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
311 }
312 err = tfm_crypto_memory_check(output,
313 output_size,
314 TFM_MEMORY_ACCESS_RW);
315 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
316 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
317 }
318 err = tfm_crypto_memory_check(output_length,
319 sizeof(size_t),
320 TFM_MEMORY_ACCESS_RW);
321 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
322 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
323 }
324
325 /* Look up the corresponding operation context */
326 err = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
327 handle,
328 (void **)&operation);
329
330 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
331 return err;
332 }
333
334 /* If the IV is required and it's not been set yet */
335 if ((operation->iv_required == 1) && (operation->iv_set == 0)) {
336
337 if (operation->ctx.cipher.operation != MBEDTLS_DECRYPT) {
338 /* Release the operation context */
339 tfm_crypto_operation_release(handle);
340 return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
341 }
342
343 /* This call is used to set the IV on the object */
344 err = tfm_crypto_encrypt_set_iv(handle, input, input_length);
345
346 *output_length = 0;
347
348 return err;
349 }
350
351 /* If the key is not set, setup phase has not been completed */
352 if (operation->key_set == 0) {
353 /* Release the operation context */
354 tfm_crypto_operation_release(handle);
355 return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
356 }
357
358 *output_length = 0;
359
360 ret = mbedtls_cipher_update(&(operation->ctx.cipher), input, input_length,
361 output, &olen);
362
363 if ((ret != 0) || (olen == 0)) {
364 /* Release the operation context */
365 tfm_crypto_operation_release(handle);
366 return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
367 }
368
369 /* Assign the output buffer length */
370 *output_length = olen;
371
372 return TFM_CRYPTO_ERR_PSA_SUCCESS;
373}
374
375enum tfm_crypto_err_t tfm_crypto_cipher_finish(
376 psa_cipher_operation_t *handle,
377 uint8_t *output,
378 size_t output_size,
379 size_t *output_length)
380{
381 int ret;
382 enum tfm_crypto_err_t err;
383 size_t olen;
384 struct psa_cipher_operation_s *operation = NULL;
385
386 /* Validate pointers */
387 err = tfm_crypto_memory_check(handle,
388 sizeof(psa_cipher_operation_t),
389 TFM_MEMORY_ACCESS_RW);
390 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
391 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
392 }
393 err = tfm_crypto_memory_check(output,
394 output_size,
395 TFM_MEMORY_ACCESS_RW);
396 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
397 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
398 }
399 err = tfm_crypto_memory_check(output_length,
400 sizeof(size_t),
401 TFM_MEMORY_ACCESS_RW);
402 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
403 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
404 }
405
406 *output_length = 0;
407
408 /* Look up the corresponding operation context */
409 err = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
410 handle,
411 (void **)&operation);
412
413 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
414 return err;
415 }
416
417 ret = mbedtls_cipher_finish(&(operation->ctx.cipher), output, &olen);
418 if (ret != 0) {
419 /* Release the operation context */
420 tfm_crypto_operation_release(handle);
421 return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
422 }
423
424 *output_length = olen;
425
426 /* Clear the Mbed TLS context */
427 mbedtls_cipher_free(&(operation->ctx.cipher));
428
429 /* Release the operation context */
430 err = tfm_crypto_operation_release(handle);
431 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
432 return err;
433 }
434
435 return TFM_CRYPTO_ERR_PSA_SUCCESS;
436}
437
438enum tfm_crypto_err_t tfm_crypto_cipher_abort(psa_cipher_operation_t *handle)
439{
440 enum tfm_crypto_err_t err;
441 struct psa_cipher_operation_s *operation = NULL;
442
443 /* Validate pointers */
444 err = tfm_crypto_memory_check(handle,
445 sizeof(psa_cipher_operation_t),
446 TFM_MEMORY_ACCESS_RW);
447 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
448 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
449 }
450
451 /* Look up the corresponding operation context */
452 err = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
453 handle,
454 (void **)&operation);
455
456 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
457 return err;
458 }
459
460 /* Clear the Mbed TLS context */
461 mbedtls_cipher_free(&(operation->ctx.cipher));
462
463 /* Release the operation context */
464 err = tfm_crypto_operation_release(handle);
465 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
466 return err;
467 }
468
469 return TFM_CRYPTO_ERR_PSA_SUCCESS;
470}
471/*!@}*/