Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers chachapoly.c Source File

chachapoly.c

Go to the documentation of this file.
00001 /**
00002  * \file chachapoly.c
00003  *
00004  * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
00005  *
00006  *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
00007  *  SPDX-License-Identifier: Apache-2.0
00008  *
00009  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  *  not use this file except in compliance with the License.
00011  *  You may obtain a copy of the License at
00012  *
00013  *  http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  *  Unless required by applicable law or agreed to in writing, software
00016  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  *  See the License for the specific language governing permissions and
00019  *  limitations under the License.
00020  *
00021  *  This file is part of mbed TLS (https://tls.mbed.org)
00022  */
00023 #if !defined(MBEDTLS_CONFIG_FILE)
00024 #include "mbedtls/config.h"
00025 #else
00026 #include MBEDTLS_CONFIG_FILE
00027 #endif
00028 
00029 #if defined(MBEDTLS_CHACHAPOLY_C)
00030 
00031 #include "mbedtls/chachapoly.h"
00032 #include "mbedtls/platform_util.h"
00033 
00034 #include <string.h>
00035 
00036 #if defined(MBEDTLS_SELF_TEST)
00037 #if defined(MBEDTLS_PLATFORM_C)
00038 #include "mbedtls/platform.h"
00039 #else
00040 #include <stdio.h>
00041 #define mbedtls_printf printf
00042 #endif /* MBEDTLS_PLATFORM_C */
00043 #endif /* MBEDTLS_SELF_TEST */
00044 
00045 #if !defined(MBEDTLS_CHACHAPOLY_ALT)
00046 
00047 /* Parameter validation macros */
00048 #define CHACHAPOLY_VALIDATE_RET( cond )                                       \
00049     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
00050 #define CHACHAPOLY_VALIDATE( cond )                                           \
00051     MBEDTLS_INTERNAL_VALIDATE( cond )
00052 
00053 #define CHACHAPOLY_STATE_INIT       ( 0 )
00054 #define CHACHAPOLY_STATE_AAD        ( 1 )
00055 #define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
00056 #define CHACHAPOLY_STATE_FINISHED   ( 3 )
00057 
00058 /**
00059  * \brief           Adds nul bytes to pad the AAD for Poly1305.
00060  *
00061  * \param ctx       The ChaCha20-Poly1305 context.
00062  */
00063 static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
00064 {
00065     uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
00066     unsigned char zeroes[15];
00067 
00068     if( partial_block_len == 0U )
00069         return( 0 );
00070 
00071     memset( zeroes, 0, sizeof( zeroes ) );
00072 
00073     return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
00074                                      zeroes,
00075                                      16U - partial_block_len ) );
00076 }
00077 
00078 /**
00079  * \brief           Adds nul bytes to pad the ciphertext for Poly1305.
00080  *
00081  * \param ctx       The ChaCha20-Poly1305 context.
00082  */
00083 static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
00084 {
00085     uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
00086     unsigned char zeroes[15];
00087 
00088     if( partial_block_len == 0U )
00089         return( 0 );
00090 
00091     memset( zeroes, 0, sizeof( zeroes ) );
00092     return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
00093                                      zeroes,
00094                                      16U - partial_block_len ) );
00095 }
00096 
00097 void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
00098 {
00099     CHACHAPOLY_VALIDATE( ctx != NULL );
00100 
00101     mbedtls_chacha20_init( &ctx->chacha20_ctx );
00102     mbedtls_poly1305_init( &ctx->poly1305_ctx );
00103     ctx->aad_len        = 0U;
00104     ctx->ciphertext_len = 0U;
00105     ctx->state          = CHACHAPOLY_STATE_INIT;
00106     ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
00107 }
00108 
00109 void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
00110 {
00111     if( ctx == NULL )
00112         return;
00113 
00114     mbedtls_chacha20_free( &ctx->chacha20_ctx );
00115     mbedtls_poly1305_free( &ctx->poly1305_ctx );
00116     ctx->aad_len        = 0U;
00117     ctx->ciphertext_len = 0U;
00118     ctx->state          = CHACHAPOLY_STATE_INIT;
00119     ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
00120 }
00121 
00122 int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
00123                                const unsigned char key[32] )
00124 {
00125     int ret;
00126     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
00127     CHACHAPOLY_VALIDATE_RET( key != NULL );
00128 
00129     ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
00130 
00131     return( ret );
00132 }
00133 
00134 int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
00135                                const unsigned char nonce[12],
00136                                mbedtls_chachapoly_mode_t  mode  )
00137 {
00138     int ret;
00139     unsigned char poly1305_key[64];
00140     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
00141     CHACHAPOLY_VALIDATE_RET( nonce != NULL );
00142 
00143     /* Set counter = 0, will be update to 1 when generating Poly1305 key */
00144     ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
00145     if( ret != 0 )
00146         goto cleanup;
00147 
00148     /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
00149      * counter = 0.  This is the same as encrypting a buffer of zeroes.
00150      * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
00151      * The other 256 bits are discarded.
00152      */
00153     memset( poly1305_key, 0, sizeof( poly1305_key ) );
00154     ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
00155                                       poly1305_key, poly1305_key );
00156     if( ret != 0 )
00157         goto cleanup;
00158 
00159     ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
00160 
00161     if( ret == 0 )
00162     {
00163         ctx->aad_len        = 0U;
00164         ctx->ciphertext_len = 0U;
00165         ctx->state          = CHACHAPOLY_STATE_AAD;
00166         ctx->mode           = mode;
00167     }
00168 
00169 cleanup:
00170     mbedtls_platform_zeroize( poly1305_key, 64U );
00171     return( ret );
00172 }
00173 
00174 int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
00175                                    const unsigned char *aad,
00176                                    size_t aad_len )
00177 {
00178     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
00179     CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
00180 
00181     if( ctx->state != CHACHAPOLY_STATE_AAD )
00182         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
00183 
00184     ctx->aad_len += aad_len;
00185 
00186     return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
00187 }
00188 
00189 int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
00190                                size_t len,
00191                                const unsigned char *input,
00192                                unsigned char *output )
00193 {
00194     int ret;
00195     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
00196     CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
00197     CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
00198 
00199     if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
00200         ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
00201     {
00202         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
00203     }
00204 
00205     if( ctx->state == CHACHAPOLY_STATE_AAD )
00206     {
00207         ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
00208 
00209         ret = chachapoly_pad_aad( ctx );
00210         if( ret != 0 )
00211             return( ret );
00212     }
00213 
00214     ctx->ciphertext_len += len;
00215 
00216     if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
00217     {
00218         ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
00219         if( ret != 0 )
00220             return( ret );
00221 
00222         ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
00223         if( ret != 0 )
00224             return( ret );
00225     }
00226     else /* DECRYPT */
00227     {
00228         ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
00229         if( ret != 0 )
00230             return( ret );
00231 
00232         ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
00233         if( ret != 0 )
00234             return( ret );
00235     }
00236 
00237     return( 0 );
00238 }
00239 
00240 int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
00241                                unsigned char mac[16] )
00242 {
00243     int ret;
00244     unsigned char len_block[16];
00245     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
00246     CHACHAPOLY_VALIDATE_RET( mac != NULL );
00247 
00248     if( ctx->state == CHACHAPOLY_STATE_INIT )
00249     {
00250         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
00251     }
00252 
00253     if( ctx->state == CHACHAPOLY_STATE_AAD )
00254     {
00255         ret = chachapoly_pad_aad( ctx );
00256         if( ret != 0 )
00257             return( ret );
00258     }
00259     else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
00260     {
00261         ret = chachapoly_pad_ciphertext( ctx );
00262         if( ret != 0 )
00263             return( ret );
00264     }
00265 
00266     ctx->state = CHACHAPOLY_STATE_FINISHED;
00267 
00268     /* The lengths of the AAD and ciphertext are processed by
00269      * Poly1305 as the final 128-bit block, encoded as little-endian integers.
00270      */
00271     len_block[ 0] = (unsigned char)( ctx->aad_len       );
00272     len_block[ 1] = (unsigned char)( ctx->aad_len >>  8 );
00273     len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
00274     len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
00275     len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
00276     len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
00277     len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
00278     len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
00279     len_block[ 8] = (unsigned char)( ctx->ciphertext_len       );
00280     len_block[ 9] = (unsigned char)( ctx->ciphertext_len >>  8 );
00281     len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
00282     len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
00283     len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
00284     len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
00285     len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
00286     len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
00287 
00288     ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
00289     if( ret != 0 )
00290         return( ret );
00291 
00292     ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
00293 
00294     return( ret );
00295 }
00296 
00297 static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
00298                                      mbedtls_chachapoly_mode_t  mode,
00299                                      size_t length,
00300                                      const unsigned char nonce[12],
00301                                      const unsigned char *aad,
00302                                      size_t aad_len,
00303                                      const unsigned char *input,
00304                                      unsigned char *output,
00305                                      unsigned char tag[16] )
00306 {
00307     int ret;
00308 
00309     ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
00310     if( ret != 0 )
00311         goto cleanup;
00312 
00313     ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
00314     if( ret != 0 )
00315         goto cleanup;
00316 
00317     ret = mbedtls_chachapoly_update( ctx, length, input, output );
00318     if( ret != 0 )
00319         goto cleanup;
00320 
00321     ret = mbedtls_chachapoly_finish( ctx, tag );
00322 
00323 cleanup:
00324     return( ret );
00325 }
00326 
00327 int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
00328                                         size_t length,
00329                                         const unsigned char nonce[12],
00330                                         const unsigned char *aad,
00331                                         size_t aad_len,
00332                                         const unsigned char *input,
00333                                         unsigned char *output,
00334                                         unsigned char tag[16] )
00335 {
00336     CHACHAPOLY_VALIDATE_RET( ctx   != NULL );
00337     CHACHAPOLY_VALIDATE_RET( nonce != NULL );
00338     CHACHAPOLY_VALIDATE_RET( tag   != NULL );
00339     CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad    != NULL );
00340     CHACHAPOLY_VALIDATE_RET( length  == 0 || input  != NULL );
00341     CHACHAPOLY_VALIDATE_RET( length  == 0 || output != NULL );
00342 
00343     return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
00344                                       length, nonce, aad, aad_len,
00345                                       input, output, tag ) );
00346 }
00347 
00348 int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
00349                                      size_t length,
00350                                      const unsigned char nonce[12],
00351                                      const unsigned char *aad,
00352                                      size_t aad_len,
00353                                      const unsigned char tag[16],
00354                                      const unsigned char *input,
00355                                      unsigned char *output )
00356 {
00357     int ret;
00358     unsigned char check_tag[16];
00359     size_t i;
00360     int diff;
00361     CHACHAPOLY_VALIDATE_RET( ctx   != NULL );
00362     CHACHAPOLY_VALIDATE_RET( nonce != NULL );
00363     CHACHAPOLY_VALIDATE_RET( tag   != NULL );
00364     CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad    != NULL );
00365     CHACHAPOLY_VALIDATE_RET( length  == 0 || input  != NULL );
00366     CHACHAPOLY_VALIDATE_RET( length  == 0 || output != NULL );
00367 
00368     if( ( ret = chachapoly_crypt_and_tag( ctx,
00369                         MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
00370                         aad, aad_len, input, output, check_tag ) ) != 0 )
00371     {
00372         return( ret );
00373     }
00374 
00375     /* Check tag in "constant-time" */
00376     for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
00377         diff |= tag[i] ^ check_tag[i];
00378 
00379     if( diff != 0 )
00380     {
00381         mbedtls_platform_zeroize( output, length );
00382         return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
00383     }
00384 
00385     return( 0 );
00386 }
00387 
00388 #endif /* MBEDTLS_CHACHAPOLY_ALT */
00389 
00390 #if defined(MBEDTLS_SELF_TEST)
00391 
00392 static const unsigned char test_key[1][32] =
00393 {
00394     {
00395         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
00396         0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
00397         0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
00398         0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
00399     }
00400 };
00401 
00402 static const unsigned char test_nonce[1][12] =
00403 {
00404     {
00405         0x07, 0x00, 0x00, 0x00,                         /* 32-bit common part */
00406         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47  /* 64-bit IV */
00407     }
00408 };
00409 
00410 static const unsigned char test_aad[1][12] =
00411 {
00412     {
00413         0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
00414         0xc4, 0xc5, 0xc6, 0xc7
00415     }
00416 };
00417 
00418 static const size_t test_aad_len[1] =
00419 {
00420     12U
00421 };
00422 
00423 static const unsigned char test_input[1][114] =
00424 {
00425     {
00426         0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
00427         0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
00428         0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
00429         0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
00430         0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
00431         0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
00432         0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
00433         0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
00434         0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
00435         0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
00436         0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
00437         0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
00438         0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
00439         0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
00440         0x74, 0x2e
00441     }
00442 };
00443 
00444 static const unsigned char test_output[1][114] =
00445 {
00446     {
00447         0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
00448         0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
00449         0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
00450         0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
00451         0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
00452         0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
00453         0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
00454         0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
00455         0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
00456         0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
00457         0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
00458         0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
00459         0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
00460         0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
00461         0x61, 0x16
00462     }
00463 };
00464 
00465 static const size_t test_input_len[1] =
00466 {
00467     114U
00468 };
00469 
00470 static const unsigned char test_mac[1][16] =
00471 {
00472     {
00473         0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
00474         0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
00475     }
00476 };
00477 
00478 #define ASSERT( cond, args )            \
00479     do                                  \
00480     {                                   \
00481         if( ! ( cond ) )                \
00482         {                               \
00483             if( verbose != 0 )          \
00484                 mbedtls_printf args;    \
00485                                         \
00486             return( -1 );               \
00487         }                               \
00488     }                                   \
00489     while( 0 )
00490 
00491 int mbedtls_chachapoly_self_test( int verbose )
00492 {
00493     mbedtls_chachapoly_context ctx;
00494     unsigned i;
00495     int ret;
00496     unsigned char output[200];
00497     unsigned char mac[16];
00498 
00499     for( i = 0U; i < 1U; i++ )
00500     {
00501         if( verbose != 0 )
00502             mbedtls_printf( "  ChaCha20-Poly1305 test %u ", i );
00503 
00504         mbedtls_chachapoly_init( &ctx );
00505 
00506         ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
00507         ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
00508 
00509         ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
00510                                                   test_input_len[i],
00511                                                   test_nonce[i],
00512                                                   test_aad[i],
00513                                                   test_aad_len[i],
00514                                                   test_input[i],
00515                                                   output,
00516                                                   mac );
00517 
00518         ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
00519 
00520         ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
00521                 ( "failure (wrong output)\n" ) );
00522 
00523         ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
00524                 ( "failure (wrong MAC)\n" ) );
00525 
00526         mbedtls_chachapoly_free( &ctx );
00527 
00528         if( verbose != 0 )
00529             mbedtls_printf( "passed\n" );
00530     }
00531 
00532     if( verbose != 0 )
00533         mbedtls_printf( "\n" );
00534 
00535     return( 0 );
00536 }
00537 
00538 #endif /* MBEDTLS_SELF_TEST */
00539 
00540 #endif /* MBEDTLS_CHACHAPOLY_C */