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