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