@@ -393,6 +393,102 @@ psa_status_t cc3xx_aead_update_ad(
393
393
return PSA_ERROR_CORRUPTION_DETECTED ;
394
394
}
395
395
396
+ #if !defined(CC3XX_CONFIG_AES_TUNNELLING_ENABLE ) && defined(PSA_WANT_ALG_CCM )
397
+ /**
398
+ * @brief Encrypt or decrypt a message fragment in an active AEAD AES-CCM operation.
399
+ * This is only required when CryptoCell is operating in non-tunnelling
400
+ * mode, in which case AES-CCM only computes the CBC-MAC tag, and thus a
401
+ * separate AES-CTR call is required
402
+ *
403
+ * @param[in] operation Active AEAD operation.
404
+ * @param[in] input Buffer containing the message fragment.
405
+ * @param[in] input_length Size of the input buffer in bytes.
406
+ * @param[out] output Buffer where the output is to be written.
407
+ * @param[in] output_size Size of the output buffer in bytes.
408
+ * @param[out] output_length The number of bytes that make up the output.
409
+ * @param[in] block_buf_size_in_use Current AES DMA buffer usage in bytes.
410
+ *
411
+ * @return psa_status_t
412
+ */
413
+ static psa_status_t cc3xx_aead_ccm_ctr_update (
414
+ cc3xx_aead_operation_t * operation ,
415
+ const uint8_t * input ,
416
+ size_t input_length ,
417
+ uint8_t * output ,
418
+ size_t output_size ,
419
+ size_t * output_length ,
420
+ size_t block_buf_size_in_use )
421
+ {
422
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED ;
423
+ cc3xx_err_t err ;
424
+ struct cc3xx_aes_state_t * state = & operation -> aes ;
425
+ size_t processed_bytes = 0 ;
426
+ size_t counter_incr_val = (block_buf_size_in_use + input_length ) / AES_BLOCK_SIZE ;
427
+
428
+ err = cc3xx_lowlevel_aes_init (CC3XX_AES_DIRECTION_ENCRYPT ,
429
+ CC3XX_AES_MODE_CTR , CC3XX_AES_KEY_ID_USER_KEY ,
430
+ (uint32_t * )state -> key_buf , state -> key_size ,
431
+ (uint32_t * )state -> ctr , AES_IV_LEN );
432
+ if (err != CC3XX_ERR_SUCCESS ) {
433
+ return cc3xx_to_psa_err (err );
434
+ }
435
+
436
+ if (block_buf_size_in_use > 0 ) {
437
+ size_t partial_len = ((block_buf_size_in_use + input_length ) < AES_BLOCK_SIZE ) ?
438
+ input_length : AES_BLOCK_SIZE - block_buf_size_in_use ;
439
+ uint8_t scratch_block [AES_BLOCK_SIZE ] = {0 };
440
+ size_t current_output_size = cc3xx_lowlevel_aes_get_current_output_size ();
441
+
442
+ cc3xx_lowlevel_aes_set_output_buffer (scratch_block , AES_BLOCK_SIZE );
443
+
444
+ err = cc3xx_lowlevel_aes_update (scratch_block , block_buf_size_in_use );
445
+ if (err != CC3XX_ERR_SUCCESS ) {
446
+ return cc3xx_to_psa_err (err );
447
+ }
448
+
449
+ err = cc3xx_lowlevel_aes_update (input , partial_len );
450
+ if (err != CC3XX_ERR_SUCCESS ) {
451
+ return cc3xx_to_psa_err (err );
452
+ }
453
+
454
+ cc3xx_lowlevel_dma_flush_buffer (false);
455
+
456
+ /* Write-back the partially-encrypted data */
457
+ memcpy (output , scratch_block + block_buf_size_in_use , partial_len );
458
+
459
+ processed_bytes = cc3xx_lowlevel_aes_get_current_output_size () -
460
+ (current_output_size + block_buf_size_in_use );
461
+ }
462
+
463
+ if ((input_length - processed_bytes ) > 0 ) {
464
+ const uint8_t * remaining_input = input + processed_bytes ;
465
+ const size_t remaining_input_length = input_length - processed_bytes ;
466
+ uint8_t * remaining_output = output + processed_bytes ;
467
+ const size_t remaining_output_size = output_size - processed_bytes ;
468
+ size_t current_output_size = cc3xx_lowlevel_aes_get_current_output_size ();
469
+
470
+ cc3xx_lowlevel_aes_set_output_buffer (remaining_output , remaining_output_size );
471
+
472
+ err = cc3xx_lowlevel_aes_update (remaining_input , remaining_input_length );
473
+ if (err != CC3XX_ERR_SUCCESS ) {
474
+ return cc3xx_to_psa_err (err );
475
+ }
476
+
477
+ cc3xx_lowlevel_dma_flush_buffer (false);
478
+
479
+ processed_bytes += cc3xx_lowlevel_aes_get_current_output_size () - current_output_size ;
480
+ }
481
+
482
+ * output_length += processed_bytes ;
483
+
484
+ if (counter_incr_val > 0 ) {
485
+ c3xx_lowlevel_aes_ccm_incr_ctr (state -> ctr , counter_incr_val );
486
+ }
487
+
488
+ return PSA_SUCCESS ;
489
+ }
490
+ #endif /* !CC3XX_CONFIG_AES_TUNNELLING_ENABLE && PSA_WANT_ALG_CCM */
491
+
396
492
psa_status_t cc3xx_aead_update (
397
493
cc3xx_aead_operation_t * operation ,
398
494
const uint8_t * input ,
@@ -404,12 +500,46 @@ psa_status_t cc3xx_aead_update(
404
500
cc3xx_err_t err ;
405
501
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED ;
406
502
size_t last_output_num_bytes = 0 , current_output_size = 0 ;
503
+ #if !defined(CC3XX_CONFIG_AES_TUNNELLING_ENABLE ) && defined(PSA_WANT_ALG_CCM )
504
+ bool ctr_required ;
505
+ size_t ctr_block_buf_size_in_use = 0 ;
506
+ #endif /* !CC3XX_CONFIG_AES_TUNNELLING_ENABLE && PSA_WANT_ALG_CCM */
407
507
408
508
CC3XX_ASSERT (operation != NULL );
409
509
CC3XX_ASSERT (input != NULL );
410
510
CC3XX_ASSERT (output != NULL );
411
511
CC3XX_ASSERT (output_length != NULL );
412
512
513
+ /* Initialize this length to a safe value that might be overridden */
514
+ * output_length = 0 ;
515
+
516
+ #if !defined(CC3XX_CONFIG_AES_TUNNELLING_ENABLE ) && defined(PSA_WANT_ALG_CCM )
517
+ ctr_required = ((operation -> key_type == PSA_KEY_TYPE_AES ) &&
518
+ (operation -> aes .mode == CC3XX_AES_MODE_CCM ) &&
519
+ (input_length > 0 ) && (output_size > 0 )) ? true : false;
520
+
521
+ if (ctr_required ) {
522
+ ctr_block_buf_size_in_use = (operation -> aes .crypted_length > 0 ) ?
523
+ operation -> aes .dma_state .block_buf_size_in_use : 0 ;
524
+
525
+ if (operation -> aes .direction == CC3XX_AES_DIRECTION_DECRYPT ) {
526
+ status = cc3xx_aead_ccm_ctr_update (operation ,
527
+ input ,
528
+ input_length ,
529
+ output ,
530
+ output_size ,
531
+ output_length ,
532
+ ctr_block_buf_size_in_use );
533
+ if (status != PSA_SUCCESS ) {
534
+ return status ;
535
+ }
536
+
537
+ /* CBC-MAC computes the tag on plaintext data */
538
+ input = output ;
539
+ }
540
+ }
541
+ #endif /* !CC3XX_CONFIG_AES_TUNNELLING_ENABLE && PSA_WANT_ALG_CCM */
542
+
413
543
/* This either restores the state or completes the init */
414
544
status = cc3xx_internal_cipher_setup_complete (operation );
415
545
if (status != PSA_SUCCESS ) {
@@ -505,21 +635,34 @@ psa_status_t cc3xx_aead_update(
505
635
506
636
err = cc3xx_lowlevel_aes_update (input , input_length );
507
637
if (err != CC3XX_ERR_SUCCESS ) {
508
- status = cc3xx_to_psa_err ( err );
509
- goto out_aes ;
638
+ cc3xx_lowlevel_aes_uninit ( );
639
+ return cc3xx_to_psa_err ( err ) ;
510
640
}
511
641
current_output_size = cc3xx_lowlevel_aes_get_current_output_size ();
512
642
513
- * output_length = current_output_size - last_output_num_bytes ;
643
+ * output_length + = current_output_size - last_output_num_bytes ;
514
644
515
645
operation -> last_output_num_bytes = current_output_size ;
516
646
517
647
cc3xx_lowlevel_aes_get_state (& operation -> aes );
518
648
519
- status = PSA_SUCCESS ;
520
- out_aes :
521
649
cc3xx_lowlevel_aes_uninit ();
522
- return status ;
650
+
651
+ #if !defined(CC3XX_CONFIG_AES_TUNNELLING_ENABLE ) && defined(PSA_WANT_ALG_CCM )
652
+ if ((ctr_required ) && (operation -> aes .direction == CC3XX_AES_DIRECTION_ENCRYPT )) {
653
+ status = cc3xx_aead_ccm_ctr_update (operation ,
654
+ input ,
655
+ input_length ,
656
+ output ,
657
+ output_size ,
658
+ output_length ,
659
+ ctr_block_buf_size_in_use );
660
+ if (status != PSA_SUCCESS ) {
661
+ return status ;
662
+ }
663
+ }
664
+ #endif /* !CC3XX_CONFIG_AES_TUNNELLING_ENABLE && PSA_WANT_ALG_CCM */
665
+ return PSA_SUCCESS ;
523
666
#endif /* PSA_WANT_KEY_TYPE_AES */
524
667
525
668
default :
0 commit comments