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