blob: 81bb3b7024668eef8d4cff34e490f8f9c2538eb8 [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 */
Daniel King34b822c2016-05-15 17:28:08 -030025
26#if !defined(MBEDTLS_CONFIG_FILE)
27#include "mbedtls/config.h"
28#else
29#include MBEDTLS_CONFIG_FILE
30#endif
31
32#if defined(MBEDTLS_CHACHA20_C)
33
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020034#include "mbedtls/chacha20.h"
35#include "mbedtls/platform_util.h"
Daniel King34b822c2016-05-15 17:28:08 -030036
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
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020049#if !defined(MBEDTLS_CHACHA20_ALT)
50
Daniel Kinge6e79682016-05-24 11:16:17 -030051#define BYTES_TO_U32_LE( data, offset ) \
52 ( (uint32_t) data[offset] \
53 | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \
54 | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \
55 | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \
Daniel King34b822c2016-05-15 17:28:08 -030056 )
57
Daniel Kinge6e79682016-05-24 11:16:17 -030058#define ROTL32( value, amount ) ( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030059
60#define CHACHA20_CTR_INDEX ( 12U )
61
62#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
63
Daniel King34b822c2016-05-15 17:28:08 -030064/**
65 * \brief ChaCha20 quarter round operation.
66 *
67 * The quarter round is defined as follows (from RFC 7539):
68 * 1. a += b; d ^= a; d <<<= 16;
69 * 2. c += d; b ^= c; b <<<= 12;
70 * 3. a += b; d ^= a; d <<<= 8;
71 * 4. c += d; b ^= c; b <<<= 7;
72 *
73 * \param state ChaCha20 state to modify.
74 * \param a The index of 'a' in the state.
75 * \param b The index of 'b' in the state.
76 * \param c The index of 'c' in the state.
77 * \param d The index of 'd' in the state.
78 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020079static inline void chacha20_quarter_round( uint32_t state[16],
80 size_t a,
81 size_t b,
82 size_t c,
83 size_t d )
Daniel King34b822c2016-05-15 17:28:08 -030084{
85 /* a += b; d ^= a; d <<<= 16; */
86 state[a] += state[b];
87 state[d] ^= state[a];
88 state[d] = ROTL32( state[d], 16 );
89
90 /* c += d; b ^= c; b <<<= 12 */
91 state[c] += state[d];
92 state[b] ^= state[c];
93 state[b] = ROTL32( state[b], 12 );
94
95 /* a += b; d ^= a; d <<<= 8; */
96 state[a] += state[b];
97 state[d] ^= state[a];
98 state[d] = ROTL32( state[d], 8 );
99
100 /* c += d; b ^= c; b <<<= 7; */
101 state[c] += state[d];
102 state[b] ^= state[c];
103 state[b] = ROTL32( state[b], 7 );
104}
105
106/**
107 * \brief Perform the ChaCha20 inner block operation.
108 *
109 * This function performs two rounds: the column round and the
110 * diagonal round.
111 *
112 * \param state The ChaCha20 state to update.
113 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200114static void chacha20_inner_block( uint32_t state[16] )
Daniel King34b822c2016-05-15 17:28:08 -0300115{
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200116 chacha20_quarter_round( state, 0, 4, 8, 12 );
117 chacha20_quarter_round( state, 1, 5, 9, 13 );
118 chacha20_quarter_round( state, 2, 6, 10, 14 );
119 chacha20_quarter_round( state, 3, 7, 11, 15 );
Daniel King34b822c2016-05-15 17:28:08 -0300120
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200121 chacha20_quarter_round( state, 0, 5, 10, 15 );
122 chacha20_quarter_round( state, 1, 6, 11, 12 );
123 chacha20_quarter_round( state, 2, 7, 8, 13 );
124 chacha20_quarter_round( state, 3, 4, 9, 14 );
Daniel King34b822c2016-05-15 17:28:08 -0300125}
126
127/**
128 * \brief Generates a keystream block.
129 *
130 * \param initial_state The initial ChaCha20 state (containing the key, nonce, counter).
131 * \param working_state This state is used as a temporary working area.
132 * \param keystream Generated keystream bytes are written to this buffer.
133 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200134static void chacha20_block( const uint32_t initial_state[16],
135 uint32_t working_state[16],
136 unsigned char keystream[64] )
Daniel King34b822c2016-05-15 17:28:08 -0300137{
138 size_t i;
139 size_t offset;
140
Daniel Kingb8025c52016-05-17 14:43:01 -0300141 memcpy( working_state,
142 initial_state,
143 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300144
145 for ( i = 0U; i < 10U; i++ )
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200146 chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300147
Daniel Kingb8025c52016-05-17 14:43:01 -0300148 working_state[0] += initial_state[0];
149 working_state[1] += initial_state[1];
150 working_state[2] += initial_state[2];
151 working_state[3] += initial_state[3];
152 working_state[4] += initial_state[4];
153 working_state[5] += initial_state[5];
154 working_state[6] += initial_state[6];
155 working_state[7] += initial_state[7];
156 working_state[8] += initial_state[8];
157 working_state[9] += initial_state[9];
158 working_state[10] += initial_state[10];
159 working_state[11] += initial_state[11];
160 working_state[12] += initial_state[12];
161 working_state[13] += initial_state[13];
162 working_state[14] += initial_state[14];
163 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300164
165 for ( i = 0U; i < 16; i++ )
166 {
167 offset = i * 4U;
168
Daniel Kinge6e79682016-05-24 11:16:17 -0300169 keystream[offset ] = (unsigned char) working_state[i];
170 keystream[offset + 1U] = (unsigned char) ( working_state[i] >> 8 );
171 keystream[offset + 2U] = (unsigned char) ( working_state[i] >> 16 );
172 keystream[offset + 3U] = (unsigned char) ( working_state[i] >> 24 );
Daniel King34b822c2016-05-15 17:28:08 -0300173 }
174}
175
176void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
177{
178 if ( ctx != NULL )
179 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200180 mbedtls_platform_zeroize( ctx->initial_state, sizeof( ctx->initial_state ) );
181 mbedtls_platform_zeroize( ctx->working_state, sizeof( ctx->working_state ) );
182 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Daniel King34b822c2016-05-15 17:28:08 -0300183
184 /* Initially, there's no keystream bytes available */
185 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
186 }
187}
188
189void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
190{
191 if ( ctx != NULL )
192 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200193 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300194 }
195}
196
197int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
198 const unsigned char key[32] )
199{
200 if ( ( ctx == NULL ) || ( key == NULL ) )
201 {
202 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
203 }
204
205 /* ChaCha20 constants - the string "expand 32-byte k" */
206 ctx->initial_state[0] = 0x61707865;
207 ctx->initial_state[1] = 0x3320646e;
208 ctx->initial_state[2] = 0x79622d32;
209 ctx->initial_state[3] = 0x6b206574;
210
211 /* Set key */
212 ctx->initial_state[4] = BYTES_TO_U32_LE( key, 0 );
213 ctx->initial_state[5] = BYTES_TO_U32_LE( key, 4 );
214 ctx->initial_state[6] = BYTES_TO_U32_LE( key, 8 );
215 ctx->initial_state[7] = BYTES_TO_U32_LE( key, 12 );
216 ctx->initial_state[8] = BYTES_TO_U32_LE( key, 16 );
217 ctx->initial_state[9] = BYTES_TO_U32_LE( key, 20 );
218 ctx->initial_state[10] = BYTES_TO_U32_LE( key, 24 );
219 ctx->initial_state[11] = BYTES_TO_U32_LE( key, 28 );
220
221 return( 0 );
222}
223
224int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
225 const unsigned char nonce[12],
226 uint32_t counter )
227{
228 if ( ( ctx == NULL ) || ( nonce == NULL ) )
229 {
230 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
231 }
232
233 /* Counter */
234 ctx->initial_state[12] = counter;
235
236 /* Nonce */
237 ctx->initial_state[13] = BYTES_TO_U32_LE( nonce, 0 );
238 ctx->initial_state[14] = BYTES_TO_U32_LE( nonce, 4 );
239 ctx->initial_state[15] = BYTES_TO_U32_LE( nonce, 8 );
240
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200241 mbedtls_platform_zeroize( ctx->working_state, sizeof( ctx->working_state ) );
242 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200243
244 /* Initially, there's no keystream bytes available */
245 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
246
Daniel King34b822c2016-05-15 17:28:08 -0300247 return( 0 );
248}
249
Daniel Kingbd920622016-05-15 19:56:20 -0300250int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel King34b822c2016-05-15 17:28:08 -0300251 size_t size,
252 const unsigned char *input,
253 unsigned char *output )
254{
255 size_t offset = 0U;
256 size_t i;
257
Daniel Kinga310c5e2016-05-17 15:56:26 -0300258 if ( ctx == NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300259 {
260 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
261 }
Daniel Kinga310c5e2016-05-17 15:56:26 -0300262 else if ( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
263 {
264 /* input and output pointers are allowed to be NULL only if size == 0 */
265 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
266 }
Daniel King34b822c2016-05-15 17:28:08 -0300267
268 /* Use leftover keystream bytes, if available */
269 while ( ( size > 0U ) && ( ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) )
270 {
271 output[offset] = input[offset] ^ ctx->keystream8[ctx->keystream_bytes_used];
272
273 ctx->keystream_bytes_used++;
274 offset++;
275 size--;
276 }
277
278 /* Process full blocks */
279 while ( size >= CHACHA20_BLOCK_SIZE_BYTES )
280 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200281 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200282 chacha20_block( ctx->initial_state, ctx->working_state, ctx->keystream8 );
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200283 ctx->initial_state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300284
285 for ( i = 0U; i < 64U; i += 8U )
286 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200287 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
288 output[offset + i + 1U ] = input[offset + i + 1U ] ^ ctx->keystream8[i + 1U ];
289 output[offset + i + 2U ] = input[offset + i + 2U ] ^ ctx->keystream8[i + 2U ];
290 output[offset + i + 3U ] = input[offset + i + 3U ] ^ ctx->keystream8[i + 3U ];
291 output[offset + i + 4U ] = input[offset + i + 4U ] ^ ctx->keystream8[i + 4U ];
292 output[offset + i + 5U ] = input[offset + i + 5U ] ^ ctx->keystream8[i + 5U ];
293 output[offset + i + 6U ] = input[offset + i + 6U ] ^ ctx->keystream8[i + 6U ];
294 output[offset + i + 7U ] = input[offset + i + 7U ] ^ ctx->keystream8[i + 7U ];
Daniel King34b822c2016-05-15 17:28:08 -0300295 }
296
Daniel Kingb8025c52016-05-17 14:43:01 -0300297 offset += CHACHA20_BLOCK_SIZE_BYTES;
298 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300299 }
300
301 /* Last (partial) block */
302 if ( size > 0U )
303 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200304 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200305 chacha20_block( ctx->initial_state, ctx->working_state, ctx->keystream8 );
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200306 ctx->initial_state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300307
308 for ( i = 0U; i < size; i++)
309 {
310 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
311 }
312
313 ctx->keystream_bytes_used = size;
314
Daniel King34b822c2016-05-15 17:28:08 -0300315 }
316
Daniel Kinge6e79682016-05-24 11:16:17 -0300317 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300318}
319
Daniel King34b822c2016-05-15 17:28:08 -0300320int mbedtls_chacha20_crypt( const unsigned char key[32],
321 const unsigned char nonce[12],
322 uint32_t counter,
323 size_t data_len,
324 const unsigned char* input,
325 unsigned char* output )
326{
327 mbedtls_chacha20_context ctx;
328 int result;
329
330 mbedtls_chacha20_init( &ctx );
331
332 result = mbedtls_chacha20_setkey( &ctx, key );
333 if ( result != 0 )
334 goto cleanup;
335
336 result = mbedtls_chacha20_starts( &ctx, nonce, counter );
337 if ( result != 0 )
338 goto cleanup;
339
Daniel Kingbd920622016-05-15 19:56:20 -0300340 result = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300341
342cleanup:
343 mbedtls_chacha20_free( &ctx );
Daniel Kinge6e79682016-05-24 11:16:17 -0300344 return( result );
Daniel King34b822c2016-05-15 17:28:08 -0300345}
346
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200347#endif /* !MBEDTLS_CHACHA20_ALT */
348
Daniel King34b822c2016-05-15 17:28:08 -0300349#if defined(MBEDTLS_SELF_TEST)
350
351static const unsigned char test_keys[2][32] =
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, 0x00
358 },
359 {
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
364 }
365};
366
367static const unsigned char test_nonces[2][12] =
368{
369 {
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00
372 },
373 {
374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x02
376 }
377};
378
379static const uint32_t test_counters[2] =
380{
381 0U,
382 1U
383};
384
385static const unsigned char test_input[2][375] =
386{
387 {
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
396 },
397 {
398 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
399 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
400 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
401 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
402 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
403 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
404 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
405 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
406 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
407 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
408 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
409 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
410 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
411 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
412 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
413 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
414 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
415 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
416 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
417 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
418 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
419 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
420 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
421 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
422 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
423 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
424 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
425 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
426 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
427 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
428 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
429 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
430 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
431 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
432 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
433 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
434 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
435 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
436 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
437 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
438 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
439 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
440 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
441 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
442 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
443 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
444 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
445 }
446};
447
448static const unsigned char test_output[2][375] =
449{
450 {
451 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
452 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
453 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
454 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
455 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
456 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
457 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
458 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
459 },
460 {
461 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
462 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
463 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
464 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
465 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
466 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
467 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
468 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
469 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
470 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
471 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
472 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
473 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
474 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
475 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
476 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
477 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
478 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
479 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
480 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
481 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
482 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
483 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
484 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
485 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
486 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
487 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
488 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
489 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
490 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
491 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
492 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
493 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
494 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
495 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
496 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
497 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
498 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
499 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
500 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
501 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
502 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
503 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
504 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
505 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
506 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
507 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
508 }
509};
510
511static const size_t test_lengths[2] =
512{
513 64U,
514 375U
515};
516
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200517#define ASSERT( cond, args ) \
518 do \
519 { \
520 if( ! ( cond ) ) \
521 { \
522 if( verbose != 0 ) \
523 mbedtls_printf args; \
524 \
525 return( -1 ); \
526 } \
527 } \
528 while( 0 )
529
Daniel King34b822c2016-05-15 17:28:08 -0300530int mbedtls_chacha20_self_test( int verbose )
531{
532 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200533 unsigned i;
Daniel King34b822c2016-05-15 17:28:08 -0300534 int result;
535
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200536 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300537 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200538 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200539 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300540
Daniel King34b822c2016-05-15 17:28:08 -0300541 result = mbedtls_chacha20_crypt( test_keys[i],
542 test_nonces[i],
543 test_counters[i],
544 test_lengths[i],
545 test_input[i],
546 output );
Daniel King34b822c2016-05-15 17:28:08 -0300547
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200548 ASSERT( 0 == result, ( "error code: %i\n", result ) );
Daniel King34b822c2016-05-15 17:28:08 -0300549
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200550 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
551 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300552
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200553 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300554 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300555 }
556
557 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300558 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300559
560 return( 0 );
561}
562
563#endif /* MBEDTLS_SELF_TEST */
564
565#endif /* !MBEDTLS_CHACHA20_C */