xref: /optee_os/lib/libmbedtls/mbedtls/library/chacha20.c (revision 11fa71b9ddb429088f325cfda430183003ccd1db)
1 /*  SPDX-License-Identifier: Apache-2.0 */
2 /**
3  * \file chacha20.c
4  *
5  * \brief ChaCha20 cipher.
6  *
7  * \author Daniel King <damaki.gh@gmail.com>
8  *
9  *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
10  *
11  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
12  *  not use this file except in compliance with the License.
13  *  You may obtain a copy of the License at
14  *
15  *  http://www.apache.org/licenses/LICENSE-2.0
16  *
17  *  Unless required by applicable law or agreed to in writing, software
18  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
19  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  *  See the License for the specific language governing permissions and
21  *  limitations under the License.
22  *
23  *  This file is part of mbed TLS (https://tls.mbed.org)
24  */
25 
26 #if !defined(MBEDTLS_CONFIG_FILE)
27 #include "mbedtls/config.h"
28 #else
29 #include MBEDTLS_CONFIG_FILE
30 #endif
31 
32 #if defined(MBEDTLS_CHACHA20_C)
33 
34 #include "mbedtls/chacha20.h"
35 #include "mbedtls/platform_util.h"
36 #include "mbedtls/error.h"
37 
38 #include <stddef.h>
39 #include <string.h>
40 
41 #if defined(MBEDTLS_SELF_TEST)
42 #if defined(MBEDTLS_PLATFORM_C)
43 #include "mbedtls/platform.h"
44 #else
45 #include <stdio.h>
46 #define mbedtls_printf printf
47 #endif /* MBEDTLS_PLATFORM_C */
48 #endif /* MBEDTLS_SELF_TEST */
49 
50 #if !defined(MBEDTLS_CHACHA20_ALT)
51 
52 #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
53     !defined(inline) && !defined(__cplusplus)
54 #define inline __inline
55 #endif
56 
57 /* Parameter validation macros */
58 #define CHACHA20_VALIDATE_RET( cond )                                       \
59     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
60 #define CHACHA20_VALIDATE( cond )                                           \
61     MBEDTLS_INTERNAL_VALIDATE( cond )
62 
63 #define BYTES_TO_U32_LE( data, offset )                           \
64     ( (uint32_t) (data)[offset]                                   \
65       | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 )     \
66       | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 )    \
67       | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 )    \
68     )
69 
70 #define ROTL32( value, amount ) \
71     ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
72 
73 #define CHACHA20_CTR_INDEX ( 12U )
74 
75 #define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
76 
77 /**
78  * \brief           ChaCha20 quarter round operation.
79  *
80  *                  The quarter round is defined as follows (from RFC 7539):
81  *                      1.  a += b; d ^= a; d <<<= 16;
82  *                      2.  c += d; b ^= c; b <<<= 12;
83  *                      3.  a += b; d ^= a; d <<<= 8;
84  *                      4.  c += d; b ^= c; b <<<= 7;
85  *
86  * \param state     ChaCha20 state to modify.
87  * \param a         The index of 'a' in the state.
88  * \param b         The index of 'b' in the state.
89  * \param c         The index of 'c' in the state.
90  * \param d         The index of 'd' in the state.
91  */
92 static inline void chacha20_quarter_round( uint32_t state[16],
93                                            size_t a,
94                                            size_t b,
95                                            size_t c,
96                                            size_t d )
97 {
98     /* a += b; d ^= a; d <<<= 16; */
99     state[a] += state[b];
100     state[d] ^= state[a];
101     state[d] = ROTL32( state[d], 16 );
102 
103     /* c += d; b ^= c; b <<<= 12 */
104     state[c] += state[d];
105     state[b] ^= state[c];
106     state[b] = ROTL32( state[b], 12 );
107 
108     /* a += b; d ^= a; d <<<= 8; */
109     state[a] += state[b];
110     state[d] ^= state[a];
111     state[d] = ROTL32( state[d], 8 );
112 
113     /* c += d; b ^= c; b <<<= 7; */
114     state[c] += state[d];
115     state[b] ^= state[c];
116     state[b] = ROTL32( state[b], 7 );
117 }
118 
119 /**
120  * \brief           Perform the ChaCha20 inner block operation.
121  *
122  *                  This function performs two rounds: the column round and the
123  *                  diagonal round.
124  *
125  * \param state     The ChaCha20 state to update.
126  */
127 static void chacha20_inner_block( uint32_t state[16] )
128 {
129     chacha20_quarter_round( state, 0, 4, 8,  12 );
130     chacha20_quarter_round( state, 1, 5, 9,  13 );
131     chacha20_quarter_round( state, 2, 6, 10, 14 );
132     chacha20_quarter_round( state, 3, 7, 11, 15 );
133 
134     chacha20_quarter_round( state, 0, 5, 10, 15 );
135     chacha20_quarter_round( state, 1, 6, 11, 12 );
136     chacha20_quarter_round( state, 2, 7, 8,  13 );
137     chacha20_quarter_round( state, 3, 4, 9,  14 );
138 }
139 
140 /**
141  * \brief               Generates a keystream block.
142  *
143  * \param initial_state The initial ChaCha20 state (key, nonce, counter).
144  * \param keystream     Generated keystream bytes are written to this buffer.
145  */
146 static void chacha20_block( const uint32_t initial_state[16],
147                             unsigned char keystream[64] )
148 {
149     uint32_t working_state[16];
150     size_t i;
151 
152     memcpy( working_state,
153             initial_state,
154             CHACHA20_BLOCK_SIZE_BYTES );
155 
156     for( i = 0U; i < 10U; i++ )
157         chacha20_inner_block( working_state );
158 
159     working_state[ 0] += initial_state[ 0];
160     working_state[ 1] += initial_state[ 1];
161     working_state[ 2] += initial_state[ 2];
162     working_state[ 3] += initial_state[ 3];
163     working_state[ 4] += initial_state[ 4];
164     working_state[ 5] += initial_state[ 5];
165     working_state[ 6] += initial_state[ 6];
166     working_state[ 7] += initial_state[ 7];
167     working_state[ 8] += initial_state[ 8];
168     working_state[ 9] += initial_state[ 9];
169     working_state[10] += initial_state[10];
170     working_state[11] += initial_state[11];
171     working_state[12] += initial_state[12];
172     working_state[13] += initial_state[13];
173     working_state[14] += initial_state[14];
174     working_state[15] += initial_state[15];
175 
176     for( i = 0U; i < 16; i++ )
177     {
178         size_t offset = i * 4U;
179 
180         keystream[offset     ] = (unsigned char)( working_state[i]       );
181         keystream[offset + 1U] = (unsigned char)( working_state[i] >>  8 );
182         keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 );
183         keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 );
184     }
185 
186     mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
187 }
188 
189 void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
190 {
191     CHACHA20_VALIDATE( ctx != NULL );
192 
193     mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
194     mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
195 
196     /* Initially, there's no keystream bytes available */
197     ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
198 }
199 
200 void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
201 {
202     if( ctx != NULL )
203     {
204         mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
205     }
206 }
207 
208 int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
209                             const unsigned char key[32] )
210 {
211     CHACHA20_VALIDATE_RET( ctx != NULL );
212     CHACHA20_VALIDATE_RET( key != NULL );
213 
214     /* ChaCha20 constants - the string "expand 32-byte k" */
215     ctx->state[0] = 0x61707865;
216     ctx->state[1] = 0x3320646e;
217     ctx->state[2] = 0x79622d32;
218     ctx->state[3] = 0x6b206574;
219 
220     /* Set key */
221     ctx->state[4]  = BYTES_TO_U32_LE( key, 0 );
222     ctx->state[5]  = BYTES_TO_U32_LE( key, 4 );
223     ctx->state[6]  = BYTES_TO_U32_LE( key, 8 );
224     ctx->state[7]  = BYTES_TO_U32_LE( key, 12 );
225     ctx->state[8]  = BYTES_TO_U32_LE( key, 16 );
226     ctx->state[9]  = BYTES_TO_U32_LE( key, 20 );
227     ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
228     ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
229 
230     return( 0 );
231 }
232 
233 int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
234                              const unsigned char nonce[12],
235                              uint32_t counter )
236 {
237     CHACHA20_VALIDATE_RET( ctx != NULL );
238     CHACHA20_VALIDATE_RET( nonce != NULL );
239 
240     /* Counter */
241     ctx->state[12] = counter;
242 
243     /* Nonce */
244     ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
245     ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
246     ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
247 
248     mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
249 
250     /* Initially, there's no keystream bytes available */
251     ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
252 
253     return( 0 );
254 }
255 
256 int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
257                               size_t size,
258                               const unsigned char *input,
259                               unsigned char *output )
260 {
261     size_t offset = 0U;
262     size_t i;
263 
264     CHACHA20_VALIDATE_RET( ctx != NULL );
265     CHACHA20_VALIDATE_RET( size == 0 || input  != NULL );
266     CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
267 
268     /* Use leftover keystream bytes, if available */
269     while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
270     {
271         output[offset] = input[offset]
272                        ^ ctx->keystream8[ctx->keystream_bytes_used];
273 
274         ctx->keystream_bytes_used++;
275         offset++;
276         size--;
277     }
278 
279     /* Process full blocks */
280     while( size >= CHACHA20_BLOCK_SIZE_BYTES )
281     {
282         /* Generate new keystream block and increment counter */
283         chacha20_block( ctx->state, ctx->keystream8 );
284         ctx->state[CHACHA20_CTR_INDEX]++;
285 
286         for( i = 0U; i < 64U; i += 8U )
287         {
288             output[offset + i  ] = input[offset + i  ] ^ ctx->keystream8[i  ];
289             output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
290             output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
291             output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
292             output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
293             output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
294             output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
295             output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
296         }
297 
298         offset += CHACHA20_BLOCK_SIZE_BYTES;
299         size   -= CHACHA20_BLOCK_SIZE_BYTES;
300     }
301 
302     /* Last (partial) block */
303     if( size > 0U )
304     {
305         /* Generate new keystream block and increment counter */
306         chacha20_block( ctx->state, ctx->keystream8 );
307         ctx->state[CHACHA20_CTR_INDEX]++;
308 
309         for( i = 0U; i < size; i++)
310         {
311             output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
312         }
313 
314         ctx->keystream_bytes_used = size;
315 
316     }
317 
318     return( 0 );
319 }
320 
321 int mbedtls_chacha20_crypt( const unsigned char key[32],
322                             const unsigned char nonce[12],
323                             uint32_t counter,
324                             size_t data_len,
325                             const unsigned char* input,
326                             unsigned char* output )
327 {
328     mbedtls_chacha20_context ctx;
329     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
330 
331     CHACHA20_VALIDATE_RET( key != NULL );
332     CHACHA20_VALIDATE_RET( nonce != NULL );
333     CHACHA20_VALIDATE_RET( data_len == 0 || input  != NULL );
334     CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
335 
336     mbedtls_chacha20_init( &ctx );
337 
338     ret = mbedtls_chacha20_setkey( &ctx, key );
339     if( ret != 0 )
340         goto cleanup;
341 
342     ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
343     if( ret != 0 )
344         goto cleanup;
345 
346     ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
347 
348 cleanup:
349     mbedtls_chacha20_free( &ctx );
350     return( ret );
351 }
352 
353 #endif /* !MBEDTLS_CHACHA20_ALT */
354 
355 #if defined(MBEDTLS_SELF_TEST)
356 
357 static const unsigned char test_keys[2][32] =
358 {
359     {
360         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
364     },
365     {
366         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
370     }
371 };
372 
373 static const unsigned char test_nonces[2][12] =
374 {
375     {
376         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377         0x00, 0x00, 0x00, 0x00
378     },
379     {
380         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381         0x00, 0x00, 0x00, 0x02
382     }
383 };
384 
385 static const uint32_t test_counters[2] =
386 {
387     0U,
388     1U
389 };
390 
391 static const unsigned char test_input[2][375] =
392 {
393     {
394         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
400         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
402     },
403     {
404         0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
405         0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
406         0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
407         0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
408         0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
409         0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
410         0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
411         0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
412         0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
413         0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
414         0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
415         0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
416         0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
417         0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
418         0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
419         0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
420         0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
421         0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
422         0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
423         0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
424         0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
425         0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
426         0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
427         0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
428         0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
429         0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
430         0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
431         0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
432         0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
433         0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
434         0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
435         0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
436         0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
437         0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
438         0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
439         0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
440         0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
441         0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
442         0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
443         0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
444         0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
445         0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
446         0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
447         0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
448         0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
449         0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
450         0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
451     }
452 };
453 
454 static const unsigned char test_output[2][375] =
455 {
456     {
457         0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
458         0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
459         0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
460         0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
461         0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
462         0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
463         0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
464         0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
465     },
466     {
467         0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
468         0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
469         0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
470         0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
471         0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
472         0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
473         0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
474         0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
475         0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
476         0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
477         0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
478         0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
479         0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
480         0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
481         0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
482         0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
483         0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
484         0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
485         0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
486         0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
487         0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
488         0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
489         0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
490         0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
491         0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
492         0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
493         0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
494         0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
495         0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
496         0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
497         0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
498         0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
499         0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
500         0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
501         0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
502         0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
503         0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
504         0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
505         0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
506         0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
507         0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
508         0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
509         0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
510         0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
511         0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
512         0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
513         0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
514     }
515 };
516 
517 static const size_t test_lengths[2] =
518 {
519     64U,
520     375U
521 };
522 
523 #define ASSERT( cond, args )            \
524     do                                  \
525     {                                   \
526         if( ! ( cond ) )                \
527         {                               \
528             if( verbose != 0 )          \
529                 mbedtls_printf args;    \
530                                         \
531             return( -1 );               \
532         }                               \
533     }                                   \
534     while( 0 )
535 
536 int mbedtls_chacha20_self_test( int verbose )
537 {
538     unsigned char output[381];
539     unsigned i;
540     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
541 
542     for( i = 0U; i < 2U; i++ )
543     {
544         if( verbose != 0 )
545             mbedtls_printf( "  ChaCha20 test %u ", i );
546 
547         ret = mbedtls_chacha20_crypt( test_keys[i],
548                                       test_nonces[i],
549                                       test_counters[i],
550                                       test_lengths[i],
551                                       test_input[i],
552                                       output );
553 
554         ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
555 
556         ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
557                 ( "failed (output)\n" ) );
558 
559         if( verbose != 0 )
560             mbedtls_printf( "passed\n" );
561     }
562 
563     if( verbose != 0 )
564         mbedtls_printf( "\n" );
565 
566     return( 0 );
567 }
568 
569 #endif /* MBEDTLS_SELF_TEST */
570 
571 #endif /* !MBEDTLS_CHACHA20_C */
572