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