mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-04-25 09:02:48 +00:00
Add output parameter to mbedtls_gcm_finish
Alternative implementations of GCM may delay the output of partial blocks from mbedtls_gcm_update(). Add an output parameter to mbedtls_gcm_finish() to allow such implementations to pass the final partial block back to the caller. With the software implementation, this final output is always empty. Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
parent
441907ec30
commit
9461e45a17
@ -1,3 +1,13 @@
|
|||||||
|
API changes
|
||||||
|
* The interface of the GCM module has changed to remove restrictions on
|
||||||
|
how the input to multipart operations is broken down. mbedtls_gcm_finish()
|
||||||
|
now takes an extra output parameter for the last partial output block.
|
||||||
|
The software implementation always produces the full output at each
|
||||||
|
call to mbedtls_gcm_update(), but alternative implementations activated
|
||||||
|
by MBEDTLS_GCM_ALT may delay partial blocks to the next call to
|
||||||
|
mbedtls_gcm_update() or mbedtls_gcm_finish().
|
||||||
|
These changes are backward compatible for users of the cipher API.
|
||||||
|
|
||||||
Features
|
Features
|
||||||
* The multi-part GCM interface (mbedtls_gcm_update() or
|
* The multi-part GCM interface (mbedtls_gcm_update() or
|
||||||
mbedtls_cipher_update()) no longer requires the size of partial inputs to
|
mbedtls_cipher_update()) no longer requires the size of partial inputs to
|
||||||
|
@ -282,13 +282,23 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
|
|||||||
* buffer of at least \p tag_len Bytes.
|
* buffer of at least \p tag_len Bytes.
|
||||||
* \param tag_len The length of the tag to generate. This must be at least
|
* \param tag_len The length of the tag to generate. This must be at least
|
||||||
* four.
|
* four.
|
||||||
|
* \param output The buffer for the final output.
|
||||||
|
* This must be a writable buffer of at least \p output_len
|
||||||
|
* bytes.
|
||||||
|
* With the built-in implementation, there is no final
|
||||||
|
* output and this can be \p NULL.
|
||||||
|
* Alternative implementations may return a partial block
|
||||||
|
* of output.
|
||||||
|
* \param output_len The size of the \p output buffer in bytes.
|
||||||
|
* With the built-in implementation, this can be \c 0.
|
||||||
|
* Alternative implementations may require a 15-byte buffer.
|
||||||
*
|
*
|
||||||
* \return \c 0 on success.
|
* \return \c 0 on success.
|
||||||
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
|
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
|
||||||
*/
|
*/
|
||||||
int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
|
int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
|
||||||
unsigned char *tag,
|
unsigned char *output, size_t output_len,
|
||||||
size_t tag_len );
|
unsigned char *tag, size_t tag_len );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief This function clears a GCM context and the underlying
|
* \brief This function clears a GCM context and the underlying
|
||||||
|
@ -1101,6 +1101,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
|
|||||||
#if defined(MBEDTLS_GCM_C)
|
#if defined(MBEDTLS_GCM_C)
|
||||||
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
|
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
|
||||||
return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
|
return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
|
||||||
|
NULL, 0,
|
||||||
tag, tag_len ) );
|
tag, tag_len ) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1153,6 +1154,7 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
|
|||||||
|
|
||||||
if( 0 != ( ret = mbedtls_gcm_finish(
|
if( 0 != ( ret = mbedtls_gcm_finish(
|
||||||
(mbedtls_gcm_context *) ctx->cipher_ctx,
|
(mbedtls_gcm_context *) ctx->cipher_ctx,
|
||||||
|
NULL, 0,
|
||||||
check_tag, tag_len ) ) )
|
check_tag, tag_len ) ) )
|
||||||
{
|
{
|
||||||
return( ret );
|
return( ret );
|
||||||
|
@ -471,8 +471,8 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
|
int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
|
||||||
unsigned char *tag,
|
unsigned char *output, size_t output_len,
|
||||||
size_t tag_len )
|
unsigned char *tag, size_t tag_len )
|
||||||
{
|
{
|
||||||
unsigned char work_buf[16];
|
unsigned char work_buf[16];
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -482,6 +482,11 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
|
|||||||
GCM_VALIDATE_RET( ctx != NULL );
|
GCM_VALIDATE_RET( ctx != NULL );
|
||||||
GCM_VALIDATE_RET( tag != NULL );
|
GCM_VALIDATE_RET( tag != NULL );
|
||||||
|
|
||||||
|
/* We never pass any output in finish(). The output parameter exists only
|
||||||
|
* for the sake of alternative implementations. */
|
||||||
|
(void) output;
|
||||||
|
(void) output_len;
|
||||||
|
|
||||||
orig_len = ctx->len * 8;
|
orig_len = ctx->len * 8;
|
||||||
orig_add_len = ctx->add_len * 8;
|
orig_add_len = ctx->add_len * 8;
|
||||||
|
|
||||||
@ -541,7 +546,7 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
|
|||||||
if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
|
if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 )
|
||||||
return( ret );
|
return( ret );
|
||||||
|
|
||||||
if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 )
|
if( ( ret = mbedtls_gcm_finish( ctx, NULL, 0, tag, tag_len ) ) != 0 )
|
||||||
return( ret );
|
return( ret );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -979,7 +984,7 @@ int mbedtls_gcm_self_test( int verbose )
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
|
ret = mbedtls_gcm_finish( &ctx, NULL, 0, tag_buf, 16 );
|
||||||
if( ret != 0 )
|
if( ret != 0 )
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
@ -1039,7 +1044,7 @@ int mbedtls_gcm_self_test( int verbose )
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
|
ret = mbedtls_gcm_finish( &ctx, NULL, 0, tag_buf, 16 );
|
||||||
if( ret != 0 )
|
if( ret != 0 )
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ static int check_multipart( mbedtls_gcm_context *ctx,
|
|||||||
output = NULL;
|
output = NULL;
|
||||||
|
|
||||||
ASSERT_ALLOC( output, tag->len );
|
ASSERT_ALLOC( output, tag->len );
|
||||||
TEST_EQUAL( 0, mbedtls_gcm_finish( ctx, output, tag->len ) );
|
TEST_EQUAL( 0, mbedtls_gcm_finish( ctx, NULL, 0, output, tag->len ) );
|
||||||
ASSERT_COMPARE( output, tag->len, tag->x, tag->len );
|
ASSERT_COMPARE( output, tag->len, tag->x, tag->len );
|
||||||
mbedtls_free( output );
|
mbedtls_free( output );
|
||||||
output = NULL;
|
output = NULL;
|
||||||
@ -326,10 +326,10 @@ void gcm_invalid_param( )
|
|||||||
/* mbedtls_gcm_finish() */
|
/* mbedtls_gcm_finish() */
|
||||||
TEST_INVALID_PARAM_RET(
|
TEST_INVALID_PARAM_RET(
|
||||||
MBEDTLS_ERR_GCM_BAD_INPUT,
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
||||||
mbedtls_gcm_finish( NULL, valid_buffer, valid_len ) );
|
mbedtls_gcm_finish( NULL, NULL, 0, valid_buffer, valid_len ) );
|
||||||
TEST_INVALID_PARAM_RET(
|
TEST_INVALID_PARAM_RET(
|
||||||
MBEDTLS_ERR_GCM_BAD_INPUT,
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
||||||
mbedtls_gcm_finish( &ctx, NULL, valid_len ) );
|
mbedtls_gcm_finish( &ctx, NULL, 0, NULL, valid_len ) );
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
mbedtls_gcm_free( &ctx );
|
mbedtls_gcm_free( &ctx );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user