From e193ea8cb9df86586d1b90f88a8c1c97851de1cd Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Fri, 1 Oct 2021 13:00:16 +0100 Subject: [PATCH] Add Multipart AEAD CCM internal implementation Signed-off-by: Paul Elliott --- library/psa_crypto.c | 23 ++++++++++++ library/psa_crypto_aead.c | 77 +++++++++++++++++++++++++++++++-------- 2 files changed, 84 insertions(+), 16 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index ece64b100d..d8c9d14554 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3868,6 +3868,15 @@ psa_status_t psa_aead_generate_nonce( psa_aead_operation_t *operation, goto exit; } + /* For CCM, this size may not be correct according to the PSA + * specification. The PSA Crypto 1.0.1 specification states: + * + * CCM encodes the plaintext length pLen in L octets, with L the smallest + * integer >= 2 where pLen < 2^(8L). The nonce length is then 15 - L bytes. + * + * However this restriction that L has to be the smallest integer is not + * applied in practice, and it is not implementable here since the + * plaintext length may or may not be known at this time. */ required_nonce_size = PSA_AEAD_NONCE_LENGTH( operation->key_type, operation->alg ); if( nonce_size < required_nonce_size ) @@ -4030,6 +4039,13 @@ psa_status_t psa_aead_update_ad( psa_aead_operation_t *operation, operation->ad_remaining -= input_length; } +#if defined(PSA_WANT_ALG_CCM) + else if( operation->alg == PSA_ALG_CCM ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } +#endif /* PSA_WANT_ALG_CCM */ status = psa_driver_wrapper_aead_update_ad( operation, input, input_length ); @@ -4087,6 +4103,13 @@ psa_status_t psa_aead_update( psa_aead_operation_t *operation, operation->body_remaining -= input_length; } +#if defined(PSA_WANT_ALG_CCM) + else if( operation->alg == PSA_ALG_CCM ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } +#endif /* PSA_WANT_ALG_CCM */ status = psa_driver_wrapper_aead_update( operation, input, input_length, output, output_size, diff --git a/library/psa_crypto_aead.c b/library/psa_crypto_aead.c index a72865c04c..9dd40dd543 100644 --- a/library/psa_crypto_aead.c +++ b/library/psa_crypto_aead.c @@ -346,13 +346,6 @@ psa_status_t mbedtls_psa_aead_encrypt_setup( { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; -#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) - if( operation->alg == PSA_ALG_CCM ) - { - return( PSA_ERROR_NOT_SUPPORTED ); - } -#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ - status = psa_aead_setup( operation, attributes, key_buffer, key_buffer_size, alg ); @@ -373,13 +366,6 @@ psa_status_t mbedtls_psa_aead_decrypt_setup( { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; -#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) - if( operation->alg == PSA_ALG_CCM ) - { - return( PSA_ERROR_NOT_SUPPORTED ); - } -#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ - status = psa_aead_setup( operation, attributes, key_buffer, key_buffer_size, alg ); @@ -409,6 +395,18 @@ psa_status_t mbedtls_psa_aead_set_nonce( } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation->alg == PSA_ALG_CCM ) + { + status = mbedtls_to_psa_error( + mbedtls_ccm_starts( &operation->ctx.ccm, + operation->is_encrypt ? + MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT, + nonce, + nonce_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if( operation->alg == PSA_ALG_CHACHA20_POLY1305 ) { @@ -446,11 +444,22 @@ psa_status_t mbedtls_psa_aead_set_lengths( size_t ad_length, size_t plaintext_length ) { - /* Nothing here yet, work is currently done in PSA Core, however support - * for CCM will require this function. */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation->alg == PSA_ALG_CCM ) + { + return( mbedtls_to_psa_error( + mbedtls_ccm_set_lengths( &operation->ctx.ccm, + ad_length, + plaintext_length, + operation->tag_length ) ) ); + + } +#else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ ( void ) operation; ( void ) ad_length; ( void ) plaintext_length; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ return ( PSA_SUCCESS ); } @@ -471,6 +480,14 @@ psa_status_t mbedtls_psa_aead_update_ad( } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation->alg == PSA_ALG_CCM ) + { + status = mbedtls_to_psa_error( + mbedtls_ccm_update_ad( &operation->ctx.ccm, input, input_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if( operation->alg == PSA_ALG_CHACHA20_POLY1305 ) { @@ -521,6 +538,20 @@ psa_status_t mbedtls_psa_aead_update( } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation->alg == PSA_ALG_CCM ) + { + if( output_size < input_length ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = mbedtls_to_psa_error( + mbedtls_ccm_update( &operation->ctx.ccm, + input, input_length, + output, output_size, + &update_output_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if( operation->alg == PSA_ALG_CHACHA20_POLY1305 ) { @@ -577,6 +608,20 @@ psa_status_t mbedtls_psa_aead_finish( } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation->alg == PSA_ALG_CCM ) + { + /* tag must be big enough to store a tag of size passed into set + * lengths. */ + if( tag_size < operation->tag_length ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = mbedtls_to_psa_error( + mbedtls_ccm_finish( &operation->ctx.ccm, + tag, operation->tag_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if( operation->alg == PSA_ALG_CHACHA20_POLY1305 ) {