1 /*
2 * PSA cipher driver entry points
3 */
4 /*
5 * Copyright The Mbed TLS Contributors
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 #include "common.h"
22
23 #if defined(MBEDTLS_PSA_CRYPTO_C)
24
25 #include "psa_crypto_cipher.h"
26 #include "psa_crypto_core.h"
27 #include "psa_crypto_random_impl.h"
28
29 #include "mbedtls/cipher.h"
30 #include "mbedtls/error.h"
31
32 #include <string.h>
33
mbedtls_cipher_info_from_psa(psa_algorithm_t alg,psa_key_type_t key_type,size_t key_bits,mbedtls_cipher_id_t * cipher_id)34 const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
35 psa_algorithm_t alg,
36 psa_key_type_t key_type,
37 size_t key_bits,
38 mbedtls_cipher_id_t *cipher_id)
39 {
40 mbedtls_cipher_mode_t mode;
41 mbedtls_cipher_id_t cipher_id_tmp;
42
43 if (PSA_ALG_IS_AEAD(alg)) {
44 alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
45 }
46
47 if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
48 switch (alg) {
49 #if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
50 case PSA_ALG_STREAM_CIPHER:
51 mode = MBEDTLS_MODE_STREAM;
52 break;
53 #endif
54 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
55 case PSA_ALG_CTR:
56 mode = MBEDTLS_MODE_CTR;
57 break;
58 #endif
59 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
60 case PSA_ALG_CFB:
61 mode = MBEDTLS_MODE_CFB;
62 break;
63 #endif
64 #if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
65 case PSA_ALG_OFB:
66 mode = MBEDTLS_MODE_OFB;
67 break;
68 #endif
69 #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
70 case PSA_ALG_ECB_NO_PADDING:
71 mode = MBEDTLS_MODE_ECB;
72 break;
73 #endif
74 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
75 case PSA_ALG_CBC_NO_PADDING:
76 mode = MBEDTLS_MODE_CBC;
77 break;
78 #endif
79 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
80 case PSA_ALG_CBC_PKCS7:
81 mode = MBEDTLS_MODE_CBC;
82 break;
83 #endif
84 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
85 case PSA_ALG_CCM_STAR_NO_TAG:
86 mode = MBEDTLS_MODE_CCM_STAR_NO_TAG;
87 break;
88 #endif
89 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
90 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
91 mode = MBEDTLS_MODE_CCM;
92 break;
93 #endif
94 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
95 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
96 mode = MBEDTLS_MODE_GCM;
97 break;
98 #endif
99 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
100 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
101 mode = MBEDTLS_MODE_CHACHAPOLY;
102 break;
103 #endif
104 default:
105 return NULL;
106 }
107 } else if (alg == PSA_ALG_CMAC) {
108 mode = MBEDTLS_MODE_ECB;
109 } else {
110 return NULL;
111 }
112
113 switch (key_type) {
114 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
115 case PSA_KEY_TYPE_AES:
116 cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
117 break;
118 #endif
119 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
120 case PSA_KEY_TYPE_ARIA:
121 cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
122 break;
123 #endif
124 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
125 case PSA_KEY_TYPE_DES:
126 /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
127 * and 192 for three-key Triple-DES. */
128 if (key_bits == 64) {
129 cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
130 } else {
131 cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
132 }
133 /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
134 * but two-key Triple-DES is functionally three-key Triple-DES
135 * with K1=K3, so that's how we present it to mbedtls. */
136 if (key_bits == 128) {
137 key_bits = 192;
138 }
139 break;
140 #endif
141 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
142 case PSA_KEY_TYPE_CAMELLIA:
143 cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
144 break;
145 #endif
146 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
147 case PSA_KEY_TYPE_CHACHA20:
148 cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
149 break;
150 #endif
151 default:
152 return NULL;
153 }
154 if (cipher_id != NULL) {
155 *cipher_id = cipher_id_tmp;
156 }
157
158 return mbedtls_cipher_info_from_values(cipher_id_tmp,
159 (int) key_bits, mode);
160 }
161
162 #if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
163
psa_cipher_setup(mbedtls_psa_cipher_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg,mbedtls_operation_t cipher_operation)164 static psa_status_t psa_cipher_setup(
165 mbedtls_psa_cipher_operation_t *operation,
166 const psa_key_attributes_t *attributes,
167 const uint8_t *key_buffer, size_t key_buffer_size,
168 psa_algorithm_t alg,
169 mbedtls_operation_t cipher_operation)
170 {
171 int ret = 0;
172 size_t key_bits;
173 const mbedtls_cipher_info_t *cipher_info = NULL;
174 psa_key_type_t key_type = attributes->core.type;
175
176 (void) key_buffer_size;
177
178 mbedtls_cipher_init(&operation->ctx.cipher);
179
180 operation->alg = alg;
181 key_bits = attributes->core.bits;
182 cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
183 key_bits, NULL);
184 if (cipher_info == NULL) {
185 return PSA_ERROR_NOT_SUPPORTED;
186 }
187
188 ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
189 if (ret != 0) {
190 goto exit;
191 }
192
193 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
194 if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
195 /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
196 uint8_t keys[24];
197 memcpy(keys, key_buffer, 16);
198 memcpy(keys + 16, key_buffer, 8);
199 ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
200 keys,
201 192, cipher_operation);
202 } else
203 #endif
204 {
205 ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
206 (int) key_bits, cipher_operation);
207 }
208 if (ret != 0) {
209 goto exit;
210 }
211
212 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
213 defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
214 switch (alg) {
215 case PSA_ALG_CBC_NO_PADDING:
216 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
217 MBEDTLS_PADDING_NONE);
218 break;
219 case PSA_ALG_CBC_PKCS7:
220 ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
221 MBEDTLS_PADDING_PKCS7);
222 break;
223 default:
224 /* The algorithm doesn't involve padding. */
225 ret = 0;
226 break;
227 }
228 if (ret != 0) {
229 goto exit;
230 }
231 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
232 MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
233
234 operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
235 PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
236 operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
237
238 exit:
239 return mbedtls_to_psa_error(ret);
240 }
241
mbedtls_psa_cipher_encrypt_setup(mbedtls_psa_cipher_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg)242 psa_status_t mbedtls_psa_cipher_encrypt_setup(
243 mbedtls_psa_cipher_operation_t *operation,
244 const psa_key_attributes_t *attributes,
245 const uint8_t *key_buffer, size_t key_buffer_size,
246 psa_algorithm_t alg)
247 {
248 return psa_cipher_setup(operation, attributes,
249 key_buffer, key_buffer_size,
250 alg, MBEDTLS_ENCRYPT);
251 }
252
mbedtls_psa_cipher_decrypt_setup(mbedtls_psa_cipher_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg)253 psa_status_t mbedtls_psa_cipher_decrypt_setup(
254 mbedtls_psa_cipher_operation_t *operation,
255 const psa_key_attributes_t *attributes,
256 const uint8_t *key_buffer, size_t key_buffer_size,
257 psa_algorithm_t alg)
258 {
259 return psa_cipher_setup(operation, attributes,
260 key_buffer, key_buffer_size,
261 alg, MBEDTLS_DECRYPT);
262 }
263
mbedtls_psa_cipher_set_iv(mbedtls_psa_cipher_operation_t * operation,const uint8_t * iv,size_t iv_length)264 psa_status_t mbedtls_psa_cipher_set_iv(
265 mbedtls_psa_cipher_operation_t *operation,
266 const uint8_t *iv, size_t iv_length)
267 {
268 if (iv_length != operation->iv_length) {
269 return PSA_ERROR_INVALID_ARGUMENT;
270 }
271
272 return mbedtls_to_psa_error(
273 mbedtls_cipher_set_iv(&operation->ctx.cipher,
274 iv, iv_length));
275 }
276
277 #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
278 /** Process input for which the algorithm is set to ECB mode.
279 *
280 * This requires manual processing, since the PSA API is defined as being
281 * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
282 * but the underlying mbedtls_cipher_update only takes full blocks.
283 *
284 * \param ctx The mbedtls cipher context to use. It must have been
285 * set up for ECB.
286 * \param[in] input The input plaintext or ciphertext to process.
287 * \param input_length The number of bytes to process from \p input.
288 * This does not need to be aligned to a block boundary.
289 * If there is a partial block at the end of the input,
290 * it is stored in \p ctx for future processing.
291 * \param output The buffer where the output is written. It must be
292 * at least `BS * floor((p + input_length) / BS)` bytes
293 * long, where `p` is the number of bytes in the
294 * unprocessed partial block in \p ctx (with
295 * `0 <= p <= BS - 1`) and `BS` is the block size.
296 * \param output_length On success, the number of bytes written to \p output.
297 * \c 0 on error.
298 *
299 * \return #PSA_SUCCESS or an error from a hardware accelerator
300 */
psa_cipher_update_ecb(mbedtls_cipher_context_t * ctx,const uint8_t * input,size_t input_length,uint8_t * output,size_t * output_length)301 static psa_status_t psa_cipher_update_ecb(
302 mbedtls_cipher_context_t *ctx,
303 const uint8_t *input,
304 size_t input_length,
305 uint8_t *output,
306 size_t *output_length)
307 {
308 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
309 size_t block_size = ctx->cipher_info->block_size;
310 size_t internal_output_length = 0;
311 *output_length = 0;
312
313 if (input_length == 0) {
314 status = PSA_SUCCESS;
315 goto exit;
316 }
317
318 if (ctx->unprocessed_len > 0) {
319 /* Fill up to block size, and run the block if there's a full one. */
320 size_t bytes_to_copy = block_size - ctx->unprocessed_len;
321
322 if (input_length < bytes_to_copy) {
323 bytes_to_copy = input_length;
324 }
325
326 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
327 input, bytes_to_copy);
328 input_length -= bytes_to_copy;
329 input += bytes_to_copy;
330 ctx->unprocessed_len += bytes_to_copy;
331
332 if (ctx->unprocessed_len == block_size) {
333 status = mbedtls_to_psa_error(
334 mbedtls_cipher_update(ctx,
335 ctx->unprocessed_data,
336 block_size,
337 output, &internal_output_length));
338
339 if (status != PSA_SUCCESS) {
340 goto exit;
341 }
342
343 output += internal_output_length;
344 *output_length += internal_output_length;
345 ctx->unprocessed_len = 0;
346 }
347 }
348
349 while (input_length >= block_size) {
350 /* Run all full blocks we have, one by one */
351 status = mbedtls_to_psa_error(
352 mbedtls_cipher_update(ctx, input,
353 block_size,
354 output, &internal_output_length));
355
356 if (status != PSA_SUCCESS) {
357 goto exit;
358 }
359
360 input_length -= block_size;
361 input += block_size;
362
363 output += internal_output_length;
364 *output_length += internal_output_length;
365 }
366
367 if (input_length > 0) {
368 /* Save unprocessed bytes for later processing */
369 memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
370 input, input_length);
371 ctx->unprocessed_len += input_length;
372 }
373
374 status = PSA_SUCCESS;
375
376 exit:
377 return status;
378 }
379 #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
380
mbedtls_psa_cipher_update(mbedtls_psa_cipher_operation_t * operation,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)381 psa_status_t mbedtls_psa_cipher_update(
382 mbedtls_psa_cipher_operation_t *operation,
383 const uint8_t *input, size_t input_length,
384 uint8_t *output, size_t output_size, size_t *output_length)
385 {
386 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
387 size_t expected_output_size;
388
389 if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
390 /* Take the unprocessed partial block left over from previous
391 * update calls, if any, plus the input to this call. Remove
392 * the last partial block, if any. You get the data that will be
393 * output in this call. */
394 expected_output_size =
395 (operation->ctx.cipher.unprocessed_len + input_length)
396 / operation->block_length * operation->block_length;
397 } else {
398 expected_output_size = input_length;
399 }
400
401 if (output_size < expected_output_size) {
402 return PSA_ERROR_BUFFER_TOO_SMALL;
403 }
404
405 #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
406 if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
407 /* mbedtls_cipher_update has an API inconsistency: it will only
408 * process a single block at a time in ECB mode. Abstract away that
409 * inconsistency here to match the PSA API behaviour. */
410 status = psa_cipher_update_ecb(&operation->ctx.cipher,
411 input,
412 input_length,
413 output,
414 output_length);
415 } else
416 #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
417 {
418 status = mbedtls_to_psa_error(
419 mbedtls_cipher_update(&operation->ctx.cipher, input,
420 input_length, output, output_length));
421
422 if (*output_length > output_size) {
423 return PSA_ERROR_CORRUPTION_DETECTED;
424 }
425 }
426
427 return status;
428 }
429
mbedtls_psa_cipher_finish(mbedtls_psa_cipher_operation_t * operation,uint8_t * output,size_t output_size,size_t * output_length)430 psa_status_t mbedtls_psa_cipher_finish(
431 mbedtls_psa_cipher_operation_t *operation,
432 uint8_t *output, size_t output_size, size_t *output_length)
433 {
434 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
435 uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
436
437 if (operation->ctx.cipher.unprocessed_len != 0) {
438 if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
439 operation->alg == PSA_ALG_CBC_NO_PADDING) {
440 status = PSA_ERROR_INVALID_ARGUMENT;
441 goto exit;
442 }
443 }
444
445 status = mbedtls_to_psa_error(
446 mbedtls_cipher_finish(&operation->ctx.cipher,
447 temp_output_buffer,
448 output_length));
449 if (status != PSA_SUCCESS) {
450 goto exit;
451 }
452
453 if (*output_length == 0) {
454 ; /* Nothing to copy. Note that output may be NULL in this case. */
455 } else if (output_size >= *output_length) {
456 memcpy(output, temp_output_buffer, *output_length);
457 } else {
458 status = PSA_ERROR_BUFFER_TOO_SMALL;
459 }
460
461 exit:
462 mbedtls_platform_zeroize(temp_output_buffer,
463 sizeof(temp_output_buffer));
464
465 return status;
466 }
467
mbedtls_psa_cipher_abort(mbedtls_psa_cipher_operation_t * operation)468 psa_status_t mbedtls_psa_cipher_abort(
469 mbedtls_psa_cipher_operation_t *operation)
470 {
471 /* Sanity check (shouldn't happen: operation->alg should
472 * always have been initialized to a valid value). */
473 if (!PSA_ALG_IS_CIPHER(operation->alg)) {
474 return PSA_ERROR_BAD_STATE;
475 }
476
477 mbedtls_cipher_free(&operation->ctx.cipher);
478
479 return PSA_SUCCESS;
480 }
481
mbedtls_psa_cipher_encrypt(const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg,const uint8_t * iv,size_t iv_length,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)482 psa_status_t mbedtls_psa_cipher_encrypt(
483 const psa_key_attributes_t *attributes,
484 const uint8_t *key_buffer,
485 size_t key_buffer_size,
486 psa_algorithm_t alg,
487 const uint8_t *iv,
488 size_t iv_length,
489 const uint8_t *input,
490 size_t input_length,
491 uint8_t *output,
492 size_t output_size,
493 size_t *output_length)
494 {
495 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
496 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
497 size_t update_output_length, finish_output_length;
498
499 status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
500 key_buffer, key_buffer_size,
501 alg);
502 if (status != PSA_SUCCESS) {
503 goto exit;
504 }
505
506 if (iv_length > 0) {
507 status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
508 if (status != PSA_SUCCESS) {
509 goto exit;
510 }
511 }
512
513 status = mbedtls_psa_cipher_update(&operation, input, input_length,
514 output, output_size,
515 &update_output_length);
516 if (status != PSA_SUCCESS) {
517 goto exit;
518 }
519
520 status = mbedtls_psa_cipher_finish(
521 &operation,
522 mbedtls_buffer_offset(output, update_output_length),
523 output_size - update_output_length, &finish_output_length);
524 if (status != PSA_SUCCESS) {
525 goto exit;
526 }
527
528 *output_length = update_output_length + finish_output_length;
529
530 exit:
531 if (status == PSA_SUCCESS) {
532 status = mbedtls_psa_cipher_abort(&operation);
533 } else {
534 mbedtls_psa_cipher_abort(&operation);
535 }
536
537 return status;
538 }
539
mbedtls_psa_cipher_decrypt(const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)540 psa_status_t mbedtls_psa_cipher_decrypt(
541 const psa_key_attributes_t *attributes,
542 const uint8_t *key_buffer,
543 size_t key_buffer_size,
544 psa_algorithm_t alg,
545 const uint8_t *input,
546 size_t input_length,
547 uint8_t *output,
548 size_t output_size,
549 size_t *output_length)
550 {
551 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
552 mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
553 size_t olength, accumulated_length;
554
555 status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
556 key_buffer, key_buffer_size,
557 alg);
558 if (status != PSA_SUCCESS) {
559 goto exit;
560 }
561
562 if (operation.iv_length > 0) {
563 status = mbedtls_psa_cipher_set_iv(&operation,
564 input, operation.iv_length);
565 if (status != PSA_SUCCESS) {
566 goto exit;
567 }
568 }
569
570 status = mbedtls_psa_cipher_update(
571 &operation,
572 mbedtls_buffer_offset_const(input, operation.iv_length),
573 input_length - operation.iv_length,
574 output, output_size, &olength);
575 if (status != PSA_SUCCESS) {
576 goto exit;
577 }
578
579 accumulated_length = olength;
580
581 status = mbedtls_psa_cipher_finish(
582 &operation,
583 mbedtls_buffer_offset(output, accumulated_length),
584 output_size - accumulated_length, &olength);
585 if (status != PSA_SUCCESS) {
586 goto exit;
587 }
588
589 *output_length = accumulated_length + olength;
590
591 exit:
592 if (status == PSA_SUCCESS) {
593 status = mbedtls_psa_cipher_abort(&operation);
594 } else {
595 mbedtls_psa_cipher_abort(&operation);
596 }
597
598 return status;
599 }
600 #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
601
602 #endif /* MBEDTLS_PSA_CRYPTO_C */
603