blob: 4c2d8ef9ac891574060ab20c1da6f9395a031f05 [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
Daniel Kinge6e79682016-05-24 11:16:17 -030049#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 ) \
Daniel King34b822c2016-05-15 17:28:08 -030054 )
55
Daniel Kinge6e79682016-05-24 11:16:17 -030056#define ROTL32( value, amount ) ( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030057
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 Kinge6e79682016-05-24 11:16:17 -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
Daniel Kinge6e79682016-05-24 11:16:17 -0300280 mbedtls_zeroize( initial_state, sizeof( initial_state ) );
281 mbedtls_zeroize( working_state, sizeof( working_state ) );
Daniel Kingb8025c52016-05-17 14:43:01 -0300282
Daniel Kinge6e79682016-05-24 11:16:17 -0300283 return( 0 );
Daniel Kingb8025c52016-05-17 14:43:01 -0300284}
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
Daniel Kinga310c5e2016-05-17 15:56:26 -0300294 if ( ctx == NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300295 {
296 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
297 }
Daniel Kinga310c5e2016-05-17 15:56:26 -0300298 else if ( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
299 {
300 /* input and output pointers are allowed to be NULL only if size == 0 */
301 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
302 }
Daniel King34b822c2016-05-15 17:28:08 -0300303
304 /* Use leftover keystream bytes, if available */
305 while ( ( size > 0U ) && ( ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) )
306 {
307 output[offset] = input[offset] ^ ctx->keystream8[ctx->keystream_bytes_used];
308
309 ctx->keystream_bytes_used++;
310 offset++;
311 size--;
312 }
313
314 /* Process full blocks */
315 while ( size >= CHACHA20_BLOCK_SIZE_BYTES )
316 {
Daniel Kingb8025c52016-05-17 14:43:01 -0300317 mbedtls_chacha20_block( ctx->initial_state, ctx->working_state, &output[offset] );
Daniel King34b822c2016-05-15 17:28:08 -0300318
319 for ( i = 0U; i < 64U; i += 8U )
320 {
321 output[offset + i ] ^= input[offset + i ];
322 output[offset + i + 1U] ^= input[offset + i + 1U];
323 output[offset + i + 2U] ^= input[offset + i + 2U];
324 output[offset + i + 3U] ^= input[offset + i + 3U];
325 output[offset + i + 4U] ^= input[offset + i + 4U];
326 output[offset + i + 5U] ^= input[offset + i + 5U];
327 output[offset + i + 6U] ^= input[offset + i + 6U];
328 output[offset + i + 7U] ^= input[offset + i + 7U];
329 }
330
331 /* Increment counter */
332 ctx->initial_state[CHACHA20_CTR_INDEX]++;
333
Daniel Kingb8025c52016-05-17 14:43:01 -0300334 offset += CHACHA20_BLOCK_SIZE_BYTES;
335 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300336 }
337
338 /* Last (partial) block */
339 if ( size > 0U )
340 {
Daniel Kingb8025c52016-05-17 14:43:01 -0300341 mbedtls_chacha20_block( ctx->initial_state, ctx->working_state, ctx->keystream8 );
Daniel King34b822c2016-05-15 17:28:08 -0300342
343 for ( i = 0U; i < size; i++)
344 {
345 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
346 }
347
348 ctx->keystream_bytes_used = size;
349
350 /* Increment counter */
351 ctx->initial_state[CHACHA20_CTR_INDEX]++;
352 }
353
Daniel Kinge6e79682016-05-24 11:16:17 -0300354 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300355}
356
357#endif /* !MBEDTLS_CHACHA20_ALT */
358
359int mbedtls_chacha20_crypt( const unsigned char key[32],
360 const unsigned char nonce[12],
361 uint32_t counter,
362 size_t data_len,
363 const unsigned char* input,
364 unsigned char* output )
365{
366 mbedtls_chacha20_context ctx;
367 int result;
368
369 mbedtls_chacha20_init( &ctx );
370
371 result = mbedtls_chacha20_setkey( &ctx, key );
372 if ( result != 0 )
373 goto cleanup;
374
375 result = mbedtls_chacha20_starts( &ctx, nonce, counter );
376 if ( result != 0 )
377 goto cleanup;
378
Daniel Kingbd920622016-05-15 19:56:20 -0300379 result = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300380
381cleanup:
382 mbedtls_chacha20_free( &ctx );
Daniel Kinge6e79682016-05-24 11:16:17 -0300383 return( result );
Daniel King34b822c2016-05-15 17:28:08 -0300384}
385
386#if defined(MBEDTLS_SELF_TEST)
387
388static const unsigned char test_keys[2][32] =
389{
390 {
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, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
395 },
396 {
397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
401 }
402};
403
404static const unsigned char test_nonces[2][12] =
405{
406 {
407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
408 0x00, 0x00, 0x00, 0x00
409 },
410 {
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x02
413 }
414};
415
416static const uint32_t test_counters[2] =
417{
418 0U,
419 1U
420};
421
422static const unsigned char test_input[2][375] =
423{
424 {
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
433 },
434 {
435 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
436 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
437 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
438 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
439 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
440 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
441 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
442 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
443 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
444 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
445 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
446 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
447 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
448 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
449 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
450 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
451 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
452 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
453 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
454 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
455 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
456 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
457 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
458 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
459 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
460 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
461 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
462 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
463 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
464 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
465 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
466 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
467 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
468 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
469 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
470 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
471 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
472 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
473 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
474 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
475 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
476 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
477 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
478 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
479 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
480 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
481 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
482 }
483};
484
485static const unsigned char test_output[2][375] =
486{
487 {
488 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
489 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
490 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
491 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
492 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
493 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
494 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
495 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
496 },
497 {
498 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
499 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
500 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
501 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
502 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
503 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
504 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
505 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
506 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
507 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
508 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
509 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
510 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
511 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
512 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
513 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
514 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
515 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
516 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
517 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
518 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
519 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
520 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
521 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
522 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
523 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
524 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
525 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
526 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
527 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
528 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
529 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
530 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
531 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
532 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
533 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
534 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
535 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
536 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
537 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
538 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
539 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
540 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
541 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
542 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
543 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
544 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
545 }
546};
547
548static const size_t test_lengths[2] =
549{
550 64U,
551 375U
552};
553
554int mbedtls_chacha20_self_test( int verbose )
555{
556 unsigned char output[381];
557 size_t i;
558 int result;
559
560 for ( i = 0U; i < 2U; i++ )
561 {
Daniel Kingdedf4a32016-05-18 10:07:53 -0300562 if ( verbose != 0 )
563 {
Daniel Kingb6897f62016-05-19 09:57:59 -0300564 mbedtls_printf( " ChaCha20 test %zu ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300565 }
566
Daniel King34b822c2016-05-15 17:28:08 -0300567 result = mbedtls_chacha20_crypt( test_keys[i],
568 test_nonces[i],
569 test_counters[i],
570 test_lengths[i],
571 test_input[i],
572 output );
573 if ( result != 0)
574 {
575 if ( verbose != 0 )
576 {
Daniel Kingdedf4a32016-05-18 10:07:53 -0300577 mbedtls_printf( "error code: %i\n", result );
Daniel King34b822c2016-05-15 17:28:08 -0300578 }
579
580 return( -1 );
581 }
582
583 if ( 0 != memcmp( output, test_output[i], test_lengths[i] ) )
584 {
585 if ( verbose != 0 )
586 {
Daniel Kingdedf4a32016-05-18 10:07:53 -0300587 mbedtls_printf( "failed\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300588 }
589
590 return( -1 );
591 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300592
593 if ( verbose != 0 )
594 {
595 mbedtls_printf( "passed\n" );
596 }
597 }
598
599 if( verbose != 0 )
600 {
601 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300602 }
603
604 return( 0 );
605}
606
607#endif /* MBEDTLS_SELF_TEST */
608
609#endif /* !MBEDTLS_CHACHA20_C */