blob: 8206a3bf0d321ef033c8cafbceb58c481602068d [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 */
137static void mbedtls_chacha20_block( mbedtls_chacha20_context *ctx,
138 unsigned char keystream[64] )
139{
140 size_t i;
141 size_t offset;
142
143 memcpy( ctx->working_state,
144 ctx->initial_state,
145 sizeof(ctx->initial_state) );
146
147 for ( i = 0U; i < 10U; i++ )
148 {
149 mbedtls_chacha20_inner_block( ctx->working_state );
150 }
151
152 ctx->working_state[0] += ctx->initial_state[0];
153 ctx->working_state[1] += ctx->initial_state[1];
154 ctx->working_state[2] += ctx->initial_state[2];
155 ctx->working_state[3] += ctx->initial_state[3];
156 ctx->working_state[4] += ctx->initial_state[4];
157 ctx->working_state[5] += ctx->initial_state[5];
158 ctx->working_state[6] += ctx->initial_state[6];
159 ctx->working_state[7] += ctx->initial_state[7];
160 ctx->working_state[8] += ctx->initial_state[8];
161 ctx->working_state[9] += ctx->initial_state[9];
162 ctx->working_state[10] += ctx->initial_state[10];
163 ctx->working_state[11] += ctx->initial_state[11];
164 ctx->working_state[12] += ctx->initial_state[12];
165 ctx->working_state[13] += ctx->initial_state[13];
166 ctx->working_state[14] += ctx->initial_state[14];
167 ctx->working_state[15] += ctx->initial_state[15];
168
169 for ( i = 0U; i < 16; i++ )
170 {
171 offset = i * 4U;
172
173 keystream[offset ] = (unsigned char) ctx->working_state[i];
174 keystream[offset + 1U] = (unsigned char)( ctx->working_state[i] >> 8 );
175 keystream[offset + 2U] = (unsigned char)( ctx->working_state[i] >> 16 );
176 keystream[offset + 3U] = (unsigned char)( ctx->working_state[i] >> 24 );
177 }
178}
179
180void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
181{
182 if ( ctx != NULL )
183 {
184 mbedtls_zeroize( ctx->initial_state, sizeof( ctx->initial_state ) );
185 mbedtls_zeroize( ctx->working_state, sizeof( ctx->working_state ) );
186 mbedtls_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
187
188 /* Initially, there's no keystream bytes available */
189 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
190 }
191}
192
193void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
194{
195 if ( ctx != NULL )
196 {
197 mbedtls_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
198 }
199}
200
201int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
202 const unsigned char key[32] )
203{
204 if ( ( ctx == NULL ) || ( key == NULL ) )
205 {
206 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
207 }
208
209 /* ChaCha20 constants - the string "expand 32-byte k" */
210 ctx->initial_state[0] = 0x61707865;
211 ctx->initial_state[1] = 0x3320646e;
212 ctx->initial_state[2] = 0x79622d32;
213 ctx->initial_state[3] = 0x6b206574;
214
215 /* Set key */
216 ctx->initial_state[4] = BYTES_TO_U32_LE( key, 0 );
217 ctx->initial_state[5] = BYTES_TO_U32_LE( key, 4 );
218 ctx->initial_state[6] = BYTES_TO_U32_LE( key, 8 );
219 ctx->initial_state[7] = BYTES_TO_U32_LE( key, 12 );
220 ctx->initial_state[8] = BYTES_TO_U32_LE( key, 16 );
221 ctx->initial_state[9] = BYTES_TO_U32_LE( key, 20 );
222 ctx->initial_state[10] = BYTES_TO_U32_LE( key, 24 );
223 ctx->initial_state[11] = BYTES_TO_U32_LE( key, 28 );
224
225 return( 0 );
226}
227
228int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
229 const unsigned char nonce[12],
230 uint32_t counter )
231{
232 if ( ( ctx == NULL ) || ( nonce == NULL ) )
233 {
234 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
235 }
236
237 /* Counter */
238 ctx->initial_state[12] = counter;
239
240 /* Nonce */
241 ctx->initial_state[13] = BYTES_TO_U32_LE( nonce, 0 );
242 ctx->initial_state[14] = BYTES_TO_U32_LE( nonce, 4 );
243 ctx->initial_state[15] = BYTES_TO_U32_LE( nonce, 8 );
244
245 return( 0 );
246}
247
Daniel Kingbd920622016-05-15 19:56:20 -0300248int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel King34b822c2016-05-15 17:28:08 -0300249 size_t size,
250 const unsigned char *input,
251 unsigned char *output )
252{
253 size_t offset = 0U;
254 size_t i;
255
256 if ( ( ctx == NULL ) || ( input == NULL ) || ( output == NULL ) )
257 {
258 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
259 }
260
261 /* Use leftover keystream bytes, if available */
262 while ( ( size > 0U ) && ( ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) )
263 {
264 output[offset] = input[offset] ^ ctx->keystream8[ctx->keystream_bytes_used];
265
266 ctx->keystream_bytes_used++;
267 offset++;
268 size--;
269 }
270
271 /* Process full blocks */
272 while ( size >= CHACHA20_BLOCK_SIZE_BYTES )
273 {
274 mbedtls_chacha20_block( ctx, &output[offset] );
275
276 for ( i = 0U; i < 64U; i += 8U )
277 {
278 output[offset + i ] ^= input[offset + i ];
279 output[offset + i + 1U] ^= input[offset + i + 1U];
280 output[offset + i + 2U] ^= input[offset + i + 2U];
281 output[offset + i + 3U] ^= input[offset + i + 3U];
282 output[offset + i + 4U] ^= input[offset + i + 4U];
283 output[offset + i + 5U] ^= input[offset + i + 5U];
284 output[offset + i + 6U] ^= input[offset + i + 6U];
285 output[offset + i + 7U] ^= input[offset + i + 7U];
286 }
287
288 /* Increment counter */
289 ctx->initial_state[CHACHA20_CTR_INDEX]++;
290
291 offset += 64U;
292 size -= 64U;
293 }
294
295 /* Last (partial) block */
296 if ( size > 0U )
297 {
298 mbedtls_chacha20_block( ctx, ctx->keystream8 );
299
300 for ( i = 0U; i < size; i++)
301 {
302 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
303 }
304
305 ctx->keystream_bytes_used = size;
306
307 /* Increment counter */
308 ctx->initial_state[CHACHA20_CTR_INDEX]++;
309 }
310
311 return 0;
312}
313
314#endif /* !MBEDTLS_CHACHA20_ALT */
315
316int mbedtls_chacha20_crypt( const unsigned char key[32],
317 const unsigned char nonce[12],
318 uint32_t counter,
319 size_t data_len,
320 const unsigned char* input,
321 unsigned char* output )
322{
323 mbedtls_chacha20_context ctx;
324 int result;
325
326 mbedtls_chacha20_init( &ctx );
327
328 result = mbedtls_chacha20_setkey( &ctx, key );
329 if ( result != 0 )
330 goto cleanup;
331
332 result = mbedtls_chacha20_starts( &ctx, nonce, counter );
333 if ( result != 0 )
334 goto cleanup;
335
Daniel Kingbd920622016-05-15 19:56:20 -0300336 result = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300337
338cleanup:
339 mbedtls_chacha20_free( &ctx );
340 return result;
341}
342
343#if defined(MBEDTLS_SELF_TEST)
344
345static const unsigned char test_keys[2][32] =
346{
347 {
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
352 },
353 {
354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
358 }
359};
360
361static const unsigned char test_nonces[2][12] =
362{
363 {
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00
366 },
367 {
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0x02
370 }
371};
372
373static const uint32_t test_counters[2] =
374{
375 0U,
376 1U
377};
378
379static const unsigned char test_input[2][375] =
380{
381 {
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 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 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
393 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
394 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
395 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
396 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
397 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
398 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
399 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
400 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
401 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
402 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
403 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
404 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
405 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
406 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
407 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
408 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
409 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
410 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
411 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
412 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
413 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
414 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
415 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
416 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
417 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
418 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
419 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
420 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
421 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
422 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
423 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
424 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
425 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
426 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
427 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
428 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
429 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
430 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
431 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
432 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
433 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
434 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
435 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
436 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
437 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
438 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
439 }
440};
441
442static const unsigned char test_output[2][375] =
443{
444 {
445 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
446 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
447 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
448 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
449 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
450 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
451 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
452 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
453 },
454 {
455 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
456 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
457 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
458 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
459 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
460 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
461 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
462 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
463 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
464 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
465 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
466 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
467 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
468 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
469 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
470 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
471 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
472 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
473 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
474 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
475 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
476 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
477 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
478 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
479 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
480 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
481 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
482 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
483 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
484 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
485 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
486 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
487 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
488 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
489 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
490 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
491 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
492 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
493 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
494 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
495 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
496 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
497 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
498 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
499 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
500 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
501 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
502 }
503};
504
505static const size_t test_lengths[2] =
506{
507 64U,
508 375U
509};
510
511int mbedtls_chacha20_self_test( int verbose )
512{
513 unsigned char output[381];
514 size_t i;
515 int result;
516
517 for ( i = 0U; i < 2U; i++ )
518 {
519 result = mbedtls_chacha20_crypt( test_keys[i],
520 test_nonces[i],
521 test_counters[i],
522 test_lengths[i],
523 test_input[i],
524 output );
525 if ( result != 0)
526 {
527 if ( verbose != 0 )
528 {
529 mbedtls_printf( "ChaCha20 test %zi error code: %i\n", i, result );
530 }
531
532 return( -1 );
533 }
534
535 if ( 0 != memcmp( output, test_output[i], test_lengths[i] ) )
536 {
537 if ( verbose != 0 )
538 {
539 mbedtls_printf( "ChaCha20 test %zi failed\n", i );
540 }
541
542 return( -1 );
543 }
544 }
545
546 return( 0 );
547}
548
549#endif /* MBEDTLS_SELF_TEST */
550
551#endif /* !MBEDTLS_CHACHA20_C */