Add support for chunked plaintext/cyphertext input.
Signed-off-by: Mateusz Starzyk <mateusz.starzyk@mobica.com>
diff --git a/library/ccm.c b/library/ccm.c
index ae5fa34..4b1b499 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -333,59 +333,67 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char i;
- size_t len_left, olen;
- const unsigned char *src;
- unsigned char *dst;
+ size_t use_len, offset, olen;
if( output_size < input_len )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
CCM_VALIDATE_RET( output_length != NULL );
*output_len = input_len;
- /*
- * Authenticate and {en,de}crypt the message.
- *
- * The only difference between encryption and decryption is
- * the respective order of authentication and {en,de}cryption.
- */
- len_left = input_len;
- src = input;
- dst = output;
-
- while( len_left > 0 )
+ if( ctx->processed == 0 )
{
- size_t use_len = len_left > 16 ? 16 : len_left;
-
- if( ctx->mode == CCM_ENCRYPT )
- {
- memset( ctx->b, 0, 16 );
- memcpy( ctx->b, src, use_len );
- UPDATE_CBC_MAC;
- }
-
- mbedtls_ccm_crypt( ctx, 0, use_len, src, dst );
-
- if( ctx->mode == CCM_DECRYPT )
- {
- memset( ctx->b, 0, 16 );
- memcpy( ctx->b, dst, use_len );
- UPDATE_CBC_MAC;
- }
-
- dst += use_len;
- src += use_len;
- len_left -= use_len;
-
- /*
- * Increment counter.
- * No need to check for overflow thanks to the length check above.
- */
- for( i = 0; i < ctx->q; i++ )
- if( ++(ctx->ctr)[15-i] != 0 )
- break;
+ memset( ctx->b, 0, 16 );
}
- return (0);
+ while ( input_len > 0 )
+ {
+ offset = ctx->processed % 16;
+
+ use_len = 16 - offset;
+
+ if( use_len > input_len )
+ use_len = input_len;
+
+ ctx->processed += use_len;
+ memcpy( ctx->b + offset, input, use_len );
+
+ if( use_len + offset == 16 || ctx->processed == ctx->plaintext_len )
+ {
+ if( ctx->mode == CCM_ENCRYPT )
+ {
+ UPDATE_CBC_MAC;
+ ret = mbedtls_ccm_crypt( ctx, 0, use_len, ctx->b, output );
+ if( ret != 0 )
+ return ret;
+ memset( ctx->b, 0, 16 );
+ }
+
+ if( ctx->mode == CCM_DECRYPT )
+ {
+ ret = mbedtls_ccm_crypt( ctx, 0, use_len, ctx->b, output );
+ if( ret != 0 )
+ return ret;
+ memset( ctx->b, 0, 16 );
+ memcpy( ctx->b, output, use_len );
+ UPDATE_CBC_MAC;
+ memset( ctx->b, 0, 16 );
+ }
+
+ input_len -= use_len;
+ input += use_len;
+ output += use_len;
+
+ /*
+ * Increment counter.
+ * No need to check for overflow thanks to the length check above.
+ */
+ for( i = 0; i < ctx->q; i++ )
+ if( ++(ctx->ctr)[15-i] != 0 )
+ break;
+ }
+ }
+
+ return 0;
}
int mbedtls_ccm_finish( mbedtls_ccm_context *ctx,