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