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