From 22f7a35ca4de9bca49aa2e994eaa87460b3abe77 Mon Sep 17 00:00:00 2001 From: Mateusz Starzyk Date: Wed, 28 Jul 2021 15:08:47 +0200 Subject: [PATCH] Do not use output buffer for internal XOR during decryption. Signed-off-by: Mateusz Starzyk --- include/mbedtls/ccm.h | 2 ++ library/ccm.c | 56 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/include/mbedtls/ccm.h b/include/mbedtls/ccm.h index c903e68fd..06aa6a888 100644 --- a/include/mbedtls/ccm.h +++ b/include/mbedtls/ccm.h @@ -61,6 +61,8 @@ #define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /** Authenticated decryption failed. */ #define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F +/** Memory allocation failed */ +#define MBEDTLS_ERR_CCM_ALLOC_FAILED -0x0011 #ifdef __cplusplus extern "C" { diff --git a/library/ccm.c b/library/ccm.c index a6ba77435..3663a769d 100644 --- a/library/ccm.c +++ b/library/ccm.c @@ -36,14 +36,17 @@ #include -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #include #define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ #if !defined(MBEDTLS_CCM_ALT) @@ -330,13 +333,16 @@ int mbedtls_ccm_update( mbedtls_ccm_context *ctx, unsigned char *output, size_t output_size, size_t *output_len ) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int ret; unsigned char i; size_t use_len, offset, olen; + const size_t local_output_len = input_len; + unsigned char* local_output = NULL; + if( ctx->state & CCM_STATE__ERROR ) { - return ret; + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } if( ctx->processed + input_len > ctx->plaintext_len ) @@ -344,10 +350,24 @@ int mbedtls_ccm_update( mbedtls_ccm_context *ctx, return MBEDTLS_ERR_CCM_BAD_INPUT; } + /* Local output is used for decryption only. */ + if( ctx->mode == MBEDTLS_CCM_DECRYPT || \ + ctx->mode == MBEDTLS_CCM_STAR_DECRYPT ) + { + local_output = mbedtls_calloc( local_output_len, sizeof( *local_output) ); + if( local_output == NULL ) + { + ctx->state |= CCM_STATE__ERROR; + return MBEDTLS_ERR_CCM_ALLOC_FAILED; + } + } + if( output_size < input_len ) return( MBEDTLS_ERR_CCM_BAD_INPUT ); *output_len = input_len; + ret = 0; + while ( input_len > 0 ) { offset = ctx->processed % 16; @@ -370,31 +390,37 @@ int mbedtls_ccm_update( mbedtls_ccm_context *ctx, if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen ) ) != 0 ) { ctx->state |= CCM_STATE__ERROR; - return( ret ); + goto exit; } } ret = mbedtls_ccm_crypt( ctx, offset, use_len, input, output ); if( ret != 0 ) - return ret; + goto exit; } if( ctx->mode == MBEDTLS_CCM_DECRYPT || \ ctx->mode == MBEDTLS_CCM_STAR_DECRYPT ) { - ret = mbedtls_ccm_crypt( ctx, offset, use_len, input, output ); + /* Write decrypted data to local_output to avoid using output variable as + * input in the XOR operation for Y. + */ + ret = mbedtls_ccm_crypt( ctx, offset, use_len, input, local_output ); if( ret != 0 ) - return ret; + goto exit; for( i = 0; i < use_len; i++ ) - ctx->y[i + offset] ^= output[i]; + ctx->y[i + offset] ^= local_output[i]; + + memcpy( output, local_output, use_len ); + mbedtls_platform_zeroize( local_output, local_output_len ); if( use_len + offset == 16 || ctx->processed == ctx->plaintext_len ) { if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen ) ) != 0 ) { ctx->state |= CCM_STATE__ERROR; - return( ret ); + goto exit; } } } @@ -411,7 +437,15 @@ int mbedtls_ccm_update( mbedtls_ccm_context *ctx, output += use_len; } - return 0; +exit: + if( ctx->mode == MBEDTLS_CCM_DECRYPT || \ + ctx->mode == MBEDTLS_CCM_STAR_DECRYPT ) + { + mbedtls_platform_zeroize( local_output, local_output_len ); + mbedtls_free( local_output ); + } + + return ret; } int mbedtls_ccm_finish( mbedtls_ccm_context *ctx,