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