Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /**
  2.  * \file chachapoly.c
  3.  *
  4.  * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
  5.  *
  6.  *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
  7.  *  SPDX-License-Identifier: GPL-2.0
  8.  *
  9.  *  This program is free software; you can redistribute it and/or modify
  10.  *  it under the terms of the GNU General Public License as published by
  11.  *  the Free Software Foundation; either version 2 of the License, or
  12.  *  (at your option) any later version.
  13.  *
  14.  *  This program is distributed in the hope that it will be useful,
  15.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  *  GNU General Public License for more details.
  18.  *
  19.  *  You should have received a copy of the GNU General Public License along
  20.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  21.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  22.  *
  23.  *  This file is part of mbed TLS (https://tls.mbed.org)
  24.  */
  25. #if !defined(MBEDTLS_CONFIG_FILE)
  26. #include "mbedtls/config.h"
  27. #else
  28. #include MBEDTLS_CONFIG_FILE
  29. #endif
  30.  
  31. #if defined(MBEDTLS_CHACHAPOLY_C)
  32.  
  33. #include "mbedtls/chachapoly.h"
  34. #include "mbedtls/platform_util.h"
  35.  
  36. #include <string.h>
  37.  
  38. #if defined(MBEDTLS_SELF_TEST)
  39. #if defined(MBEDTLS_PLATFORM_C)
  40. #include "mbedtls/platform.h"
  41. #else
  42. #include <stdio.h>
  43. #define mbedtls_printf printf
  44. #endif /* MBEDTLS_PLATFORM_C */
  45. #endif /* MBEDTLS_SELF_TEST */
  46.  
  47. #if !defined(MBEDTLS_CHACHAPOLY_ALT)
  48.  
  49. /* Parameter validation macros */
  50. #define CHACHAPOLY_VALIDATE_RET( cond )                                       \
  51.     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
  52. #define CHACHAPOLY_VALIDATE( cond )                                           \
  53.     MBEDTLS_INTERNAL_VALIDATE( cond )
  54.  
  55. #define CHACHAPOLY_STATE_INIT       ( 0 )
  56. #define CHACHAPOLY_STATE_AAD        ( 1 )
  57. #define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
  58. #define CHACHAPOLY_STATE_FINISHED   ( 3 )
  59.  
  60. /**
  61.  * \brief           Adds nul bytes to pad the AAD for Poly1305.
  62.  *
  63.  * \param ctx       The ChaCha20-Poly1305 context.
  64.  */
  65. static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
  66. {
  67.     uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
  68.     unsigned char zeroes[15];
  69.  
  70.     if( partial_block_len == 0U )
  71.         return( 0 );
  72.  
  73.     memset( zeroes, 0, sizeof( zeroes ) );
  74.  
  75.     return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
  76.                                      zeroes,
  77.                                      16U - partial_block_len ) );
  78. }
  79.  
  80. /**
  81.  * \brief           Adds nul bytes to pad the ciphertext for Poly1305.
  82.  *
  83.  * \param ctx       The ChaCha20-Poly1305 context.
  84.  */
  85. static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
  86. {
  87.     uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
  88.     unsigned char zeroes[15];
  89.  
  90.     if( partial_block_len == 0U )
  91.         return( 0 );
  92.  
  93.     memset( zeroes, 0, sizeof( zeroes ) );
  94.     return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
  95.                                      zeroes,
  96.                                      16U - partial_block_len ) );
  97. }
  98.  
  99. void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
  100. {
  101.     CHACHAPOLY_VALIDATE( ctx != NULL );
  102.  
  103.     mbedtls_chacha20_init( &ctx->chacha20_ctx );
  104.     mbedtls_poly1305_init( &ctx->poly1305_ctx );
  105.     ctx->aad_len        = 0U;
  106.     ctx->ciphertext_len = 0U;
  107.     ctx->state          = CHACHAPOLY_STATE_INIT;
  108.     ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
  109. }
  110.  
  111. void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
  112. {
  113.     if( ctx == NULL )
  114.         return;
  115.  
  116.     mbedtls_chacha20_free( &ctx->chacha20_ctx );
  117.     mbedtls_poly1305_free( &ctx->poly1305_ctx );
  118.     ctx->aad_len        = 0U;
  119.     ctx->ciphertext_len = 0U;
  120.     ctx->state          = CHACHAPOLY_STATE_INIT;
  121.     ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
  122. }
  123.  
  124. int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
  125.                                const unsigned char key[32] )
  126. {
  127.     int ret;
  128.     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
  129.     CHACHAPOLY_VALIDATE_RET( key != NULL );
  130.  
  131.     ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
  132.  
  133.     return( ret );
  134. }
  135.  
  136. int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
  137.                                const unsigned char nonce[12],
  138.                                mbedtls_chachapoly_mode_t mode  )
  139. {
  140.     int ret;
  141.     unsigned char poly1305_key[64];
  142.     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
  143.     CHACHAPOLY_VALIDATE_RET( nonce != NULL );
  144.  
  145.     /* Set counter = 0, will be update to 1 when generating Poly1305 key */
  146.     ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
  147.     if( ret != 0 )
  148.         goto cleanup;
  149.  
  150.     /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
  151.      * counter = 0.  This is the same as encrypting a buffer of zeroes.
  152.      * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
  153.      * The other 256 bits are discarded.
  154.      */
  155.     memset( poly1305_key, 0, sizeof( poly1305_key ) );
  156.     ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
  157.                                       poly1305_key, poly1305_key );
  158.     if( ret != 0 )
  159.         goto cleanup;
  160.  
  161.     ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
  162.  
  163.     if( ret == 0 )
  164.     {
  165.         ctx->aad_len        = 0U;
  166.         ctx->ciphertext_len = 0U;
  167.         ctx->state          = CHACHAPOLY_STATE_AAD;
  168.         ctx->mode           = mode;
  169.     }
  170.  
  171. cleanup:
  172.     mbedtls_platform_zeroize( poly1305_key, 64U );
  173.     return( ret );
  174. }
  175.  
  176. int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
  177.                                    const unsigned char *aad,
  178.                                    size_t aad_len )
  179. {
  180.     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
  181.     CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
  182.  
  183.     if( ctx->state != CHACHAPOLY_STATE_AAD )
  184.         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
  185.  
  186.     ctx->aad_len += aad_len;
  187.  
  188.     return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
  189. }
  190.  
  191. int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
  192.                                size_t len,
  193.                                const unsigned char *input,
  194.                                unsigned char *output )
  195. {
  196.     int ret;
  197.     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
  198.     CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
  199.     CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
  200.  
  201.     if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
  202.         ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
  203.     {
  204.         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
  205.     }
  206.  
  207.     if( ctx->state == CHACHAPOLY_STATE_AAD )
  208.     {
  209.         ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
  210.  
  211.         ret = chachapoly_pad_aad( ctx );
  212.         if( ret != 0 )
  213.             return( ret );
  214.     }
  215.  
  216.     ctx->ciphertext_len += len;
  217.  
  218.     if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
  219.     {
  220.         ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
  221.         if( ret != 0 )
  222.             return( ret );
  223.  
  224.         ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
  225.         if( ret != 0 )
  226.             return( ret );
  227.     }
  228.     else /* DECRYPT */
  229.     {
  230.         ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
  231.         if( ret != 0 )
  232.             return( ret );
  233.  
  234.         ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
  235.         if( ret != 0 )
  236.             return( ret );
  237.     }
  238.  
  239.     return( 0 );
  240. }
  241.  
  242. int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
  243.                                unsigned char mac[16] )
  244. {
  245.     int ret;
  246.     unsigned char len_block[16];
  247.     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
  248.     CHACHAPOLY_VALIDATE_RET( mac != NULL );
  249.  
  250.     if( ctx->state == CHACHAPOLY_STATE_INIT )
  251.     {
  252.         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
  253.     }
  254.  
  255.     if( ctx->state == CHACHAPOLY_STATE_AAD )
  256.     {
  257.         ret = chachapoly_pad_aad( ctx );
  258.         if( ret != 0 )
  259.             return( ret );
  260.     }
  261.     else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
  262.     {
  263.         ret = chachapoly_pad_ciphertext( ctx );
  264.         if( ret != 0 )
  265.             return( ret );
  266.     }
  267.  
  268.     ctx->state = CHACHAPOLY_STATE_FINISHED;
  269.  
  270.     /* The lengths of the AAD and ciphertext are processed by
  271.      * Poly1305 as the final 128-bit block, encoded as little-endian integers.
  272.      */
  273.     len_block[ 0] = (unsigned char)( ctx->aad_len       );
  274.     len_block[ 1] = (unsigned char)( ctx->aad_len >>  8 );
  275.     len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
  276.     len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
  277.     len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
  278.     len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
  279.     len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
  280.     len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
  281.     len_block[ 8] = (unsigned char)( ctx->ciphertext_len       );
  282.     len_block[ 9] = (unsigned char)( ctx->ciphertext_len >>  8 );
  283.     len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
  284.     len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
  285.     len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
  286.     len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
  287.     len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
  288.     len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
  289.  
  290.     ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
  291.     if( ret != 0 )
  292.         return( ret );
  293.  
  294.     ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
  295.  
  296.     return( ret );
  297. }
  298.  
  299. static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
  300.                                      mbedtls_chachapoly_mode_t mode,
  301.                                      size_t length,
  302.                                      const unsigned char nonce[12],
  303.                                      const unsigned char *aad,
  304.                                      size_t aad_len,
  305.                                      const unsigned char *input,
  306.                                      unsigned char *output,
  307.                                      unsigned char tag[16] )
  308. {
  309.     int ret;
  310.  
  311.     ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
  312.     if( ret != 0 )
  313.         goto cleanup;
  314.  
  315.     ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
  316.     if( ret != 0 )
  317.         goto cleanup;
  318.  
  319.     ret = mbedtls_chachapoly_update( ctx, length, input, output );
  320.     if( ret != 0 )
  321.         goto cleanup;
  322.  
  323.     ret = mbedtls_chachapoly_finish( ctx, tag );
  324.  
  325. cleanup:
  326.     return( ret );
  327. }
  328.  
  329. int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
  330.                                         size_t length,
  331.                                         const unsigned char nonce[12],
  332.                                         const unsigned char *aad,
  333.                                         size_t aad_len,
  334.                                         const unsigned char *input,
  335.                                         unsigned char *output,
  336.                                         unsigned char tag[16] )
  337. {
  338.     CHACHAPOLY_VALIDATE_RET( ctx   != NULL );
  339.     CHACHAPOLY_VALIDATE_RET( nonce != NULL );
  340.     CHACHAPOLY_VALIDATE_RET( tag   != NULL );
  341.     CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad    != NULL );
  342.     CHACHAPOLY_VALIDATE_RET( length  == 0 || input  != NULL );
  343.     CHACHAPOLY_VALIDATE_RET( length  == 0 || output != NULL );
  344.  
  345.     return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
  346.                                       length, nonce, aad, aad_len,
  347.                                       input, output, tag ) );
  348. }
  349.  
  350. int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
  351.                                      size_t length,
  352.                                      const unsigned char nonce[12],
  353.                                      const unsigned char *aad,
  354.                                      size_t aad_len,
  355.                                      const unsigned char tag[16],
  356.                                      const unsigned char *input,
  357.                                      unsigned char *output )
  358. {
  359.     int ret;
  360.     unsigned char check_tag[16];
  361.     size_t i;
  362.     int diff;
  363.     CHACHAPOLY_VALIDATE_RET( ctx   != NULL );
  364.     CHACHAPOLY_VALIDATE_RET( nonce != NULL );
  365.     CHACHAPOLY_VALIDATE_RET( tag   != NULL );
  366.     CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad    != NULL );
  367.     CHACHAPOLY_VALIDATE_RET( length  == 0 || input  != NULL );
  368.     CHACHAPOLY_VALIDATE_RET( length  == 0 || output != NULL );
  369.  
  370.     if( ( ret = chachapoly_crypt_and_tag( ctx,
  371.                         MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
  372.                         aad, aad_len, input, output, check_tag ) ) != 0 )
  373.     {
  374.         return( ret );
  375.     }
  376.  
  377.     /* Check tag in "constant-time" */
  378.     for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
  379.         diff |= tag[i] ^ check_tag[i];
  380.  
  381.     if( diff != 0 )
  382.     {
  383.         mbedtls_platform_zeroize( output, length );
  384.         return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
  385.     }
  386.  
  387.     return( 0 );
  388. }
  389.  
  390. #endif /* MBEDTLS_CHACHAPOLY_ALT */
  391.  
  392. #if defined(MBEDTLS_SELF_TEST)
  393.  
  394. static const unsigned char test_key[1][32] =
  395. {
  396.     {
  397.         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
  398.         0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
  399.         0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
  400.         0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
  401.     }
  402. };
  403.  
  404. static const unsigned char test_nonce[1][12] =
  405. {
  406.     {
  407.         0x07, 0x00, 0x00, 0x00,                         /* 32-bit common part */
  408.         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47  /* 64-bit IV */
  409.     }
  410. };
  411.  
  412. static const unsigned char test_aad[1][12] =
  413. {
  414.     {
  415.         0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
  416.         0xc4, 0xc5, 0xc6, 0xc7
  417.     }
  418. };
  419.  
  420. static const size_t test_aad_len[1] =
  421. {
  422.     12U
  423. };
  424.  
  425. static const unsigned char test_input[1][114] =
  426. {
  427.     {
  428.         0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
  429.         0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
  430.         0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
  431.         0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
  432.         0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
  433.         0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
  434.         0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
  435.         0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
  436.         0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
  437.         0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
  438.         0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
  439.         0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
  440.         0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
  441.         0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
  442.         0x74, 0x2e
  443.     }
  444. };
  445.  
  446. static const unsigned char test_output[1][114] =
  447. {
  448.     {
  449.         0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
  450.         0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
  451.         0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
  452.         0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
  453.         0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
  454.         0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
  455.         0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
  456.         0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
  457.         0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
  458.         0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
  459.         0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
  460.         0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
  461.         0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
  462.         0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
  463.         0x61, 0x16
  464.     }
  465. };
  466.  
  467. static const size_t test_input_len[1] =
  468. {
  469.     114U
  470. };
  471.  
  472. static const unsigned char test_mac[1][16] =
  473. {
  474.     {
  475.         0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
  476.         0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
  477.     }
  478. };
  479.  
  480. #define ASSERT( cond, args )            \
  481.     do                                  \
  482.     {                                   \
  483.         if( ! ( cond ) )                \
  484.         {                               \
  485.             if( verbose != 0 )          \
  486.                 mbedtls_printf args;    \
  487.                                         \
  488.             return( -1 );               \
  489.         }                               \
  490.     }                                   \
  491.     while( 0 )
  492.  
  493. int mbedtls_chachapoly_self_test( int verbose )
  494. {
  495.     mbedtls_chachapoly_context ctx;
  496.     unsigned i;
  497.     int ret;
  498.     unsigned char output[200];
  499.     unsigned char mac[16];
  500.  
  501.     for( i = 0U; i < 1U; i++ )
  502.     {
  503.         if( verbose != 0 )
  504.             mbedtls_printf( "  ChaCha20-Poly1305 test %u ", i );
  505.  
  506.         mbedtls_chachapoly_init( &ctx );
  507.  
  508.         ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
  509.         ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
  510.  
  511.         ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
  512.                                                   test_input_len[i],
  513.                                                   test_nonce[i],
  514.                                                   test_aad[i],
  515.                                                   test_aad_len[i],
  516.                                                   test_input[i],
  517.                                                   output,
  518.                                                   mac );
  519.  
  520.         ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
  521.  
  522.         ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
  523.                 ( "failure (wrong output)\n" ) );
  524.  
  525.         ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
  526.                 ( "failure (wrong MAC)\n" ) );
  527.  
  528.         mbedtls_chachapoly_free( &ctx );
  529.  
  530.         if( verbose != 0 )
  531.             mbedtls_printf( "passed\n" );
  532.     }
  533.  
  534.     if( verbose != 0 )
  535.         mbedtls_printf( "\n" );
  536.  
  537.     return( 0 );
  538. }
  539.  
  540. #endif /* MBEDTLS_SELF_TEST */
  541.  
  542. #endif /* MBEDTLS_CHACHAPOLY_C */
  543.