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