14
14
#include <sxsymcrypt/chachapoly.h>
15
15
#include <sxsymcrypt/internal.h>
16
16
#include <sxsymcrypt/keyref.h>
17
+ #include <cracen/mem_helpers.h>
17
18
#include <cracen/statuscodes.h>
18
19
#include <zephyr/sys/__assert.h>
19
-
20
20
#include "common.h"
21
- #include <cracen/mem_helpers.h>
22
21
23
22
/* CCM, GCM and ChaCha20-Poly1305 have 16 byte tags by default */
24
23
#define DEFAULT_TAG_SIZE 16
25
24
25
+ #define CCM_HEADER_MAX_LENGTH 26
26
+
26
27
/*
27
28
* This function assumes it is given a valid algorithm for aead.
28
29
*/
@@ -57,8 +58,10 @@ static bool is_nonce_length_supported(psa_algorithm_t alg, size_t nonce_length)
57
58
case PSA_ALG_GCM :
58
59
case PSA_ALG_CHACHA20_POLY1305 :
59
60
return nonce_length == 12u ;
61
+ #ifdef PSA_NEED_CRACEN_CCM_AES
60
62
case PSA_ALG_CCM :
61
63
return sx_aead_aesccm_nonce_size_is_valid (nonce_length );
64
+ #endif
62
65
}
63
66
64
67
return false;
@@ -195,12 +198,12 @@ static void cracen_writebe(uint8_t *out, uint64_t data, uint16_t targetsz)
195
198
}
196
199
}
197
200
198
- static psa_status_t create_aead_ccmheader (cracen_aead_operation_t * operation )
201
+ static void create_aead_ccmheader (cracen_aead_operation_t * operation ,
202
+ uint8_t header [static CCM_HEADER_MAX_LENGTH ],
203
+ size_t * header_length )
199
204
{
200
205
uint8_t flags ;
201
206
size_t m , l ;
202
- uint8_t header [26 ] = {0 };
203
- size_t header_size = 16 ;
204
207
205
208
/* RFC3610 paragraph 2.2 defines the formatting of the first block.
206
209
* M, CCM TAG size is one of {4,6,8,10,12,14,16}, CCM* not supported
@@ -232,28 +235,27 @@ static psa_status_t create_aead_ccmheader(cracen_aead_operation_t *operation)
232
235
233
236
cracen_writebe (& (header [1 + operation -> nonce_length ]), operation -> plaintext_length , l );
234
237
238
+ * header_length = 16 ;
235
239
/*
236
240
* If there is additional authentication data, encode the size into
237
241
* bytes [16, 17/21/25] depending on the length
238
242
*/
239
243
if (operation -> ad_length > 0 ) {
240
244
if (operation -> ad_length < 0xFF00 ) {
241
245
cracen_writebe (& header [16 ], operation -> ad_length , 2 );
242
- header_size += 2 ;
246
+ * header_length += 2 ;
243
247
} else if (operation -> ad_length <= 0xFFFFFFFF ) {
244
248
header [16 ] = 0xFF ;
245
249
header [17 ] = 0xFE ;
246
250
cracen_writebe (& header [18 ], operation -> ad_length , 4 );
247
- header_size += 6 ;
251
+ * header_length += 6 ;
248
252
} else {
249
253
header [16 ] = 0xFF ;
250
254
header [17 ] = 0xFF ;
251
255
cracen_writebe (& header [18 ], operation -> ad_length , 8 );
252
- header_size += 10 ;
256
+ * header_length += 10 ;
253
257
}
254
258
}
255
-
256
- return cracen_aead_update_ad (operation , header , header_size );
257
259
}
258
260
259
261
static psa_status_t setup (cracen_aead_operation_t * operation , enum cipher_operation dir ,
@@ -343,8 +345,8 @@ psa_status_t cracen_aead_decrypt_setup(cracen_aead_operation_t *operation,
343
345
return setup (operation , CRACEN_DECRYPT , attributes , key_buffer , key_buffer_size , alg );
344
346
}
345
347
346
- psa_status_t cracen_aead_set_nonce (cracen_aead_operation_t * operation , const uint8_t * nonce ,
347
- size_t nonce_length )
348
+ static psa_status_t set_nonce (cracen_aead_operation_t * operation , const uint8_t * nonce ,
349
+ size_t nonce_length )
348
350
{
349
351
if (!is_nonce_length_supported (operation -> alg , nonce_length )) {
350
352
return PSA_ERROR_NOT_SUPPORTED ;
@@ -353,9 +355,26 @@ psa_status_t cracen_aead_set_nonce(cracen_aead_operation_t *operation, const uin
353
355
memcpy (operation -> nonce , nonce , nonce_length );
354
356
operation -> nonce_length = nonce_length ;
355
357
358
+ return PSA_SUCCESS ;
359
+ }
360
+
361
+ psa_status_t cracen_aead_set_nonce (cracen_aead_operation_t * operation , const uint8_t * nonce ,
362
+ size_t nonce_length )
363
+ {
364
+ psa_status_t status ;
365
+
366
+ status = set_nonce (operation , nonce , nonce_length );
367
+ if (status != PSA_SUCCESS ) {
368
+ return status ;
369
+ }
370
+
356
371
/* Create the CCM header */
357
- if (operation -> alg == PSA_ALG_CCM ) {
358
- return create_aead_ccmheader (operation );
372
+ if (IS_ENABLED (PSA_NEED_CRACEN_CCM_AES ) && operation -> alg == PSA_ALG_CCM ) {
373
+ uint8_t ccm_header [CCM_HEADER_MAX_LENGTH ];
374
+ size_t ccm_header_length ;
375
+
376
+ create_aead_ccmheader (operation , ccm_header , & ccm_header_length );
377
+ return cracen_aead_update_ad (operation , ccm_header , ccm_header_length );
359
378
}
360
379
361
380
return PSA_SUCCESS ;
@@ -428,13 +447,14 @@ static psa_status_t cracen_aead_update_internal(cracen_aead_operation_t *operati
428
447
/* Clamp input length to a multiple of the block size. */
429
448
blk_bytes = input_length & ~(get_block_size (operation -> alg ) - 1 );
430
449
431
- /* For CCM, sxsymcrypt driver needs a chunk of input data to produce a tag
450
+ /* For CCM, in multi-part mode sxsymcrypt needs a chunk of input data to produce a tag
432
451
* therefore we buffer the last block until finish will be called.
433
452
* blk_bytes tracks the amount of block-sized input that will be
434
453
* processed immediately. So to buffer the input and prevent processing
435
454
* we subtract one block from blk_bytes.
436
455
*/
437
- if (operation -> alg == PSA_ALG_CCM && input_length != 0 && blk_bytes == input_length ) {
456
+ if (IS_ENABLED (PSA_NEED_CRACEN_CCM_AES ) &&
457
+ operation -> alg == PSA_ALG_CCM && input_length != 0 && blk_bytes == input_length ) {
438
458
blk_bytes -= get_block_size (operation -> alg );
439
459
}
440
460
@@ -607,7 +627,7 @@ psa_status_t cracen_aead_verify(cracen_aead_operation_t *operation, uint8_t *pla
607
627
608
628
safe_memzero ((void * )operation , sizeof (cracen_aead_operation_t ));
609
629
610
- return silex_statuscodes_to_psa ( sx_status ) ;
630
+ return PSA_SUCCESS ;
611
631
}
612
632
613
633
psa_status_t cracen_aead_abort (cracen_aead_operation_t * operation )
@@ -616,6 +636,49 @@ psa_status_t cracen_aead_abort(cracen_aead_operation_t *operation)
616
636
return PSA_SUCCESS ;
617
637
}
618
638
639
+ static psa_status_t feed_singlepart_ccm_aad (cracen_aead_operation_t * operation ,
640
+ const uint8_t * additional_data ,
641
+ size_t additional_data_length )
642
+ {
643
+ psa_status_t status ;
644
+ /* Data fed to CRACEN needs to remain untouched until it's been consumed
645
+ * (sx_aead_wait()), so don't put the CCM header buffer on the stack.
646
+ */
647
+ static uint8_t ccm_header_aad [ROUND_UP (CCM_HEADER_MAX_LENGTH ,
648
+ PSA_BLOCK_CIPHER_BLOCK_LENGTH (PSA_KEY_TYPE_AES ))];
649
+ size_t ccm_header_length ;
650
+ size_t aad_fed_count ;
651
+
652
+ create_aead_ccmheader (operation , ccm_header_aad , & ccm_header_length );
653
+
654
+ if (additional_data_length != 0 ) {
655
+ /* Data fed to CRACEN needs to be block size-aligned, so
656
+ * complete the header with the beginning of the user-provided AAD.
657
+ */
658
+ aad_fed_count = MIN (additional_data_length ,
659
+ sizeof (ccm_header_aad ) - ccm_header_length );
660
+ memcpy (ccm_header_aad + ccm_header_length , additional_data , aad_fed_count );
661
+ } else {
662
+ aad_fed_count = 0 ;
663
+ }
664
+
665
+ status = cracen_feed_data_to_hw (operation , ccm_header_aad ,
666
+ ccm_header_length + aad_fed_count , NULL , true);
667
+ if (status != PSA_SUCCESS ) {
668
+ return status ;
669
+ }
670
+
671
+ if (additional_data_length != aad_fed_count ) {
672
+ /* Feed the rest of the user-provided AAD.
673
+ * The last feeding doesn't need to be block size-aligned.
674
+ */
675
+ status = cracen_feed_data_to_hw (operation , additional_data + aad_fed_count ,
676
+ additional_data_length - aad_fed_count , NULL , true);
677
+ }
678
+
679
+ return status ;
680
+ }
681
+
619
682
psa_status_t cracen_aead_encrypt (const psa_key_attributes_t * attributes , const uint8_t * key_buffer ,
620
683
size_t key_buffer_size , psa_algorithm_t alg , const uint8_t * nonce ,
621
684
size_t nonce_length , const uint8_t * additional_data ,
@@ -625,57 +688,57 @@ psa_status_t cracen_aead_encrypt(const psa_key_attributes_t *attributes, const u
625
688
{
626
689
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED ;
627
690
cracen_aead_operation_t operation = {0 };
628
- size_t update_length = 0 ;
629
- uint8_t local_tag_buffer [PSA_AEAD_TAG_MAX_SIZE ] = {0 };
630
- size_t tag_length = 0 ;
691
+ size_t tag_length ;
631
692
632
- status =
633
- cracen_aead_encrypt_setup (& operation , attributes , key_buffer , key_buffer_size , alg );
634
- if (status != PSA_SUCCESS ) {
635
- goto error_exit ;
693
+ if (ciphertext_size < plaintext_length ) {
694
+ return PSA_ERROR_BUFFER_TOO_SMALL ;
636
695
}
637
696
638
- status = cracen_aead_set_lengths (& operation , additional_data_length , plaintext_length );
697
+ status = cracen_aead_encrypt_setup (& operation , attributes ,
698
+ key_buffer , key_buffer_size , alg );
639
699
if (status != PSA_SUCCESS ) {
640
700
goto error_exit ;
641
701
}
642
702
643
- status = cracen_aead_set_nonce (& operation , nonce , nonce_length );
703
+ status = cracen_aead_set_lengths (& operation , additional_data_length , plaintext_length );
644
704
if (status != PSA_SUCCESS ) {
645
705
goto error_exit ;
646
706
}
647
707
648
- status = cracen_aead_update_ad (& operation , additional_data , additional_data_length );
708
+ /* Do not call the cracen_aead_update*() functions to avoid using
709
+ * HW context switching (process_on_hw()) in single-part operations.
710
+ */
711
+
712
+ status = set_nonce (& operation , nonce , nonce_length );
649
713
if (status != PSA_SUCCESS ) {
650
714
goto error_exit ;
651
715
}
652
716
653
- status = cracen_aead_update (& operation , plaintext , plaintext_length , ciphertext ,
654
- ciphertext_size , ciphertext_length );
717
+ if (IS_ENABLED (PSA_NEED_CRACEN_CCM_AES ) && alg == PSA_ALG_CCM ) {
718
+ status = feed_singlepart_ccm_aad (& operation , additional_data ,
719
+ additional_data_length );
720
+ } else {
721
+ status = cracen_feed_data_to_hw (& operation , additional_data ,
722
+ additional_data_length , NULL , true);
723
+ }
655
724
if (status != PSA_SUCCESS ) {
656
- * ciphertext_length = 0 ;
657
725
goto error_exit ;
658
726
}
659
727
660
- status = cracen_aead_finish (& operation , & ciphertext [* ciphertext_length ],
661
- ciphertext_size - * ciphertext_length , & update_length ,
662
- local_tag_buffer , sizeof (local_tag_buffer ), & tag_length );
728
+ status = cracen_feed_data_to_hw (& operation , plaintext , plaintext_length , ciphertext , false);
663
729
if (status != PSA_SUCCESS ) {
664
- * ciphertext_length = 0 ;
665
730
goto error_exit ;
666
731
}
667
- * ciphertext_length += update_length ;
668
732
669
- /* Copy tag to the end of the ciphertext buffer, if big enough */
670
- if ( * ciphertext_length + tag_length > ciphertext_size ) {
671
- * ciphertext_length = 0 ;
672
- status = PSA_ERROR_BUFFER_TOO_SMALL ;
733
+ status = cracen_aead_finish ( & operation , NULL , 0 , NULL ,
734
+ & ciphertext [ plaintext_length ],
735
+ ciphertext_size - plaintext_length , & tag_length ) ;
736
+ if ( status != PSA_SUCCESS ) {
673
737
goto error_exit ;
674
738
}
675
- memcpy (& ciphertext [* ciphertext_length ], & local_tag_buffer , tag_length );
676
- * ciphertext_length += tag_length ;
677
739
678
- return status ;
740
+ * ciphertext_length = plaintext_length + tag_length ;
741
+ return PSA_SUCCESS ;
679
742
680
743
error_exit :
681
744
cracen_aead_abort (& operation );
@@ -691,49 +754,61 @@ psa_status_t cracen_aead_decrypt(const psa_key_attributes_t *attributes, const u
691
754
{
692
755
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED ;
693
756
cracen_aead_operation_t operation = {0 };
694
- size_t update_length = 0 ;
695
757
696
- status =
697
- cracen_aead_decrypt_setup ( & operation , attributes , key_buffer , key_buffer_size , alg );
758
+ status = cracen_aead_decrypt_setup ( & operation , attributes ,
759
+ key_buffer , key_buffer_size , alg );
698
760
if (status != PSA_SUCCESS ) {
699
761
goto error_exit ;
700
762
}
701
763
702
- status = cracen_aead_set_lengths (& operation , additional_data_length ,
703
- ciphertext_length - operation .tag_size );
764
+ * plaintext_length = ciphertext_length - operation .tag_size ;
765
+
766
+ if (plaintext_size < * plaintext_length ) {
767
+ status = PSA_ERROR_BUFFER_TOO_SMALL ;
768
+ goto error_exit ;
769
+ }
770
+
771
+ status = cracen_aead_set_lengths (& operation , additional_data_length , * plaintext_length );
704
772
if (status != PSA_SUCCESS ) {
705
773
goto error_exit ;
706
774
}
707
775
708
- status = cracen_aead_set_nonce (& operation , nonce , nonce_length );
776
+ /* Do not call the cracen_aead_update*() functions to avoid using
777
+ * HW context switching (process_on_hw()) in single-part operations.
778
+ */
779
+
780
+ status = set_nonce (& operation , nonce , nonce_length );
709
781
if (status != PSA_SUCCESS ) {
710
782
goto error_exit ;
711
783
}
712
784
713
- status = cracen_aead_update_ad (& operation , additional_data , additional_data_length );
785
+ if (IS_ENABLED (PSA_NEED_CRACEN_CCM_AES ) && alg == PSA_ALG_CCM ) {
786
+ status = feed_singlepart_ccm_aad (& operation , additional_data ,
787
+ additional_data_length );
788
+ } else {
789
+ status = cracen_feed_data_to_hw (& operation , additional_data ,
790
+ additional_data_length , NULL , true);
791
+ }
714
792
if (status != PSA_SUCCESS ) {
715
793
goto error_exit ;
716
794
}
717
795
718
- status = cracen_aead_update (& operation , ciphertext , ciphertext_length - operation . tag_size ,
719
- plaintext , plaintext_size , plaintext_length );
796
+ status = cracen_feed_data_to_hw (& operation , ciphertext ,
797
+ * plaintext_length , plaintext , false );
720
798
if (status != PSA_SUCCESS ) {
721
- * plaintext_length = 0 ;
722
799
goto error_exit ;
723
800
}
724
801
725
- status = cracen_aead_verify (& operation , & plaintext [* plaintext_length ],
726
- plaintext_size - * plaintext_length , & update_length ,
727
- & ciphertext [ciphertext_length - operation .tag_size ],
728
- operation .tag_size );
802
+ status = cracen_aead_verify (& operation , NULL , 0 , NULL ,
803
+ & ciphertext [* plaintext_length ], operation .tag_size );
729
804
if (status != PSA_SUCCESS ) {
730
- * plaintext_length = 0 ;
731
805
goto error_exit ;
732
806
}
733
- * plaintext_length += update_length ;
734
807
735
- return status ;
808
+ return PSA_SUCCESS ;
809
+
736
810
error_exit :
811
+ * plaintext_length = 0 ;
737
812
cracen_aead_abort (& operation );
738
813
return status ;
739
814
}
0 commit comments