diff --git a/include/mbedtls/ccm.h b/include/mbedtls/ccm.h index 6f991fefbd..0dc5b59683 100644 --- a/include/mbedtls/ccm.h +++ b/include/mbedtls/ccm.h @@ -198,6 +198,7 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, * \param ctx The CCM context to use for encryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. + * For tag length = 0, input length is ignored. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, @@ -207,6 +208,7 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, * at least \p ad_len Bytes. * \param ad_len The length of additional data in Bytes. * This must be less than 2^16 - 2^8. + * For tag length = 0, AD length can be 0. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least * that length. @@ -279,6 +281,7 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, * \param ctx The CCM context to use for decryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. + * For tag length = 0, input length is ignored. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, @@ -288,6 +291,7 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, * at least that \p ad_len Bytes. * \param ad_len The length of additional data in Bytes. * This must be less than 2^16 - 2^8. + * For tag length = 0, AD length can be 0. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least * that length. diff --git a/library/ccm.c b/library/ccm.c index 15efff79f0..e062678569 100644 --- a/library/ccm.c +++ b/library/ccm.c @@ -150,9 +150,20 @@ static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx) if( !(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGHTS_SET) ) return 0; - if( ctx->tag_len == 0 && \ - ( ctx->mode == MBEDTLS_CCM_ENCRYPT || ctx->mode == MBEDTLS_CCM_DECRYPT ) ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); + /* CCM expects non-empty tag. + * CCM* allows empty tag. For CCM* without tag, ignore plaintext length. + */ + if( ctx->tag_len == 0 ) + { + if( ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT ) + { + ctx->plaintext_len = 0; + } + else + { + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + } + } /* * First block: @@ -342,7 +353,10 @@ int mbedtls_ccm_update( mbedtls_ccm_context *ctx, return MBEDTLS_ERR_CCM_BAD_INPUT; } - if( ctx->processed + input_len > ctx->plaintext_len ) + /* Check against plaintext length only if performing operation with + * authentication + */ + if( ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len ) { return MBEDTLS_ERR_CCM_BAD_INPUT; }