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