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