1 /*
2 * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 /** \file cc3xx_psa_cipher.c
9 *
10 * This file contains the implementation of the entry points associated to the
11 * cipher capability (single-part and multipart) as described by the PSA
12 * Cryptoprocessor Driver interface specification
13 *
14 */
15
16 #include "cc3xx_psa_cipher.h"
17 #include "cc3xx_crypto_primitives_private.h"
18 #include "cc3xx_internal_aes.h"
19 #include "cc3xx_internal_chacha20.h"
20 #include "cc_pal_mem.h"
21 #include "cc_pal_log.h"
22
23 /* To be able to include the PSA style configuration */
24 #include "mbedtls/build_info.h"
25
add_pkcs_padding(uint8_t * output,size_t output_size,size_t data_size)26 static psa_status_t add_pkcs_padding(
27 uint8_t *output,
28 size_t output_size,
29 size_t data_size)
30 {
31 if (NULL == output) {
32 return PSA_ERROR_INVALID_ARGUMENT;
33 }
34
35 uint8_t padding_size = output_size - data_size;
36
37 for (size_t i = 0; i < padding_size; i++) {
38 output[data_size + i] = padding_size;
39 }
40
41 return PSA_SUCCESS;
42 }
43
get_pkcs_padding(const uint8_t * input,size_t input_len,size_t * data_len)44 static psa_status_t get_pkcs_padding(
45 const uint8_t *input,
46 size_t input_len,
47 size_t *data_len)
48 {
49 size_t i, pad_idx;
50 uint8_t padding_len, bad = 0;
51
52 if(NULL == input || NULL == data_len) {
53 return PSA_ERROR_INVALID_ARGUMENT;
54 }
55
56 padding_len = input[input_len - 1];
57 *data_len = input_len - padding_len;
58
59 /* Avoid logical || since it results in a branch */
60 bad |= padding_len > input_len;
61 bad |= padding_len == 0;
62
63 /* The number of bytes checked must be independent of padding_len,
64 * so pick input_len, which is usually 8 or 16 (one block) */
65 pad_idx = input_len - padding_len;
66 for( i = 0; i < input_len; i++ ) {
67 bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
68 }
69
70 return( PSA_ERROR_INVALID_PADDING * ( bad != 0 ) );
71 }
72
cipher_setup(cc3xx_cipher_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key,size_t key_length,psa_algorithm_t alg,psa_encrypt_or_decrypt_t dir)73 static psa_status_t cipher_setup(
74 cc3xx_cipher_operation_t *operation,
75 const psa_key_attributes_t *attributes,
76 const uint8_t *key, size_t key_length,
77 psa_algorithm_t alg,
78 psa_encrypt_or_decrypt_t dir)
79 {
80 psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
81 psa_key_type_t key_type = psa_get_key_type(attributes);
82 size_t key_bits = psa_get_key_bits(attributes);
83
84 if (PSA_BYTES_TO_BITS(key_length) != key_bits) {
85 /* The attributes don't match the buffer given as input */
86 return PSA_ERROR_INVALID_ARGUMENT;
87 }
88
89 if (!(PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_BLOCK_CIPHER_MAC(alg))) {
90 return PSA_ERROR_INVALID_ARGUMENT;
91 }
92
93 CC_PalMemSetZero(operation, sizeof(cc3xx_cipher_operation_t));
94
95 operation->alg = alg;
96 operation->key_type = key_type;
97 operation->dir = dir;
98 operation->iv_size = PSA_CIPHER_IV_LENGTH(key_type, alg);
99 operation->block_size = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
100 PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
101 /* Default callbacks get overwritten only in case of PKCS7 padding */
102 operation->add_padding = NULL;
103 operation->get_padding = NULL;
104
105 switch (operation->key_type) {
106 #if defined(PSA_WANT_KEY_TYPE_AES)
107 case PSA_KEY_TYPE_AES:
108 cc3xx_aes_init(&operation->ctx.aes);
109
110 switch (operation->dir) {
111 case PSA_CRYPTO_DRIVER_ENCRYPT:
112 if (( ret = cc3xx_aes_setkey_enc(
113 &operation->ctx.aes,
114 key,
115 key_bits) )
116 != PSA_SUCCESS) {
117 return ret;
118 }
119 break;
120
121 case PSA_CRYPTO_DRIVER_DECRYPT:
122 if (( ret = cc3xx_aes_setkey_dec(
123 &operation->ctx.aes,
124 key,
125 key_bits) )
126 != PSA_SUCCESS) {
127 return ret;
128 }
129 break;
130
131 default:
132 return PSA_ERROR_NOT_SUPPORTED;
133 }
134 break;
135 #endif /* PSA_WANT_KEY_TYPE_AES */
136 #if defined(PSA_WANT_KEY_TYPE_CHACHA20)
137 case PSA_KEY_TYPE_CHACHA20:
138 cc3xx_chacha20_init(&operation->ctx.chacha);
139
140 if (( ret = cc3xx_chacha20_setkey(
141 &operation->ctx.chacha,
142 key,
143 key_length) )
144 != PSA_SUCCESS) {
145 return ret;
146 }
147 break;
148 #endif /* PSA_WANT_KEY_TYPE_CHACHA20 */
149
150 default:
151 return PSA_ERROR_NOT_SUPPORTED;
152 }
153
154 #if defined(PSA_WANT_ALG_CBC_PKCS7)
155 if (operation->alg == PSA_ALG_CBC_PKCS7) {
156 operation->add_padding = add_pkcs_padding;
157 operation->get_padding = get_pkcs_padding;
158 }
159 #endif /* PSA_WANT_ALG_CBC_PKCS7 */
160
161 return ret;
162 }
163
164 /** \defgroup psa_cipher PSA driver entry points for symmetric cipher
165 *
166 * Entry points for symmetric cipher encryption and decryption as described
167 * by the PSA Cryptoprocessor Driver interface specification
168 *
169 * @{
170 */
cc3xx_cipher_encrypt_setup(cc3xx_cipher_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key,size_t key_length,psa_algorithm_t alg)171 psa_status_t cc3xx_cipher_encrypt_setup(
172 cc3xx_cipher_operation_t *operation,
173 const psa_key_attributes_t *attributes,
174 const uint8_t *key, size_t key_length,
175 psa_algorithm_t alg)
176 {
177 return cipher_setup(operation,
178 attributes,
179 key, key_length,
180 alg,
181 PSA_CRYPTO_DRIVER_ENCRYPT);
182 }
183
cc3xx_cipher_decrypt_setup(cc3xx_cipher_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key,size_t key_length,psa_algorithm_t alg)184 psa_status_t cc3xx_cipher_decrypt_setup(
185 cc3xx_cipher_operation_t *operation,
186 const psa_key_attributes_t *attributes,
187 const uint8_t *key, size_t key_length,
188 psa_algorithm_t alg)
189 {
190 return cipher_setup(operation,
191 attributes,
192 key, key_length,
193 alg,
194 PSA_CRYPTO_DRIVER_DECRYPT);
195 }
196
cc3xx_cipher_set_iv(cc3xx_cipher_operation_t * operation,const uint8_t * iv,size_t iv_length)197 psa_status_t cc3xx_cipher_set_iv(
198 cc3xx_cipher_operation_t *operation,
199 const uint8_t *iv, size_t iv_length)
200 {
201 psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
202
203 if (iv_length > AES_IV_SIZE) {
204 return PSA_ERROR_NOT_SUPPORTED;
205 }
206
207 switch (operation->key_type) {
208 #if defined(PSA_WANT_KEY_TYPE_CHACHA20)
209 case PSA_KEY_TYPE_CHACHA20:
210 {
211 uint8_t *iv_pnt = (uint8_t *)iv;
212 uint32_t counter = 0; /* Use zero as specified by PSA Crypto spec */
213 /* When the IV is 16 bytes the first four bytes contain the counter in
214 * little endian. When the IV is 12 bytes it contains only the IV and
215 * the counter should be set to 0. More information in ChaCha20 section
216 * here: https://armmbed.github.io/mbed-crypto/html/api/ops/ciphers.html
217 */
218 switch (iv_length) {
219 case 16:
220 /* Read the counter value in little endian */
221 counter = (iv[3] << 24) | (iv[2] << 16) | (iv[1] << 8) | iv[0];
222 iv_pnt += 4;
223 iv_length -= 4;
224 case 12:
225 ret = cc3xx_chacha20_set_counter(&operation->ctx.chacha,
226 counter);
227 if (ret == PSA_SUCCESS) {
228 ret = cc3xx_chacha20_set_nonce(&operation->ctx.chacha,
229 iv_pnt,
230 iv_length);
231 }
232 break;
233 case 8:
234 /* Original Chacha, i.e. 64 bit nonce and 64 bit counter */
235 ret = PSA_ERROR_NOT_SUPPORTED;
236 break;
237 default:
238 ret = PSA_ERROR_INVALID_ARGUMENT;
239 break;
240 }
241 }
242 break;
243 #endif /* PSA_WANT_KEY_TYPE_CHACHA20 */
244 #if defined(PSA_WANT_KEY_TYPE_AES)
245 case PSA_KEY_TYPE_AES:
246
247 if (iv_length != AES_IV_SIZE) {
248 return PSA_ERROR_INVALID_ARGUMENT;
249 }
250
251 CC_PalMemCopy(operation->iv, iv, iv_length);
252 operation->iv_size = iv_length;
253 ret = PSA_SUCCESS;
254 break;
255 #endif /* PSA_WANT_KEY_TYPE_AES */
256
257 default:
258 ret = PSA_ERROR_NOT_SUPPORTED;
259 }
260
261 return ret;
262 }
263
cc3xx_cipher_update(cc3xx_cipher_operation_t * operation,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)264 psa_status_t cc3xx_cipher_update(
265 cc3xx_cipher_operation_t *operation,
266 const uint8_t *input, size_t input_length,
267 uint8_t *output, size_t output_size, size_t *output_length)
268 {
269 psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
270 size_t block_size = operation->block_size;
271 size_t expected_output_size;
272
273 if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
274 expected_output_size =
275 ( operation->unprocessed_size + input_length )
276 / operation->block_size * operation->block_size;
277 } else {
278 expected_output_size = input_length;
279 }
280
281 if (output_size < expected_output_size) {
282 return PSA_ERROR_BUFFER_TOO_SMALL;
283 }
284
285 *output_length = 0;
286
287 size_t copy_len;
288
289 switch (operation->key_type) {
290 #if defined(PSA_WANT_KEY_TYPE_AES)
291 case PSA_KEY_TYPE_AES:
292 switch (operation->alg) {
293 #if defined(PSA_WANT_ALG_CBC_NO_PADDING) || defined(PSA_WANT_ALG_CBC_PKCS7)
294 case PSA_ALG_CBC_NO_PADDING:
295 case PSA_ALG_CBC_PKCS7:
296 if ((operation->dir == PSA_CRYPTO_DRIVER_DECRYPT &&
297 NULL != operation->add_padding &&
298 input_length <= block_size -
299 operation->unprocessed_size) ||
300 (operation->dir == PSA_CRYPTO_DRIVER_DECRYPT &&
301 NULL == operation->add_padding &&
302 input_length < block_size -
303 operation->unprocessed_size) ||
304 (operation->dir == PSA_CRYPTO_DRIVER_ENCRYPT &&
305 input_length < block_size -
306 operation->unprocessed_size)) {
307 CC_PalMemCopy(&(operation->unprocessed_data
308 [operation->unprocessed_size]),
309 input,
310 input_length);
311
312 operation->unprocessed_size += input_length;
313 return PSA_SUCCESS;
314 }
315
316 if (0 != operation->unprocessed_size) {
317 copy_len = block_size
318 - operation->unprocessed_size;
319
320 CC_PalMemCopy(&(operation->unprocessed_data
321 [operation->unprocessed_size]),
322 input,
323 copy_len);
324
325 if (( ret = cc3xx_aes_crypt(
326 &operation->ctx.aes,
327 CIPHER_CBC,
328 block_size,
329 operation->iv,
330 operation->unprocessed_data,
331 output) )
332 != PSA_SUCCESS) {
333 return ret;
334 }
335
336 operation->unprocessed_size = 0;
337
338 *output_length += block_size;
339 output += block_size;
340
341 input += copy_len;
342 input_length -= copy_len;
343 }
344
345 if (0 != input_length) {
346 copy_len = input_length % block_size;
347
348 if (copy_len == 0 &&
349 operation->dir==PSA_CRYPTO_DRIVER_DECRYPT &&
350 operation->add_padding != NULL) {
351 copy_len = block_size;
352 }
353
354 CC_PalMemCopy(operation->unprocessed_data,
355 &(input[input_length - copy_len]),
356 copy_len);
357
358 operation->unprocessed_size += copy_len;
359 input_length -= copy_len;
360 }
361
362 if (0 != input_length) {
363 if (( ret = cc3xx_aes_crypt(
364 &operation->ctx.aes,
365 CIPHER_CBC,
366 input_length,
367 operation->iv,
368 input,
369 output) )
370 != PSA_SUCCESS) {
371 return ret;
372 }
373
374 *output_length = input_length;
375 }
376 break;
377 #endif /* PSA_WANT_ALG_CBC_NO_PADDING || PSA_WANT_ALG_CBC_PKCS7 */
378 #if defined(PSA_WANT_ALG_ECB_NO_PADDING)
379 case PSA_ALG_ECB_NO_PADDING:
380 if (( ret = cc3xx_aes_crypt(
381 &operation->ctx.aes,
382 CIPHER_ECB,
383 input_length,
384 operation->iv,
385 input,
386 output) )
387 != PSA_SUCCESS) {
388 return ret;
389 }
390
391 *output_length = input_length;
392 break;
393 #endif /* PSA_WANT_ALG_ECB_NO_PADDING */
394 #if defined(PSA_WANT_ALG_CTR)
395 case PSA_ALG_CTR:
396 if (( ret = cc3xx_aes_crypt(
397 &operation->ctx.aes,
398 CIPHER_CTR,
399 input_length,
400 operation->iv,
401 input,
402 output) )
403 != PSA_SUCCESS) {
404 return ret;
405 }
406
407 *output_length = input_length;
408 break;
409 #endif /* PSA_WANT_ALG_CTR */
410 #if defined(PSA_WANT_ALG_OFB)
411 case PSA_ALG_OFB:
412 if (( ret = cc3xx_aes_crypt(
413 &operation->ctx.aes,
414 CIPHER_OFB,
415 input_length,
416 operation->iv,
417 input,
418 output) )
419 != PSA_SUCCESS) {
420 return ret;
421 }
422
423 *output_length = input_length;
424 break;
425 #endif /* PSA_WANT_ALG_OFB */
426 default:
427 return PSA_ERROR_NOT_SUPPORTED;
428 } /* operation->alg */
429
430 if (*output_length > output_size) {
431 return PSA_ERROR_CORRUPTION_DETECTED;
432 }
433 break;
434 #endif /* PSA_WANT_KEY_TYPE_AES */
435 #if defined(PSA_WANT_KEY_TYPE_CHACHA20)
436 case PSA_KEY_TYPE_CHACHA20:
437 if (( ret = cc3xx_chacha20_update(
438 &operation->ctx.chacha,
439 input,
440 input_length,
441 output,
442 output_size,
443 output_length) )
444 != PSA_SUCCESS) {
445 return ret;
446 }
447 break;
448 #endif /* PSA_WANT_KEY_TYPE_CHACHA20 */
449
450 default:
451 return PSA_ERROR_NOT_SUPPORTED;
452 }
453
454 return ret;
455 }
456
cc3xx_cipher_finish(cc3xx_cipher_operation_t * operation,uint8_t * output,size_t output_size,size_t * output_length)457 psa_status_t cc3xx_cipher_finish(
458 cc3xx_cipher_operation_t *operation,
459 uint8_t *output,
460 size_t output_size,
461 size_t *output_length)
462 {
463 psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
464 /* Buffer for encypted/decrypted data if we have unprocessed data. This
465 * is neccesary when PKCS7 padding is used so that we don't write the
466 * actual padding data to the output buffer when performing decryption.
467 */
468 uint8_t temp_buff[AES_BLOCK_SIZE];
469 /* The length of the data without the padding, this is updated for PKCS7
470 * decryption only.
471 */
472 size_t data_len = operation->block_size;
473
474 if(data_len > AES_BLOCK_SIZE){
475 return PSA_ERROR_BUFFER_TOO_SMALL;
476 }
477
478 *output_length = 0;
479
480 switch (operation->key_type) {
481 #if defined(PSA_WANT_KEY_TYPE_AES)
482 case PSA_KEY_TYPE_AES:
483 switch (operation->alg) {
484 #if defined(PSA_WANT_ALG_CBC_NO_PADDING) || defined(PSA_WANT_ALG_CBC_PKCS7)
485 case PSA_ALG_CBC_NO_PADDING:
486 case PSA_ALG_CBC_PKCS7:
487 if (operation->dir == PSA_CRYPTO_DRIVER_ENCRYPT) {
488 if (operation->add_padding == NULL) {
489 if (operation->unprocessed_size != 0) {
490 /* Return PSA_ERROR_INVALID_ARGUMENT as this condition
491 * implies that a previous call to psa_cipher_update()
492 * has not been performed to completely align to a
493 * block of data and mode is PSA_ALG_CBC_NO_PADDING
494 */
495 return PSA_ERROR_INVALID_ARGUMENT;
496 }
497
498 return PSA_SUCCESS;
499 }
500
501 if (( ret = operation->add_padding(
502 operation->unprocessed_data,
503 operation->block_size,
504 operation->unprocessed_size) )
505 != PSA_SUCCESS) {
506 return ret;
507 }
508 } else if (operation->block_size !=
509 operation->unprocessed_size) {
510 if (operation->add_padding == NULL &&
511 operation->unprocessed_size == 0) {
512 return PSA_SUCCESS;
513 }
514
515 /* Return PSA_ERROR_INVALID_ARGUMENT as this condition implies
516 * that a previous call to psa_cipher_update() has not been
517 * performed to completely align to a block of data and mode is
518 * PSA_ALG_CBC_NO_PADDING
519 */
520 return PSA_ERROR_INVALID_ARGUMENT;
521 }
522
523 if (( ret = cc3xx_aes_crypt(
524 &operation->ctx.aes,
525 CIPHER_CBC,
526 operation->block_size,
527 operation->iv,
528 operation->unprocessed_data,
529 temp_buff))
530 != PSA_SUCCESS) {
531 return ret;
532 }
533
534 /* Set output size for decryption */
535 if (operation->dir == PSA_CRYPTO_DRIVER_DECRYPT){
536 /* get_padding() is initialised for CBC_PKCS7 only */
537 if (operation->get_padding == NULL) {
538 return PSA_ERROR_CORRUPTION_DETECTED;
539 }
540
541 ret = operation->get_padding(
542 temp_buff,
543 operation->block_size,
544 &data_len);
545
546 if (ret != PSA_SUCCESS){
547 return ret;
548 }
549
550 }
551
552 if (output_size < data_len) {
553 return PSA_ERROR_BUFFER_TOO_SMALL;
554 }
555
556 CC_PalMemCopy(output, temp_buff, data_len);
557 *output_length = data_len;
558 break;
559 #endif /* PSA_WANT_ALG_CBC_NO_PADDING || PSA_WANT_ALG_CBC_PKCS7 */
560 #if defined(PSA_WANT_ALG_ECB_NO_PADDING)
561 case PSA_ALG_ECB_NO_PADDING:
562 return PSA_SUCCESS;
563 #endif /* PSA_WANT_ALG_ECB_NO_PADDING */
564 #if defined(PSA_WANT_ALG_CTR)
565 case PSA_ALG_CTR:
566 return PSA_SUCCESS;
567 #endif /* PSA_WANT_ALG_CTR */
568 #if defined(PSA_WANT_ALG_OFB)
569 case PSA_ALG_OFB:
570 return PSA_SUCCESS;
571 #endif /* PSA_WANT_ALG_OFB */
572 default:
573 return PSA_ERROR_NOT_SUPPORTED;
574 } /* operation->alg */
575 break;
576 #endif /* PSA_WANT_KEY_TYPE_AES */
577 #if defined(PSA_WANT_KEY_TYPE_CHACHA20)
578 case PSA_KEY_TYPE_CHACHA20:
579 ret = cc3xx_chacha20_finish(&operation->ctx.chacha, output,
580 output_size, output_length);
581 cc3xx_chacha20_free(&operation->ctx.chacha);
582 break;
583 #endif /* PSA_WANT_KEY_TYPE_CHACHA20 */
584
585 default:
586 ret = PSA_ERROR_NOT_SUPPORTED;
587 }
588
589 return ret;
590 }
591
cc3xx_cipher_abort(cc3xx_cipher_operation_t * operation)592 psa_status_t cc3xx_cipher_abort(cc3xx_cipher_operation_t *operation)
593 {
594 switch (operation->key_type) {
595 #if defined(PSA_WANT_KEY_TYPE_AES)
596 case PSA_KEY_TYPE_AES:
597 cc3xx_aes_free(&operation->ctx.aes);
598 break;
599 #endif /* PSA_WANT_KEY_TYPE_AES */
600 #if defined(PSA_WANT_KEY_TYPE_CHACHA20)
601 case PSA_KEY_TYPE_CHACHA20:
602 cc3xx_chacha20_free(&operation->ctx.chacha);
603 break;
604 #endif /* PSA_WANT_KEY_TYPE_CHACHA20 */
605 default:
606 return PSA_ERROR_NOT_SUPPORTED;
607 }
608
609 CC_PalMemSetZero(operation, sizeof(cc3xx_cipher_operation_t));
610
611 return PSA_SUCCESS;
612 }
613
cc3xx_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)614 psa_status_t cc3xx_cipher_encrypt(
615 const psa_key_attributes_t *attributes,
616 const uint8_t *key_buffer,
617 size_t key_buffer_size,
618 psa_algorithm_t alg,
619 const uint8_t *iv,
620 size_t iv_length,
621 const uint8_t *input,
622 size_t input_length,
623 uint8_t *output,
624 size_t output_size,
625 size_t *output_length)
626 {
627 psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
628 cc3xx_cipher_operation_t operation = {0};
629 size_t olength, accumulated_length = 0;
630
631 if ( (ret = cc3xx_cipher_encrypt_setup(
632 &operation,
633 attributes,
634 key_buffer,
635 key_buffer_size,
636 alg) )
637 != PSA_SUCCESS) {
638 cc3xx_cipher_abort(&operation);
639 return ret;
640 }
641
642 /* ECB doesn't not expect an IV */
643 if (alg != PSA_ALG_ECB_NO_PADDING) {
644 if (operation.iv_size != iv_length) {
645 cc3xx_cipher_abort(&operation);
646 return PSA_ERROR_INVALID_ARGUMENT;
647 }
648
649 if ( (ret = cc3xx_cipher_set_iv(
650 &operation,
651 iv,
652 iv_length) )
653 != PSA_SUCCESS) {
654 cc3xx_cipher_abort(&operation);
655 return ret;
656 }
657 }
658
659 if ( (ret = cc3xx_cipher_update(
660 &operation,
661 input,
662 input_length,
663 output,
664 output_size,
665 &olength) )
666 != PSA_SUCCESS) {
667 cc3xx_cipher_abort(&operation);
668 return ret;
669 }
670
671 accumulated_length += olength;
672
673 if ( (ret = cc3xx_cipher_finish(
674 &operation,
675 output + accumulated_length,
676 output_size - accumulated_length,
677 &olength) )
678 != PSA_SUCCESS) {
679 cc3xx_cipher_abort(&operation);
680 return ret;
681 }
682
683 *output_length = accumulated_length + olength;
684
685 ret = cc3xx_cipher_abort(&operation);
686
687 return ret;
688 }
689
cc3xx_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)690 psa_status_t cc3xx_cipher_decrypt(
691 const psa_key_attributes_t *attributes,
692 const uint8_t *key_buffer,
693 size_t key_buffer_size,
694 psa_algorithm_t alg,
695 const uint8_t *input,
696 size_t input_length,
697 uint8_t *output,
698 size_t output_size,
699 size_t *output_length)
700 {
701 psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
702 cc3xx_cipher_operation_t operation = {0};
703 size_t olength, accumulated_length;
704
705 if ( (ret = cc3xx_cipher_decrypt_setup(
706 &operation,
707 attributes,
708 key_buffer,
709 key_buffer_size,
710 alg) )
711 != PSA_SUCCESS) {
712 cc3xx_cipher_abort(&operation);
713 return ret;
714 }
715
716 /* ECB doesn't not expect an IV */
717 if (alg != PSA_ALG_ECB_NO_PADDING) {
718 if ( (ret = cc3xx_cipher_set_iv(
719 &operation,
720 input,
721 operation.iv_size) )
722 != PSA_SUCCESS) {
723 cc3xx_cipher_abort(&operation);
724 return ret;
725 }
726 }
727
728 if ( (ret = cc3xx_cipher_update(
729 &operation,
730 input + operation.iv_size,
731 input_length - operation.iv_size,
732 output,
733 output_size,
734 &olength) )
735 != PSA_SUCCESS) {
736 cc3xx_cipher_abort(&operation);
737 return ret;
738 }
739
740 accumulated_length = olength;
741
742 if ( (ret = cc3xx_cipher_finish(
743 &operation,
744 output + accumulated_length,
745 output_size - accumulated_length,
746 &olength) )
747 != PSA_SUCCESS) {
748 cc3xx_cipher_abort(&operation);
749 return ret;
750 }
751
752 *output_length = accumulated_length + olength;
753
754 ret = cc3xx_cipher_abort(&operation);
755
756 return ret;
757 }
758 /** @} */ // end of psa_cipher
759