mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-03-25 04:43:32 +00:00
Remove alignment requirement for mbedtls_gcm_update: implementation
mbedtls_gcm_update now accepts inputs of arbitrary size. There is no longer a requirement that all calls except the last one pass a multiple of 16 bytes. This commit updates the library code and adjusts the GCM tests to exercise arbitrarily aligned input sizes. Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
parent
36dd93e745
commit
58fc272af9
113
library/gcm.c
113
library/gcm.c
@ -355,21 +355,64 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Increment the counter. */
|
||||
static void gcm_incr( unsigned char y[16] )
|
||||
{
|
||||
size_t i;
|
||||
for( i = 16; i > 12; i-- )
|
||||
if( ++y[i - 1] != 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
/* Calculate and apply the encryption mask. Process use_len bytes of data,
|
||||
* starting at position offset in the mask block. */
|
||||
static int gcm_mask( mbedtls_gcm_context *ctx,
|
||||
unsigned char ectr[16],
|
||||
size_t offset, size_t use_len,
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
size_t i;
|
||||
size_t olen = 0;
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
|
||||
&olen ) ) != 0 )
|
||||
{
|
||||
mbedtls_platform_zeroize( ectr, 16 );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
for( i = 0; i < use_len; i++ )
|
||||
{
|
||||
if( ctx->mode == MBEDTLS_GCM_DECRYPT )
|
||||
ctx->buf[offset + i] ^= input[i];
|
||||
output[i] = ectr[offset + i] ^ input[i];
|
||||
if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
|
||||
ctx->buf[offset + i] ^= output[i];
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
|
||||
size_t length,
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
unsigned char ectr[16];
|
||||
size_t i;
|
||||
const unsigned char *p;
|
||||
const unsigned char *p = input;
|
||||
unsigned char *out_p = output;
|
||||
size_t use_len, olen = 0;
|
||||
size_t offset;
|
||||
unsigned char ectr[16];
|
||||
|
||||
/* Exit early if length==0 so that we don't do any pointer arithmetic on
|
||||
* a potentially null pointer. */
|
||||
if( length == 0 )
|
||||
return( 0 );
|
||||
|
||||
GCM_VALIDATE_RET( ctx != NULL );
|
||||
GCM_VALIDATE_RET( length == 0 || input != NULL );
|
||||
GCM_VALIDATE_RET( length == 0 || output != NULL );
|
||||
GCM_VALIDATE_RET( input != NULL );
|
||||
GCM_VALIDATE_RET( output != NULL );
|
||||
|
||||
if( output > input && (size_t) ( output - input ) < length )
|
||||
return( MBEDTLS_ERR_GCM_BAD_INPUT );
|
||||
@ -382,39 +425,48 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
|
||||
return( MBEDTLS_ERR_GCM_BAD_INPUT );
|
||||
}
|
||||
|
||||
ctx->len += length;
|
||||
|
||||
p = input;
|
||||
while( length > 0 )
|
||||
offset = ctx->len % 16;
|
||||
if( offset != 0 )
|
||||
{
|
||||
use_len = ( length < 16 ) ? length : 16;
|
||||
size_t use_len = 16 - offset;
|
||||
if( use_len > length )
|
||||
use_len = length;
|
||||
|
||||
for( i = 16; i > 12; i-- )
|
||||
if( ++ctx->y[i - 1] != 0 )
|
||||
break;
|
||||
|
||||
if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
|
||||
&olen ) ) != 0 )
|
||||
{
|
||||
if( ( ret = gcm_mask( ctx, ectr, offset, use_len, p, out_p ) ) != 0 )
|
||||
return( ret );
|
||||
}
|
||||
|
||||
for( i = 0; i < use_len; i++ )
|
||||
{
|
||||
if( ctx->mode == MBEDTLS_GCM_DECRYPT )
|
||||
ctx->buf[i] ^= p[i];
|
||||
out_p[i] = ectr[i] ^ p[i];
|
||||
if( ctx->mode == MBEDTLS_GCM_ENCRYPT )
|
||||
ctx->buf[i] ^= out_p[i];
|
||||
}
|
||||
|
||||
gcm_mult( ctx, ctx->buf, ctx->buf );
|
||||
if( offset + use_len == 16 )
|
||||
gcm_mult( ctx, ctx->buf, ctx->buf );
|
||||
|
||||
ctx->len += use_len;
|
||||
length -= use_len;
|
||||
p += use_len;
|
||||
out_p += use_len;
|
||||
}
|
||||
|
||||
ctx->len += length;
|
||||
|
||||
while( length >= 16 )
|
||||
{
|
||||
gcm_incr( ctx->y );
|
||||
if( ( ret = gcm_mask( ctx, ectr, 0, 16, p, out_p ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
gcm_mult( ctx, ctx->buf, ctx->buf );
|
||||
|
||||
length -= 16;
|
||||
p += 16;
|
||||
out_p += 16;
|
||||
}
|
||||
|
||||
if( length > 0 )
|
||||
{
|
||||
gcm_incr( ctx->y );
|
||||
if( ( ret = gcm_mask( ctx, ectr, 0, length, p, out_p ) ) != 0 )
|
||||
return( ret );
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize( ectr, sizeof( ectr ) );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
@ -436,6 +488,9 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
|
||||
if( tag_len > 16 || tag_len < 4 )
|
||||
return( MBEDTLS_ERR_GCM_BAD_INPUT );
|
||||
|
||||
if( ctx->len % 16 != 0 )
|
||||
gcm_mult( ctx, ctx->buf, ctx->buf );
|
||||
|
||||
memcpy( tag, ctx->base_ectr, tag_len );
|
||||
|
||||
if( orig_len || orig_add_len )
|
||||
|
@ -111,7 +111,7 @@ void gcm_encrypt_and_tag( int cipher_id, data_t * key_str,
|
||||
ASSERT_COMPARE( output, src_str->len, dst->x, dst->len );
|
||||
ASSERT_COMPARE( tag_output, tag_len, tag->x, tag->len );
|
||||
|
||||
for( n1 = 16; n1 < src_str->len; n1 += 16 )
|
||||
for( n1 = 0; n1 <= src_str->len; n1 += 1 )
|
||||
{
|
||||
mbedtls_test_set_step( n1 );
|
||||
if( !check_multipart( &ctx, MBEDTLS_GCM_ENCRYPT,
|
||||
@ -159,7 +159,7 @@ void gcm_decrypt_and_verify( int cipher_id, data_t * key_str,
|
||||
TEST_ASSERT( ret == 0 );
|
||||
ASSERT_COMPARE( output, src_str->len, pt_result->x, pt_result->len );
|
||||
|
||||
for( n1 = 16; n1 < src_str->len; n1 += 16 )
|
||||
for( n1 = 0; n1 <= src_str->len; n1 += 1 )
|
||||
{
|
||||
mbedtls_test_set_step( n1 );
|
||||
if( !check_multipart( &ctx, MBEDTLS_GCM_DECRYPT,
|
||||
|
Loading…
x
Reference in New Issue
Block a user