blob: 1abb96ef93cf39be0f9bc225f1f7ddc9e237ec12 [file] [log] [blame]
Daniel Kinga98ff5e2016-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 Kingf5892752016-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 Kinga98ff5e2016-05-15 17:28:08 -030054 )
55
Daniel Kingf5892752016-05-24 11:16:17 -030056#define ROTL32( value, amount ) ( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) )
Daniel Kinga98ff5e2016-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 King31ac12e2016-05-17 14:43:01 -0300137static void mbedtls_chacha20_block( const uint32_t initial_state[16],
138 uint32_t working_state[16],
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300139 unsigned char keystream[64] )
140{
141 size_t i;
142 size_t offset;
143
Daniel King31ac12e2016-05-17 14:43:01 -0300144 memcpy( working_state,
145 initial_state,
146 CHACHA20_BLOCK_SIZE_BYTES );
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300147
148 for ( i = 0U; i < 10U; i++ )
149 {
Daniel King31ac12e2016-05-17 14:43:01 -0300150 mbedtls_chacha20_inner_block( working_state );
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300151 }
152
Daniel King31ac12e2016-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 Kinga98ff5e2016-05-15 17:28:08 -0300169
170 for ( i = 0U; i < 16; i++ )
171 {
172 offset = i * 4U;
173
Daniel Kingf5892752016-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 Kinga98ff5e2016-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 King31ac12e2016-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 Kingf5892752016-05-24 11:16:17 -0300280 mbedtls_zeroize( initial_state, sizeof( initial_state ) );
281 mbedtls_zeroize( working_state, sizeof( working_state ) );
Daniel King31ac12e2016-05-17 14:43:01 -0300282
Daniel Kingf5892752016-05-24 11:16:17 -0300283 return( 0 );
Daniel King31ac12e2016-05-17 14:43:01 -0300284}
285
Daniel King0fe7b5b2016-05-15 19:56:20 -0300286int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel Kinga98ff5e2016-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 Kingf28c2aa2016-05-17 15:56:26 -0300294 if ( ctx == NULL )
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300295 {
296 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
297 }
Daniel Kingf28c2aa2016-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 Kinga98ff5e2016-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 {
Manuel Pégourié-Gonnard02969bf2018-05-07 11:57:05 +0200317 /* Generate new keystream block and increment counter */
318 mbedtls_chacha20_block( ctx->initial_state, ctx->working_state, ctx->keystream8 );
319 ctx->initial_state[CHACHA20_CTR_INDEX]++;
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300320
321 for ( i = 0U; i < 64U; i += 8U )
322 {
Manuel Pégourié-Gonnard02969bf2018-05-07 11:57:05 +0200323 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
324 output[offset + i + 1U ] = input[offset + i + 1U ] ^ ctx->keystream8[i + 1U ];
325 output[offset + i + 2U ] = input[offset + i + 2U ] ^ ctx->keystream8[i + 2U ];
326 output[offset + i + 3U ] = input[offset + i + 3U ] ^ ctx->keystream8[i + 3U ];
327 output[offset + i + 4U ] = input[offset + i + 4U ] ^ ctx->keystream8[i + 4U ];
328 output[offset + i + 5U ] = input[offset + i + 5U ] ^ ctx->keystream8[i + 5U ];
329 output[offset + i + 6U ] = input[offset + i + 6U ] ^ ctx->keystream8[i + 6U ];
330 output[offset + i + 7U ] = input[offset + i + 7U ] ^ ctx->keystream8[i + 7U ];
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300331 }
332
Daniel King31ac12e2016-05-17 14:43:01 -0300333 offset += CHACHA20_BLOCK_SIZE_BYTES;
334 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300335 }
336
337 /* Last (partial) block */
338 if ( size > 0U )
339 {
Manuel Pégourié-Gonnard02969bf2018-05-07 11:57:05 +0200340 /* Generate new keystream block and increment counter */
Daniel King31ac12e2016-05-17 14:43:01 -0300341 mbedtls_chacha20_block( ctx->initial_state, ctx->working_state, ctx->keystream8 );
Manuel Pégourié-Gonnard02969bf2018-05-07 11:57:05 +0200342 ctx->initial_state[CHACHA20_CTR_INDEX]++;
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300343
344 for ( i = 0U; i < size; i++)
345 {
346 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
347 }
348
349 ctx->keystream_bytes_used = size;
350
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300351 }
352
Daniel Kingf5892752016-05-24 11:16:17 -0300353 return( 0 );
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300354}
355
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300356int mbedtls_chacha20_crypt( const unsigned char key[32],
357 const unsigned char nonce[12],
358 uint32_t counter,
359 size_t data_len,
360 const unsigned char* input,
361 unsigned char* output )
362{
363 mbedtls_chacha20_context ctx;
364 int result;
365
366 mbedtls_chacha20_init( &ctx );
367
368 result = mbedtls_chacha20_setkey( &ctx, key );
369 if ( result != 0 )
370 goto cleanup;
371
372 result = mbedtls_chacha20_starts( &ctx, nonce, counter );
373 if ( result != 0 )
374 goto cleanup;
375
Daniel King0fe7b5b2016-05-15 19:56:20 -0300376 result = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300377
378cleanup:
379 mbedtls_chacha20_free( &ctx );
Daniel Kingf5892752016-05-24 11:16:17 -0300380 return( result );
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300381}
382
Manuel Pégourié-Gonnarddeda80e2018-05-07 09:58:35 +0200383#endif /* !MBEDTLS_CHACHA20_ALT */
384
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300385#if defined(MBEDTLS_SELF_TEST)
386
387static const unsigned char test_keys[2][32] =
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, 0x00
394 },
395 {
396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x01
400 }
401};
402
403static const unsigned char test_nonces[2][12] =
404{
405 {
406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
407 0x00, 0x00, 0x00, 0x00
408 },
409 {
410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x02
412 }
413};
414
415static const uint32_t test_counters[2] =
416{
417 0U,
418 1U
419};
420
421static const unsigned char test_input[2][375] =
422{
423 {
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 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 },
433 {
434 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
435 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
436 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
437 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
438 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
439 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
440 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
441 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
442 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
443 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
444 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
445 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
446 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
447 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
448 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
449 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
450 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
451 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
452 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
453 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
454 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
455 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
456 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
457 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
458 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
459 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
460 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
461 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
462 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
463 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
464 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
465 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
466 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
467 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
468 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
469 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
470 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
471 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
472 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
473 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
474 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
475 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
476 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
477 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
478 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
479 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
480 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
481 }
482};
483
484static const unsigned char test_output[2][375] =
485{
486 {
487 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
488 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
489 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
490 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
491 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
492 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
493 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
494 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
495 },
496 {
497 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
498 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
499 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
500 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
501 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
502 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
503 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
504 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
505 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
506 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
507 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
508 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
509 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
510 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
511 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
512 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
513 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
514 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
515 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
516 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
517 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
518 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
519 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
520 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
521 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
522 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
523 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
524 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
525 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
526 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
527 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
528 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
529 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
530 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
531 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
532 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
533 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
534 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
535 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
536 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
537 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
538 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
539 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
540 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
541 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
542 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
543 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
544 }
545};
546
547static const size_t test_lengths[2] =
548{
549 64U,
550 375U
551};
552
553int mbedtls_chacha20_self_test( int verbose )
554{
555 unsigned char output[381];
Manuel Pégourié-Gonnard726cf722018-05-07 10:14:18 +0200556 unsigned i;
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300557 int result;
558
559 for ( i = 0U; i < 2U; i++ )
560 {
Daniel Kingd00afaf2016-05-18 10:07:53 -0300561 if ( verbose != 0 )
562 {
Manuel Pégourié-Gonnard726cf722018-05-07 10:14:18 +0200563 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingd00afaf2016-05-18 10:07:53 -0300564 }
565
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300566 result = mbedtls_chacha20_crypt( test_keys[i],
567 test_nonces[i],
568 test_counters[i],
569 test_lengths[i],
570 test_input[i],
571 output );
572 if ( result != 0)
573 {
574 if ( verbose != 0 )
575 {
Daniel Kingd00afaf2016-05-18 10:07:53 -0300576 mbedtls_printf( "error code: %i\n", result );
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300577 }
578
579 return( -1 );
580 }
581
582 if ( 0 != memcmp( output, test_output[i], test_lengths[i] ) )
583 {
584 if ( verbose != 0 )
585 {
Daniel Kingd00afaf2016-05-18 10:07:53 -0300586 mbedtls_printf( "failed\n" );
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300587 }
588
589 return( -1 );
590 }
Daniel Kingd00afaf2016-05-18 10:07:53 -0300591
592 if ( verbose != 0 )
593 {
594 mbedtls_printf( "passed\n" );
595 }
596 }
597
598 if( verbose != 0 )
599 {
600 mbedtls_printf( "\n" );
Daniel Kinga98ff5e2016-05-15 17:28:08 -0300601 }
602
603 return( 0 );
604}
605
606#endif /* MBEDTLS_SELF_TEST */
607
608#endif /* !MBEDTLS_CHACHA20_C */