blob: e1fdb178936a16fbd524086f3867ef8d887c9297 [file] [log] [blame]
Antonio de Angeliscf85ba22018-10-09 13:29:40 +01001/*
2 * Copyright (c) 2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8/**
9 * \brief Include the Crypto engine header. This source module implements the
10 * interface which is being used by the other components of the service
11 * to interact with the cryptography primitives available, in SW or HW.
12 * The current implementation provides only a SW implementation based on
13 * Mbed TLS functions.
14 */
15#include "crypto_engine.h"
16
17#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
18/**
19 * \brief Buffer size used by Mbed TLS for its allocations
20 */
21#define TFM_CRYPTO_MBEDTLS_MEM_BUF_LEN (1024)
22
23/**
24 * \brief Static buffer to be used by Mbed TLS for memory allocations
25 *
26 */
27static uint8_t mbedtls_mem_buf[TFM_CRYPTO_MBEDTLS_MEM_BUF_LEN] = {0};
28
29/**
Jamie Fox4394fcf2018-10-08 16:14:52 +010030 * \brief Converts a PSA key type and key size to an Mbed TLS cipher ID.
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010031 *
Jamie Fox4394fcf2018-10-08 16:14:52 +010032 * \param[in] key_type PSA key type
33 * \param[in] key_size Key size in bits
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010034 *
Jamie Fox4394fcf2018-10-08 16:14:52 +010035 * \return An mbedtls_cipher_id_t value corresponding to key_type and key_size,
36 * or MBEDTLS_CIPHER_ID_NONE if no such cipher ID is supported by
37 * Mbed TLS.
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010038 */
Jamie Fox4394fcf2018-10-08 16:14:52 +010039static mbedtls_cipher_id_t psa_to_mbedtls_cipher_id(psa_key_type_t key_type,
40 size_t key_size)
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010041{
Jamie Fox4394fcf2018-10-08 16:14:52 +010042 switch (key_type) {
43 case PSA_KEY_TYPE_AES:
44 return MBEDTLS_CIPHER_ID_AES;
45 case PSA_KEY_TYPE_DES:
46 return (key_size == 192) ? MBEDTLS_CIPHER_ID_3DES
47 : MBEDTLS_CIPHER_ID_DES;
48 case PSA_KEY_TYPE_CAMELLIA:
49 return MBEDTLS_CIPHER_ID_CAMELLIA;
50 case PSA_KEY_TYPE_ARC4:
51 return MBEDTLS_CIPHER_ID_ARC4;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010052 default:
Jamie Fox4394fcf2018-10-08 16:14:52 +010053 return MBEDTLS_CIPHER_ID_NONE;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010054 }
55}
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010056
Jamie Fox4394fcf2018-10-08 16:14:52 +010057/**
58 * \brief Converts a PSA algorithm to an Mbed TLS cipher mode.
59 *
60 * \param[in] alg PSA algorithm
61 *
62 * \return An mbedtls_cipher_mode_t value corresponding to alg, or
63 * MBEDTLS_MODE_NONE if no such cipher mode is supported by Mbed TLS.
64 */
65static mbedtls_cipher_mode_t psa_to_mbedtls_cipher_mode(psa_algorithm_t alg)
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010066{
Jamie Fox4394fcf2018-10-08 16:14:52 +010067 if (PSA_ALG_IS_BLOCK_CIPHER(alg)) {
68 /* Clear the padding mask */
69 alg &= ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
70 }
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010071
Jamie Fox4394fcf2018-10-08 16:14:52 +010072 switch (alg) {
73 case PSA_ALG_CBC_BASE:
74 return MBEDTLS_MODE_CBC;
75 case PSA_ALG_CFB_BASE:
76 return MBEDTLS_MODE_CFB;
77 case PSA_ALG_OFB_BASE:
78 return MBEDTLS_MODE_OFB;
79 case PSA_ALG_XTS_BASE:
80 return MBEDTLS_MODE_NONE; /* FIXME: requires Mbed TLS 2.11 */
81 case PSA_ALG_CTR:
82 return MBEDTLS_MODE_CTR;
83 case PSA_ALG_ARC4:
84 return MBEDTLS_MODE_STREAM; /* ARC4 is a stream cipher */
85 case PSA_ALG_CCM:
86 return MBEDTLS_MODE_CCM;
87 case PSA_ALG_GCM:
88 return MBEDTLS_MODE_GCM;
89 default:
90 return MBEDTLS_MODE_NONE;
91 }
Antonio de Angeliscf85ba22018-10-09 13:29:40 +010092}
93
Jamie Fox4394fcf2018-10-08 16:14:52 +010094/**
95 * \brief Given a PSA key type, algorithm and key size, finds the corresponding
96 * Mbed TLS cipher info struct.
97 *
98 * \param[in] key_type PSA key type
99 * \param[in] alg PSA algorithm
100 * \param[in] key_size Key size in bits
101 *
102 * \return A pointer to the mbedtls_cipher_info_t struct corresponding to
103 * key_type, alg and key_size, or NULL if Mbed TLS does not support this
104 * combination.
105 */
106static const mbedtls_cipher_info_t *get_mbedtls_cipher_info(
107 psa_key_type_t key_type,
108 psa_algorithm_t alg,
109 size_t key_size)
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100110{
Jamie Fox4394fcf2018-10-08 16:14:52 +0100111 mbedtls_cipher_id_t cipher_id;
112 mbedtls_cipher_mode_t cipher_mode;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100113
Jamie Fox4394fcf2018-10-08 16:14:52 +0100114 /* Get the Mbed TLS cipher ID */
115 cipher_id = psa_to_mbedtls_cipher_id(key_type, key_size);
116 if (cipher_id == MBEDTLS_CIPHER_ID_NONE) {
117 /* The requested key type is not supported by Mbed TLS */
118 return NULL;
119 }
120
121 /* Get the Mbed TLS cipher mode */
122 cipher_mode = psa_to_mbedtls_cipher_mode(alg);
123 if (cipher_mode == MBEDTLS_MODE_NONE) {
124 /* The requested algorithm is not supported by Mbed TLS */
125 return NULL;
126 }
127
128 /* Get the Mbed TLS cipher info pointer */
129 return mbedtls_cipher_info_from_values(cipher_id, key_size, cipher_mode);
130}
131
132/**
133 * \brief Converts a PSA algorithm to an Mbed TLS message digest type.
134 *
135 * \param[in] alg PSA algorithm
136 *
137 * \return An mbedtls_md_type_t value corresponding to alg, or
138 * MBEDTLS_MD_NONE if no such message digest is available.
139 */
140static mbedtls_md_type_t psa_to_mbedtls_md_type(psa_algorithm_t alg)
141{
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100142 mbedtls_md_type_t type = MBEDTLS_MD_NONE;
143
144 /* Mbed TLS message digest setup */
145 switch(alg) {
146 case PSA_ALG_MD2:
147#if defined(MBEDTLS_MD2_C)
148 type = MBEDTLS_MD_MD2;
149#endif
150 break;
151 case PSA_ALG_MD4:
152#if defined(MBEDTLS_MD4_C)
153 type = MBEDTLS_MD_MD4;
154#endif
155 break;
156 case PSA_ALG_MD5:
157#if defined(MBEDTLS_MD5_C)
158 type = MBEDTLS_MD_MD5;
159#endif
160 break;
161 case PSA_ALG_RIPEMD160:
162#if defined(MBEDTLS_RIPEMD160_C)
163 type = MBEDTLS_MD_RIPEMD160;
164#endif
165 break;
166 case PSA_ALG_SHA_1:
167#if defined(MBEDTLS_SHA1_C)
168 type = MBEDTLS_MD_SHA1;
169#endif
170 break;
171 case PSA_ALG_SHA_224:
172#if defined(MBEDTLS_SHA256_C)
173 type = MBEDTLS_MD_SHA224;
174#endif
175 break;
176 case PSA_ALG_SHA_256:
177#if defined(MBEDTLS_SHA256_C)
178 type = MBEDTLS_MD_SHA256;
179#endif
180 break;
181 case PSA_ALG_SHA_384:
182#if defined(MBEDTLS_SHA512_C)
183 type = MBEDTLS_MD_SHA384;
184#endif
185 break;
186 case PSA_ALG_SHA_512:
187#if defined(MBEDTLS_SHA512_C)
188 type = MBEDTLS_MD_SHA512;
189#endif
190 break;
Jamie Fox4394fcf2018-10-08 16:14:52 +0100191 case PSA_ALG_SHA3_224:
192 case PSA_ALG_SHA3_256:
193 case PSA_ALG_SHA3_384:
194 case PSA_ALG_SHA3_512:
195 /* SHA3 not yet supported */
196 type = MBEDTLS_MD_NONE;
197 break;
198 case PSA_ALG_SHA_512_224:
199 case PSA_ALG_SHA_512_256:
200 /* SHA-512 Truncated modes not yet supported */
201 type = MBEDTLS_MD_NONE;
202 break;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100203 default:
204 break;
205 }
206
Jamie Fox4394fcf2018-10-08 16:14:52 +0100207 return type;
208}
209
210/**
211 * \brief This function maps Mbed TLS return codes to PSA return codes.
212 *
213 * \param[in] ret Mbed TLS return value
214 *
215 * \return Return values as specified by \ref psa_status_t
216 */
217static psa_status_t mbedtls_to_psa_return(int ret)
218{
219 /* zero return value means success */
220 if (ret == 0) {
221 return PSA_SUCCESS;
222 }
223
224 /* FIXME: For the time being map all errors to PSA_ERROR_UNKNOW_ERROR */
225 switch (ret) {
226 default:
227 return PSA_ERROR_UNKNOWN_ERROR;
228 }
229}
230#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
231
232psa_status_t tfm_crypto_engine_init(void)
233{
234 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
235
236#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
237 /* Initialise the Mbed TLS static memory allocator so that Mbed TLS
238 * allocates memory from the provided static buffer instead of from
239 * the heap.
240 */
241 mbedtls_memory_buffer_alloc_init(mbedtls_mem_buf,
242 TFM_CRYPTO_MBEDTLS_MEM_BUF_LEN);
243 /* The previous function doesn't return any error code */
244 return_value = PSA_SUCCESS;
245#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
246
247 return return_value;
248}
249
250psa_status_t tfm_crypto_engine_hash_setup(const psa_algorithm_t alg,
251 struct hash_engine_info *engine_info)
252{
253 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
254
255#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
256 mbedtls_md_type_t type = MBEDTLS_MD_NONE;
257
258 type = psa_to_mbedtls_md_type(alg);
259
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100260 engine_info->type = (uint32_t) type;
261
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100262 if (type == MBEDTLS_MD_NONE) {
263 return_value = PSA_ERROR_NOT_SUPPORTED;
264 } else {
265 return_value = PSA_SUCCESS;
266 }
267#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
268
269 return return_value;
270}
271
272psa_status_t tfm_crypto_engine_hash_start(
273 union engine_hash_context *hp,
274 const struct hash_engine_info *engine_info)
275{
276 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
277
278#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
279 const mbedtls_md_info_t *info = NULL;
280 int ret;
281
282 /* Mbed TLS message digest init */
283 mbedtls_md_init(&(hp->ctx));
284 info = mbedtls_md_info_from_type((mbedtls_md_type_t)engine_info->type);
285 ret = mbedtls_md_setup(&(hp->ctx), info, 0); /* 0: not HMAC */
286 if (ret != 0) {
287 return_value = mbedtls_to_psa_return(ret);
288 } else {
289 /* Start the message digest context */
290 ret = mbedtls_md_starts(&(hp->ctx));
291 return_value = mbedtls_to_psa_return(ret);
292 }
293#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
294
295 return return_value;
296}
297
298psa_status_t tfm_crypto_engine_hash_update(union engine_hash_context *hp,
299 const uint8_t *input,
300 const uint32_t input_length)
301{
302 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
303
304#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
305 int ret;
306 /* Update the message digest with a new chunk of information */
307 ret = mbedtls_md_update(&(hp->ctx), input, input_length);
308 return_value = mbedtls_to_psa_return(ret);
309#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
310
311 return return_value;
312}
313
314psa_status_t tfm_crypto_engine_hash_finish(union engine_hash_context *hp,
315 uint8_t *hash)
316{
317 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
318
319#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
320 int ret;
321 /* Finalise the hash value, producing the output */
322 ret = mbedtls_md_finish(&(hp->ctx), hash);
323 return_value = mbedtls_to_psa_return(ret);
324#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
325
326 return return_value;
327}
328
329psa_status_t tfm_crypto_engine_hash_release(union engine_hash_context *hp)
330{
331 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
332
333#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
334 /* Clear the Mbed TLS message digest context */
335 mbedtls_md_free(&(hp->ctx));
336 /* The previous function doesn't return any error code */
337 return_value = PSA_SUCCESS;
338#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
339
340 return return_value;
341}
342
343psa_status_t tfm_crypto_engine_cipher_setup(const psa_algorithm_t alg,
344 const psa_key_type_t key_type,
345 const uint32_t key_size,
346 const enum engine_cipher_mode_t engine_cipher_mode,
347 struct cipher_engine_info *engine_info)
348{
349 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
350
351#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
Jamie Fox4394fcf2018-10-08 16:14:52 +0100352 const mbedtls_cipher_info_t *info;
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100353 mbedtls_cipher_padding_t padding_mode = MBEDTLS_PADDING_NONE;
354 psa_algorithm_t padding_mode_field = PSA_ALG_BLOCK_CIPHER_PAD_NONE;
355
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100356 if ((engine_cipher_mode != ENGINE_CIPHER_MODE_ENCRYPT) &&
357 (engine_cipher_mode != ENGINE_CIPHER_MODE_DECRYPT)) {
358 return_value = PSA_ERROR_NOT_SUPPORTED;
359 } else {
Jamie Fox4394fcf2018-10-08 16:14:52 +0100360 /* Get the Mbed TLS cipher info from PSA key_type/alg/key_size. */
361 info = get_mbedtls_cipher_info(key_type, alg, key_size);
362 if (info == NULL) {
363 /* The combination of key_type, alg and key_size is not a valid
364 * Mbed TLS cipher configuration.
365 */
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100366 return_value = PSA_ERROR_NOT_SUPPORTED;
367 } else {
Jamie Fox4394fcf2018-10-08 16:14:52 +0100368 /* If CBC, need to check the padding mode */
369 if ((alg & ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK) == PSA_ALG_CBC_BASE){
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100370
371 /* Check the value of padding field */
372 padding_mode_field = alg & PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
373
374 switch (padding_mode_field) {
375 case PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:
376 padding_mode = MBEDTLS_PADDING_PKCS7;
377 return_value = PSA_SUCCESS;
378 break;
379 case PSA_ALG_BLOCK_CIPHER_PAD_NONE:
380 padding_mode = MBEDTLS_PADDING_NONE;
381 return_value = PSA_SUCCESS;
382 break;
383 default:
384 return_value = PSA_ERROR_NOT_SUPPORTED;
385 }
386 } else {
387 /* The engine is correctly configured */
388 return_value = PSA_SUCCESS;
389 }
390 }
391 }
392
393 if (return_value == PSA_SUCCESS) {
Jamie Fox4394fcf2018-10-08 16:14:52 +0100394 engine_info->type = (uint32_t) (info->type);
Antonio de Angeliscf85ba22018-10-09 13:29:40 +0100395 engine_info->cipher_mode = engine_cipher_mode;
396 engine_info->padding_mode = (uint32_t) padding_mode;
397 }
398#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
399
400 return return_value;
401}
402
403psa_status_t tfm_crypto_engine_cipher_set_padding_mode(
404 union engine_cipher_context *cp,
405 const struct cipher_engine_info *engine_info)
406{
407 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
408
409#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
410 int ret;
411 ret = mbedtls_cipher_set_padding_mode(&(cp->ctx),
412 (mbedtls_cipher_padding_t)engine_info->padding_mode);
413 return_value = mbedtls_to_psa_return(ret);
414#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
415
416 return return_value;
417}
418
419psa_status_t tfm_crypto_engine_cipher_start(
420 union engine_cipher_context *cp,
421 const struct cipher_engine_info *engine_info)
422{
423 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
424
425#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
426 int ret;
427 const mbedtls_cipher_info_t *info = NULL;
428
429 /* Mbed TLS cipher init */
430 mbedtls_cipher_init(&(cp->ctx));
431 info = mbedtls_cipher_info_from_type(engine_info->type);
432
433 ret = mbedtls_cipher_setup(&(cp->ctx), info);
434 return_value = mbedtls_to_psa_return(ret);
435#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
436
437 return return_value;
438}
439
440psa_status_t tfm_crypto_engine_cipher_set_key(
441 union engine_cipher_context *cp,
442 const uint8_t *key_data,
443 const uint32_t key_size,
444 const struct cipher_engine_info *engine_info)
445{
446 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
447
448#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
449 int ret;
450 /* Mbed TLS cipher set key */
451 if ((engine_info->cipher_mode != ENGINE_CIPHER_MODE_ENCRYPT) &&
452 (engine_info->cipher_mode != ENGINE_CIPHER_MODE_DECRYPT)) {
453 return_value = PSA_ERROR_NOT_SUPPORTED;
454 } else {
455 /* Set the key on the context */
456 ret = mbedtls_cipher_setkey(
457 &(cp->ctx),
458 key_data,
459 PSA_BYTES_TO_BITS(key_size),
460 (engine_info->cipher_mode == ENGINE_CIPHER_MODE_ENCRYPT) ?
461 MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT);
462 return_value = mbedtls_to_psa_return(ret);
463 }
464#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
465
466 return return_value;
467}
468
469psa_status_t tfm_crypto_engine_cipher_set_iv(union engine_cipher_context *cp,
470 const uint8_t *iv,
471 const uint32_t iv_length)
472{
473 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
474
475#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
476 int ret;
477
478 /* Bind the IV to the cipher operation */
479 ret = mbedtls_cipher_set_iv(&(cp->ctx), iv, iv_length);
480 if (ret != 0) {
481 return_value = mbedtls_to_psa_return(ret);
482 } else {
483 /* Reset the context after IV is set */
484 ret = mbedtls_cipher_reset(&(cp->ctx));
485 return_value = mbedtls_to_psa_return(ret);
486 }
487#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
488
489 return return_value;
490}
491
492psa_status_t tfm_crypto_engine_cipher_update(union engine_cipher_context *cp,
493 const uint8_t *input,
494 const uint32_t input_length,
495 uint8_t *output,
496 uint32_t *output_length)
497{
498 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
499
500#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
501 int ret;
502 /* Update with the chunk of input data, eventually producing output */
503 ret = mbedtls_cipher_update(&(cp->ctx), input, input_length,
504 output, (size_t *)output_length);
505 return_value = mbedtls_to_psa_return(ret);
506#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
507
508 return return_value;
509}
510
511psa_status_t tfm_crypto_engine_cipher_finish(union engine_cipher_context *cp,
512 uint8_t *output,
513 uint32_t *output_length)
514{
515 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
516
517#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
518 int ret;
519 /* Finalise the cipher operation */
520 ret = mbedtls_cipher_finish(&(cp->ctx), output, (size_t *)output_length);
521 return_value = mbedtls_to_psa_return(ret);
522#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
523
524 return return_value;
525}
526
527psa_status_t tfm_crypto_engine_cipher_release(union engine_cipher_context *cp)
528{
529 psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
530
531#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
532 /* Clear the Mbed TLS context */
533 mbedtls_cipher_free(&(cp->ctx));
534 /* The previous function doesn't return any error code */
535 return_value = PSA_SUCCESS;
536#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
537
538 return return_value;
539}