mirror of
				https://github.com/cuberite/polarssl.git
				synced 2025-11-04 04:32:24 -05: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 );
 | 
					    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,
 | 
					int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
 | 
				
			||||||
                size_t length,
 | 
					                size_t length,
 | 
				
			||||||
                const unsigned char *input,
 | 
					                const unsigned char *input,
 | 
				
			||||||
                unsigned char *output )
 | 
					                unsigned char *output )
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
					    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 | 
				
			||||||
    unsigned char ectr[16];
 | 
					    const unsigned char *p = input;
 | 
				
			||||||
    size_t i;
 | 
					 | 
				
			||||||
    const unsigned char *p;
 | 
					 | 
				
			||||||
    unsigned char *out_p = output;
 | 
					    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( ctx != NULL );
 | 
				
			||||||
    GCM_VALIDATE_RET( length == 0 || input != NULL );
 | 
					    GCM_VALIDATE_RET( input != NULL );
 | 
				
			||||||
    GCM_VALIDATE_RET( length == 0 || output != NULL );
 | 
					    GCM_VALIDATE_RET( output != NULL );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if( output > input && (size_t) ( output - input ) < length )
 | 
					    if( output > input && (size_t) ( output - input ) < length )
 | 
				
			||||||
        return( MBEDTLS_ERR_GCM_BAD_INPUT );
 | 
					        return( MBEDTLS_ERR_GCM_BAD_INPUT );
 | 
				
			||||||
@ -382,39 +425,48 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
 | 
				
			|||||||
        return( MBEDTLS_ERR_GCM_BAD_INPUT );
 | 
					        return( MBEDTLS_ERR_GCM_BAD_INPUT );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ctx->len += length;
 | 
					    offset = ctx->len % 16;
 | 
				
			||||||
 | 
					    if( offset != 0 )
 | 
				
			||||||
    p = input;
 | 
					 | 
				
			||||||
    while( length > 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( ( ret = gcm_mask( ctx, ectr, offset, use_len, p, out_p ) ) != 0 )
 | 
				
			||||||
            if( ++ctx->y[i - 1] != 0 )
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
 | 
					 | 
				
			||||||
                                   &olen ) ) != 0 )
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return( ret );
 | 
					            return( ret );
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for( i = 0; i < use_len; i++ )
 | 
					        if( offset + use_len == 16 )
 | 
				
			||||||
        {
 | 
					            gcm_mult( ctx, ctx->buf, ctx->buf );
 | 
				
			||||||
            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 );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ctx->len += use_len;
 | 
				
			||||||
        length -= use_len;
 | 
					        length -= use_len;
 | 
				
			||||||
        p += use_len;
 | 
					        p += use_len;
 | 
				
			||||||
        out_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 );
 | 
					    return( 0 );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -436,6 +488,9 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
 | 
				
			|||||||
    if( tag_len > 16 || tag_len < 4 )
 | 
					    if( tag_len > 16 || tag_len < 4 )
 | 
				
			||||||
        return( MBEDTLS_ERR_GCM_BAD_INPUT );
 | 
					        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 );
 | 
					    memcpy( tag, ctx->base_ectr, tag_len );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if( orig_len || orig_add_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( output, src_str->len, dst->x, dst->len );
 | 
				
			||||||
        ASSERT_COMPARE( tag_output, tag_len, tag->x, tag->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 );
 | 
					            mbedtls_test_set_step( n1 );
 | 
				
			||||||
            if( !check_multipart( &ctx, MBEDTLS_GCM_ENCRYPT,
 | 
					            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 );
 | 
					            TEST_ASSERT( ret == 0 );
 | 
				
			||||||
            ASSERT_COMPARE( output, src_str->len, pt_result->x, pt_result->len );
 | 
					            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 );
 | 
					                mbedtls_test_set_step( n1 );
 | 
				
			||||||
                if( !check_multipart( &ctx, MBEDTLS_GCM_DECRYPT,
 | 
					                if( !check_multipart( &ctx, MBEDTLS_GCM_DECRYPT,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user