Add ChaCha20+Poly1305 to the Cipher module
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index c5a50c0..f954cce 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -37,7 +37,7 @@
#include <stddef.h>
-#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
#define MBEDTLS_CIPHER_MODE_AEAD
#endif
@@ -147,6 +147,7 @@
MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */
MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */
MBEDTLS_CIPHER_CHACHA20, /**< Chacha20 stream cipher. */
+ MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< Chacha20-Poly1305 AEAD cipher. */
} mbedtls_cipher_type_t;
/** Supported cipher modes. */
@@ -562,11 +563,11 @@
*/
int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx );
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
/**
* \brief This function adds additional data for AEAD ciphers.
- * Only supported with GCM. Must be called
- * exactly once, after mbedtls_cipher_reset().
+ * Currently supported with GCM and ChaCha20+Poly1305.
+ * Must be called exactly once, after mbedtls_cipher_reset().
*
* \param ctx The generic cipher context.
* \param ad The additional data to use.
@@ -577,7 +578,7 @@
*/
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
const unsigned char *ad, size_t ad_len );
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_AEAD_CHACHA20_POLY1305_C */
/**
* \brief The generic cipher update function. It encrypts or
@@ -635,10 +636,10 @@
int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen );
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
/**
* \brief This function writes a tag for AEAD ciphers.
- * Only supported with GCM.
+ * Currently supported with GCM and ChaCha20+Poly1305.
* Must be called after mbedtls_cipher_finish().
*
* \param ctx The generic cipher context.
@@ -653,7 +654,7 @@
/**
* \brief This function checks the tag for AEAD ciphers.
- * Only supported with GCM.
+ * Currently supported with GCM and ChaCha20+Poly1305.
* Must be called after mbedtls_cipher_finish().
*
* \param ctx The generic cipher context.
@@ -665,7 +666,7 @@
*/
int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
const unsigned char *tag, size_t tag_len );
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_AEAD_CHACHA20_POLY1305_C */
/**
* \brief The generic all-in-one encryption/decryption function,
diff --git a/library/cipher.c b/library/cipher.c
index 68d0c10..b51a40b 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -38,6 +38,10 @@
#include <stdlib.h>
#include <string.h>
+#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
+#include "mbedtls/aead_chacha20_poly1305.h"
+#endif
+
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#endif
@@ -65,6 +69,22 @@
#define MBEDTLS_CIPHER_MODE_STREAM
#endif
+/* Compare the contents of two buffers in constant time.
+ * Returns 0 if the contents are bitwise identical, otherwise returns
+ * a non-zero value. */
+static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len )
+{
+ const unsigned char *p1 = (const unsigned char*) v1;
+ const unsigned char *p2 = (const unsigned char*) v2;
+ size_t i;
+ unsigned char diff;
+
+ for( diff = 0, i = 0; i < len; i++ )
+ diff |= p1[i] ^ p2[i];
+
+ return (int)diff;
+}
+
static int supported_init = 0;
const int *mbedtls_cipher_list( void )
@@ -263,22 +283,45 @@
return( 0 );
}
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
const unsigned char *ad, size_t ad_len )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
ctx->iv, ctx->iv_size, ad, ad_len );
}
+#endif
+
+#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
+ if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+ {
+ int result;
+ mbedtls_aead_chacha20_poly1305_mode_t mode;
+
+ mode = ( ctx->operation == MBEDTLS_ENCRYPT )
+ ? MBEDTLS_AEAD_CHACHA20_POLY1305_ENCRYPT
+ : MBEDTLS_AEAD_CHACHA20_POLY1305_DECRYPT;
+
+ result = mbedtls_aead_chacha20_poly1305_starts( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ ctx->iv,
+ mode );
+ if ( result != 0 )
+ return( result );
+
+ return mbedtls_aead_chacha20_poly1305_update_aad( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ ad_len, ad );
+ }
+#endif
return( 0 );
}
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_AEAD_CHACHA20_POLY1305_C */
int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
size_t ilen, unsigned char *output, size_t *olen )
@@ -340,6 +383,21 @@
}
#endif
+ if( input == output &&
+ ( ctx->unprocessed_len != 0 || ilen % mbedtls_cipher_get_block_size( ctx ) ) )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
+ if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 )
+ {
+ *olen = ilen;
+ return mbedtls_aead_chacha20_poly1305_update( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ ilen, input, output );
+ }
+#endif
+
#if defined(MBEDTLS_CIPHER_MODE_CBC)
if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC )
{
@@ -672,7 +730,8 @@
return( 0 );
}
- if ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type )
+ if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) ||
+ ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) )
{
return( 0 );
}
@@ -788,7 +847,7 @@
}
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
unsigned char *tag, size_t tag_len )
{
@@ -798,8 +857,22 @@
if( MBEDTLS_ENCRYPT != ctx->operation )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len );
+#endif
+
+#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
+ if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+ {
+ /* Don't allow truncated MAC for Poly1305 */
+ if ( tag_len != 16U )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ return mbedtls_aead_chacha20_poly1305_finish( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ tag );
+ }
+#endif
return( 0 );
}
@@ -807,6 +880,7 @@
int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
const unsigned char *tag, size_t tag_len )
{
+ unsigned char check_tag[16];
int ret;
if( NULL == ctx || NULL == ctx->cipher_info ||
@@ -815,12 +889,9 @@
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
+#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
- unsigned char check_tag[16];
- size_t i;
- int diff;
-
if( tag_len > sizeof( check_tag ) )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@@ -831,18 +902,38 @@
}
/* Check the tag in "constant-time" */
- for( diff = 0, i = 0; i < tag_len; i++ )
- diff |= tag[i] ^ check_tag[i];
-
- if( diff != 0 )
+ if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
return( 0 );
}
+#endif /* MBEDTLS_GCM_C */
+
+#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
+ if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+ {
+ /* Don't allow truncated MAC for Poly1305 */
+ if ( tag_len != sizeof( check_tag ) )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ ret = mbedtls_aead_chacha20_poly1305_finish( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ check_tag );
+ if ( ret != 0 )
+ {
+ return( ret );
+ }
+
+ /* Check the tag in "constant-time" */
+ if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
+ return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
+
+ return( 0 );
+ }
+#endif /* MBEDTLS_AEAD_CHACHA20_POLY1305_C */
return( 0 );
}
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_GCM_C || MBEDTLS_AEAD_CHACHA20_POLY1305_C */
/*
* Packet-oriented wrapper for non-AEAD modes
@@ -901,6 +992,39 @@
tag, tag_len ) );
}
#endif /* MBEDTLS_CCM_C */
+#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
+ if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+ {
+ int ret;
+
+ if ( ( iv_len != ctx->cipher_info->iv_size ) ||
+ ( tag_len != 16U ) ) /* Truncated MAC is not allowed for Poly1305 */
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ *olen = ilen;
+
+ ret = mbedtls_aead_chacha20_poly1305_starts( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ iv, MBEDTLS_AEAD_CHACHA20_POLY1305_ENCRYPT );
+ if ( ret != 0 )
+ return( ret );
+
+ ret = mbedtls_aead_chacha20_poly1305_update_aad( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ ad_len, ad );
+ if ( ret != 0 )
+ return( ret );
+
+ ret = mbedtls_aead_chacha20_poly1305_update( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ ilen, input, output );
+ if ( ret != 0 )
+ return( ret );
+
+ ret = mbedtls_aead_chacha20_poly1305_finish( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ tag );
+ return( ret );
+ }
+#endif /* MBEDTLS_AEAD_CHACHA20_POLY1305_C */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
@@ -947,6 +1071,47 @@
return( ret );
}
#endif /* MBEDTLS_CCM_C */
+#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
+ if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
+ {
+ unsigned char check_tag[16];
+ int ret;
+
+ if ( ( iv_len != ctx->cipher_info->iv_size ) ||
+ ( tag_len != 16U ) ) /* Truncated MAC is not allowed for Poly1305 */
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ *olen = ilen;
+
+ ret = mbedtls_aead_chacha20_poly1305_starts( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ iv, MBEDTLS_AEAD_CHACHA20_POLY1305_DECRYPT );
+ if ( ret != 0 )
+ return( ret );
+
+ ret = mbedtls_aead_chacha20_poly1305_update_aad( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ ad_len, ad );
+ if ( ret != 0 )
+ return( ret );
+
+ ret = mbedtls_aead_chacha20_poly1305_update( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ ilen, input, output );
+ if ( ret != 0 )
+ return( ret );
+
+ ret = mbedtls_aead_chacha20_poly1305_finish( (mbedtls_aead_chacha20_poly1305_context*) ctx->cipher_ctx,
+ check_tag );
+ if ( ret != 0 )
+ return( ret );
+
+ /* Compare the tag in constant time */
+ if ( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 )
+ return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
+
+ return( 0 );
+ }
+#endif /* MBEDTLS_AEAD_CHACHA20_POLY1305_C */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index f4e7964..d8c5f06 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -33,6 +33,10 @@
#include "mbedtls/cipher_internal.h"
+#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
+#include "mbedtls/aead_chacha20_poly1305.h"
+#endif
+
#if defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h"
#endif
@@ -1352,6 +1356,71 @@
};
#endif /* MBEDTLS_CHACHA20_C */
+#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
+
+static int aead_chacha20_poly1305_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ if( key_bitlen != 256U )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ if ( 0 != mbedtls_aead_chacha20_poly1305_setkey( (mbedtls_aead_chacha20_poly1305_context*)ctx, key ) )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ return( 0 );
+}
+
+static void * aead_chacha20_poly1305_ctx_alloc( void )
+{
+ mbedtls_aead_chacha20_poly1305_context *ctx;
+ ctx = mbedtls_calloc( 1, sizeof( mbedtls_aead_chacha20_poly1305_context ) );
+
+ if( ctx == NULL )
+ return( NULL );
+
+ mbedtls_aead_chacha20_poly1305_init( ctx );
+
+ return( ctx );
+}
+
+static void aead_chacha20_poly1305_ctx_free( void *ctx )
+{
+ mbedtls_aead_chacha20_poly1305_free( (mbedtls_aead_chacha20_poly1305_context *) ctx );
+ mbedtls_free( ctx );
+}
+
+static const mbedtls_cipher_base_t aead_chacha20_poly1305_base_info = {
+ MBEDTLS_CIPHER_ID_CHACHA20,
+ NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ aead_chacha20_poly1305_setkey_wrap,
+ aead_chacha20_poly1305_setkey_wrap,
+ aead_chacha20_poly1305_ctx_alloc,
+ aead_chacha20_poly1305_ctx_free
+};
+static const mbedtls_cipher_info_t aead_chacha20_poly1305_info = {
+ MBEDTLS_CIPHER_CHACHA20_POLY1305,
+ MBEDTLS_MODE_NONE,
+ 256,
+ "CHACHA20-POLY1305",
+ 12,
+ 0,
+ 64,
+ &aead_chacha20_poly1305_base_info
+};
+#endif /* MBEDTLS_AEAD_CHACHA20_POLY1305_C */
+
#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
static int null_crypt_stream( void *ctx, size_t length,
const unsigned char *input,
@@ -1511,6 +1580,10 @@
{ MBEDTLS_CIPHER_CHACHA20, &chacha20_info },
#endif
+#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_C)
+ { MBEDTLS_CIPHER_CHACHA20_POLY1305, &aead_chacha20_poly1305_info },
+#endif
+
#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
{ MBEDTLS_CIPHER_NULL, &null_cipher_info },
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */
diff --git a/library/version_features.c b/library/version_features.c
index 64aa9f6..b73410c 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -84,6 +84,9 @@
#if defined(MBEDTLS_TIMING_ALT)
"MBEDTLS_TIMING_ALT",
#endif /* MBEDTLS_TIMING_ALT */
+#if defined(MBEDTLS_AEAD_CHACHA20_POLY1305_ALT)
+ "MBEDTLS_AEAD_CHACHA20_POLY1305_ALT",
+#endif /* MBEDTLS_AEAD_CHACHA20_POLY1305_ALT */
#if defined(MBEDTLS_AES_ALT)
"MBEDTLS_AES_ALT",
#endif /* MBEDTLS_AES_ALT */
@@ -126,6 +129,9 @@
#if defined(MBEDTLS_MD5_ALT)
"MBEDTLS_MD5_ALT",
#endif /* MBEDTLS_MD5_ALT */
+#if defined(MBEDTLS_POLY1305_ALT)
+ "MBEDTLS_POLY1305_ALT",
+#endif /* MBEDTLS_POLY1305_ALT */
#if defined(MBEDTLS_RIPEMD160_ALT)
"MBEDTLS_RIPEMD160_ALT",
#endif /* MBEDTLS_RIPEMD160_ALT */
@@ -168,9 +174,6 @@
#if defined(MBEDTLS_SHA512_PROCESS_ALT)
"MBEDTLS_SHA512_PROCESS_ALT",
#endif /* MBEDTLS_SHA512_PROCESS_ALT */
-#if defined(MBEDTLS_POLY1305_ALT)
- "MBEDTLS_POLY1305_ALT",
-#endif /* MBEDTLS_POLY1305_ALT */
#if defined(MBEDTLS_DES_SETKEY_ALT)
"MBEDTLS_DES_SETKEY_ALT",
#endif /* MBEDTLS_DES_SETKEY_ALT */
@@ -540,6 +543,9 @@
#if defined(MBEDTLS_CAMELLIA_C)
"MBEDTLS_CAMELLIA_C",
#endif /* MBEDTLS_CAMELLIA_C */
+#if defined(MBEDTLS_CHACHA20_C)
+ "MBEDTLS_CHACHA20_C",
+#endif /* MBEDTLS_CHACHA20_C */
#if defined(MBEDTLS_CCM_C)
"MBEDTLS_CCM_C",
#endif /* MBEDTLS_CCM_C */
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 03797ec..c7d9fad 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -56,6 +56,7 @@
add_test_suite(camellia)
add_test_suite(ccm)
add_test_suite(chacha20)
+add_test_suite(cipher cipher.aead_chacha20_poly1305)
add_test_suite(cipher cipher.aes)
add_test_suite(cipher cipher.arc4)
add_test_suite(cipher cipher.blowfish)
diff --git a/tests/Makefile b/tests/Makefile
index 4a23e64..e6ff26c 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -52,6 +52,7 @@
test_suite_base64$(EXEXT) test_suite_blowfish$(EXEXT) \
test_suite_camellia$(EXEXT) test_suite_ccm$(EXEXT) \
test_suite_chacha20$(EXEXT) test_suite_cmac$(EXEXT) \
+ test_suite_cipher.aead_chacha20_poly1305$(EXEXT) \
test_suite_cipher.aes$(EXEXT) \
test_suite_cipher.arc4$(EXEXT) test_suite_cipher.ccm$(EXEXT) \
test_suite_cipher.chacha20$(EXEXT) \
@@ -116,6 +117,10 @@
echo " Gen $@"
perl scripts/generate_code.pl suites test_suite_aes test_suite_aes.rest
+test_suite_cipher.aead_chacha20_poly1305.c : suites/test_suite_cipher.function suites/test_suite_cipher.aead_chacha20_poly1305.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
+ echo " Gen $@"
+ perl scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.aead_chacha20_poly1305
+
test_suite_cipher.aes.c : suites/test_suite_cipher.function suites/test_suite_cipher.aes.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
echo " Gen $@"
perl scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.aes
@@ -261,6 +266,10 @@
echo " CC $<"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+test_suite_cipher.aead_chacha20_poly1305$(EXEXT): test_suite_cipher.aead_chacha20_poly1305.c $(DEP)
+ echo " CC $<"
+ $(CC) $(LOCAL_CFLAGS) $(CFLAGS) $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
test_suite_cipher.arc4$(EXEXT): test_suite_cipher.arc4.c $(DEP)
echo " CC $<"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) $< $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
diff --git a/tests/suites/test_suite_cipher.aead_chacha20_poly1305.data b/tests/suites/test_suite_cipher.aead_chacha20_poly1305.data
new file mode 100644
index 0000000..9cd1ed0
--- /dev/null
+++ b/tests/suites/test_suite_cipher.aead_chacha20_poly1305.data
@@ -0,0 +1,111 @@
+Decrypt empty buffer
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C:
+dec_empty_buf:
+
+ChaCha20+Poly1305 Encrypt and decrypt 0 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:0:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 1 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:1:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 2 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:2:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 7 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:7:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 8 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:8:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 9 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:9:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 15 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:15:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 16 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:16:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 17 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:17:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 31 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:31:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:32:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 33 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:33:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 47 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:47:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 48 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:48:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 49 bytes
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:"CHACHA20-POLY1305":256:49:-1
+
+ChaCha20+Poly1305 Encrypt and decrypt 0 bytes in multiple parts 1
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:0:0:-1:0:0:0:0
+
+ChaCha20+Poly1305 Encrypt and decrypt 1 bytes in multiple parts 1
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:1:0:-1:1:0:1:0
+
+ChaCha20+Poly1305 Encrypt and decrypt 1 bytes in multiple parts 2
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:0:1:-1:0:1:0:1
+
+ChaCha20+Poly1305 Encrypt and decrypt 16 bytes in multiple parts 1
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:16:0:-1:16:0:16:0
+
+ChaCha20+Poly1305 Encrypt and decrypt 16 bytes in multiple parts 2
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:0:16:-1:0:16:0:16
+
+ChaCha20+Poly1305 Encrypt and decrypt 16 bytes in multiple parts 3
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:1:15:-1:1:15:1:15
+
+ChaCha20+Poly1305 Encrypt and decrypt 16 bytes in multiple parts 4
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:15:1:-1:15:1:15:1
+
+ChaCha20+Poly1305 Encrypt and decrypt 22 bytes in multiple parts 1
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:15:7:-1:15:7:15:7
+
+ChaCha20+Poly1305 Encrypt and decrypt 22 bytes in multiple parts 2
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:7:15:-1:7:15:7:15
+
+ChaCha20+Poly1305 Encrypt and decrypt 22 bytes in multiple parts 3
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:16:6:-1:16:6:16:6
+
+ChaCha20+Poly1305 Encrypt and decrypt 22 bytes in multiple parts 4
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:6:16:-1:6:16:6:16
+
+ChaCha20+Poly1305 Encrypt and decrypt 32 bytes in multiple parts
+depends_on:MBEDTLS_AEAD_CHACHA20_POLY1305_C
+enc_dec_buf_multipart:MBEDTLS_CIPHER_CHACHA20_POLY1305:256:16:16:-1:16:16:16:16