Merge remote-tracking branch 'upstream-public/pr/1629' into evaluation

This commit is contained in:
Jaeden Amero 2018-05-14 17:54:25 +01:00
commit fa66c9eba2
4 changed files with 315 additions and 4 deletions

View File

@ -65,6 +65,55 @@ mbedtls_ccm_context;
#include "ccm_alt.h"
#endif /* MBEDTLS_CCM_ALT */
/**
* \brief The CCM* callback for encrypting with variable tag length.
* The function pointer is passed to the APIs called. This
* function calculates the nonce and returns it in a buffer.
*
* \warning This function must not return the same nonce more than once
* in the lifetime of the key!
*
* \note To prevent attacks taking advantage of the variable tag
* length CCM* encodes the tag length in the nonce. The method
* of encoding may vary. Standards might mandate encoding other
* information in the nonce (e.g. address and frame counter)
* too.
*
* \param app_ctx A pointer to structure containing the application context
* if it is necessary for calculating the initialisation vector
* (nonce).
* \param tag_len Length of the tag in bytes.
* \nonce Output variable, points to the buffer capable of holding the
* calculated nonce. Must be at least \p nonce_len bytes long.
* \nonce_len The length of the nonce in bytes.
*
* \return \c 0 on success.
* \return MBEDTLS_ERR_CCM_BAD_INPUT error code on failure.
*/
typedef int (*mbedtls_ccm_star_get_nonce_t)( void *app_ctx, size_t tag_len,
unsigned char *nonce,
size_t nonce_len );
/**
* \brief The CCM* callback for decrypting with variable tag length.
* The function pointer is passed to the APIs called. This
* function calculates and returns the length of the tag in the
* output parameter.
*
* \param app_ctx A pointer to structure containing the application context
* if it is necessary for decoding the tag length or validating
* the initialisation vector (nonce).
* \param tag_len Output variable for holding the tag length in bytes.
* \nonce A buffer containing the nonce.
* \nonce_len The length of the nonce in bytes.
*
* \return \c 0 on success.
* \return MBEDTLS_ERR_CCM_BAD_INPUT error code on failure.
*/
typedef int (*mbedtls_ccm_star_get_tag_len_t)( void *app_ctx, size_t* tag_len,
const unsigned char *nonce,
size_t nonce_len );
/**
* \brief This function initializes the specified CCM context,
* to make references valid, and prepare the context
@ -102,7 +151,6 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx );
/**
* \brief This function encrypts a buffer using CCM.
*
*
* \note The tag is written to a separate buffer. To concatenate
* the \p tag with the \p output, as done in <em>RFC-3610:
* Counter with CBC-MAC (CCM)</em>, use
@ -132,6 +180,82 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len );
/**
* \brief This function encrypts a buffer using CCM* with fixed tag
* length.
*
* \note The tag is written to a separate buffer. To concatenate
* the \p tag with the \p output, as done in <em>RFC-3610:
* Counter with CBC-MAC (CCM)</em>, use
* \p tag = \p output + \p length, and make sure that the
* output buffer is at least \p length + \p tag_len wide.
*
* \param ctx The CCM context to use for encryption.
* \param length The length of the input data in Bytes.
* \param iv Initialization vector (nonce).
* \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
* \param add The additional data field.
* \param add_len The length of additional data in Bytes.
* Must be less than 2^16 - 2^8.
* \param input The buffer holding the input data.
* \param output The buffer holding the output data.
* Must be at least \p length Bytes wide.
* \param tag The buffer holding the tag.
* \param tag_len The length of the tag to generate in Bytes:
* 0, 4, 6, 8, 10, 12, 14 or 16.
*
* \warning Passing 0 as \p tag_len means that the message is no
* longer authenticated.
*
* \return \c 0 on success.
* \return A CCM or cipher-specific error code on failure.
*/
int mbedtls_ccm_sfix_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len );
/**
* \brief This function encrypts a buffer using CCM* with variable
* tag length.
*
* \note The tag is written to a separate buffer. To concatenate
* the \p tag with the \p output, as done in <em>RFC-3610:
* Counter with CBC-MAC (CCM)</em>, use
* \p tag = \p output + \p length, and make sure that the
* output buffer is at least \p length + \p tag_len wide.
*
* \param ctx The CCM context to use for encryption.
* \param length The length of the input data in Bytes.
* \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12,
* or 13.
* \param add The additional data field.
* \param add_len The length of additional data in Bytes.
* Must be less than 2^16 - 2^8.
* \param input The buffer holding the input data.
* \param output The buffer holding the output data.
* Must be at least \p length Bytes wide.
* \param tag The buffer holding the tag.
* \param tag_len The length of the tag to generate in Bytes:
* 0, 4, 6, 8, 10, 12, 14 or 16.
* \param get_iv A callback function returning the IV (nonce) with the
* tag length encoded in it.
* \param get_iv_ctx Context passed to the \p get_iv callback.
*
* \warning Passing 0 as \p tag_len means that the message is no
* longer authenticated.
*
* \return \c 0 on success.
* \return A CCM or cipher-specific error code on failure.
*/
int mbedtls_ccm_svar_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
size_t iv_len, const unsigned char *add,
size_t add_len, const unsigned char *input,
unsigned char *output, unsigned char *tag,
size_t tag_len, mbedtls_ccm_star_get_nonce_t get_iv,
void *get_iv_ctx );
/**
* \brief This function performs a CCM authenticated decryption of a
* buffer.
@ -160,6 +284,74 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len );
/**
* \brief This function performs a CCM* authenticated decryption of a
* buffer with fixed tag length.
*
* \param ctx The CCM context to use for decryption.
* \param length The length of the input data in Bytes.
* \param iv Initialization vector.
* \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
* \param add The additional data field.
* \param add_len The length of additional data in Bytes.
* Must be less than 2^16 - 2^8.
* \param input The buffer holding the input data.
* \param output The buffer holding the output data.
* Must be at least \p length Bytes wide.
* \param tag The buffer holding the tag.
* \param tag_len The length of the tag in Bytes.
* 0, 4, 6, 8, 10, 12, 14 or 16.
*
* \warning Passing 0 as \p tag_len means that the message is no
* longer authenticated.
*
* \return \c 0 on success. This indicates that the message is
* authentic.
* \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
* \return A cipher-specific error code on calculation failure.
*/
int mbedtls_ccm_sfix_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len );
/**
* \brief This function performs a CCM* authenticated decryption
* of a buffer with variable tag length.
*
* \param ctx The CCM context to use for decryption.
* \param length The length of the input data in Bytes.
* \param iv Initialization vector.
* \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12,
* or 13.
* \param add The additional data field.
* \param add_len The length of additional data in Bytes.
* Must be less than 2^16 - 2^8.
* \param input The buffer holding the input data. Unlike the \p input
* parameters of other Mbed TLS CCM functions, this buffer
* holds the concatenation of the encrypted data and the
* authentication tag.
* \param output The buffer holding the output data.
* Must be at least \p length Bytes wide.
* \param output_len The length of the decrypted data.
* \param get_tag_len A callback function returning the tag length.
* \param get_tlen_ctx Context passed to the \p get_tag_len callback.
*
*
* \return \c 0 on success. This indicates that the message is
* authentic.
* \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
* \return A cipher-specific error code on calculation failure.
*/
int mbedtls_ccm_svar_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
size_t* output_len,
mbedtls_ccm_star_get_tag_len_t get_tag_len,
void *get_tlen_ctx );
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/**

View File

@ -154,7 +154,13 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
* 'length' checked later (when writing it to the first block)
*/
if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
{
/*
* Loosen the requirements to enable support for CCM* (IEEE 802.15.4)
*/
if( tag_len != 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
}
/* Also implies q is within bounds */
if( iv_len < 7 || iv_len > 13 )
@ -302,7 +308,7 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
/*
* Authenticated encryption
*/
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
int mbedtls_ccm_sfix_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
@ -312,10 +318,41 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
add, add_len, input, output, tag, tag_len ) );
}
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len )
{
if( tag_len == 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
return( mbedtls_ccm_sfix_encrypt_and_tag( ctx, length, iv, iv_len, add,
add_len, input, output, tag, tag_len ) );
}
#define CCM_MAX_IV_LEN 13
int mbedtls_ccm_svar_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
size_t iv_len, const unsigned char *add,
size_t add_len, const unsigned char *input,
unsigned char *output, unsigned char *tag,
size_t tag_len, mbedtls_ccm_star_get_nonce_t get_iv,
void *get_iv_ctx )
{
unsigned char iv[CCM_MAX_IV_LEN];
if( get_iv( get_iv_ctx, tag_len, iv, iv_len ) != 0 )
return MBEDTLS_ERR_CCM_BAD_INPUT;
return( mbedtls_ccm_sfix_encrypt_and_tag( ctx, length, iv, iv_len, add,
add_len, input, output, tag, tag_len ) );
}
/*
* Authenticated decryption
*/
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
int mbedtls_ccm_sfix_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
@ -346,6 +383,38 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
return( 0 );
}
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len )
{
if( tag_len == 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
return( mbedtls_ccm_sfix_auth_decrypt( ctx, length, iv, iv_len, add,
add_len, input, output, tag, tag_len ) );
}
int mbedtls_ccm_svar_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
size_t* output_len,
mbedtls_ccm_star_get_tag_len_t get_tag_len,
void *get_tlen_ctx )
{
size_t tag_len = 0;
if( get_tag_len( get_tlen_ctx, &tag_len, iv, iv_len ) != 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
*output_len = length - tag_len;
return( mbedtls_ccm_sfix_auth_decrypt( ctx, length, iv, iv_len, add,
add_len, input, output, input + length, tag_len ) );
}
#endif /* !MBEDTLS_CCM_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)

View File

@ -41,6 +41,15 @@ ccm_lengths:5:10:65281:8:MBEDTLS_ERR_CCM_BAD_INPUT
CCM lengths #8 msg too long for this IV length (2^16, q = 2)
ccm_lengths:65536:13:5:8:MBEDTLS_ERR_CCM_BAD_INPUT
CCM lengths #9 tag length 0
ccm_lengths:5:10:5:0:MBEDTLS_ERR_CCM_BAD_INPUT
CCM* fixed tag lengths #1 all OK
ccm_sfix_lengths:5:10:5:8:0
CCM* fixed tag lengths #2 all OK - tag length 0
ccm_sfix_lengths:5:10:5:0:0
CCM encrypt and tag RFC 3610 #1
depends_on:MBEDTLS_AES_C
mbedtls_ccm_encrypt_and_tag:MBEDTLS_CIPHER_ID_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":"08090A0B0C0D0E0F101112131415161718191A1B1C1D1E":"00000003020100A0A1A2A3A4A5":"0001020304050607":"588C979A61C663D2F066D0C2C0F989806D5F6B61DAC38417E8D12CFDF926E0"

View File

@ -74,6 +74,47 @@ exit:
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_AES_C */
void ccm_sfix_lengths( int msg_len, int iv_len, int add_len, int tag_len,
int res )
{
mbedtls_ccm_context ctx;
unsigned char key[16];
unsigned char msg[10];
unsigned char iv[14];
unsigned char add[10];
unsigned char out[10];
unsigned char tag[18];
int decrypt_ret;
mbedtls_ccm_init( &ctx );
memset( key, 0, sizeof( key ) );
memset( msg, 0, sizeof( msg ) );
memset( iv, 0, sizeof( iv ) );
memset( add, 0, sizeof( add ) );
memset( out, 0, sizeof( out ) );
memset( tag, 0, sizeof( tag ) );
TEST_ASSERT( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
key, 8 * sizeof( key ) ) == 0 );
TEST_ASSERT( mbedtls_ccm_sfix_encrypt_and_tag( &ctx, msg_len, iv, iv_len,
add, add_len, msg, out, tag, tag_len ) == res );
decrypt_ret = mbedtls_ccm_sfix_auth_decrypt( &ctx, msg_len, iv, iv_len, add,
add_len, msg, out, tag, tag_len );
if( res == 0 && tag_len != 0 )
TEST_ASSERT( decrypt_ret == MBEDTLS_ERR_CCM_AUTH_FAILED );
else
TEST_ASSERT( decrypt_ret == res );
exit:
mbedtls_ccm_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */
void mbedtls_ccm_encrypt_and_tag( int cipher_id,
char *key_hex, char *msg_hex,