blob: 78467d3fc6efe5dbb4f73967c8a1b21e6fbd7df2 [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 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02008 * Copyright The Mbed TLS Contributors
Daniel King34b822c2016-05-15 17:28:08 -03009 * 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.
Daniel King34b822c2016-05-15 17:28:08 -030022 */
Daniel King34b822c2016-05-15 17:28:08 -030023
Gilles Peskinedb09ef62020-06-03 01:43:33 +020024#include "common.h"
Daniel King34b822c2016-05-15 17:28:08 -030025
26#if defined(MBEDTLS_CHACHA20_C)
27
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020028#include "mbedtls/chacha20.h"
29#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000030#include "mbedtls/error.h"
Daniel King34b822c2016-05-15 17:28:08 -030031
32#include <stddef.h>
33#include <string.h>
34
35#if defined(MBEDTLS_SELF_TEST)
36#if defined(MBEDTLS_PLATFORM_C)
37#include "mbedtls/platform.h"
38#else
39#include <stdio.h>
40#define mbedtls_printf printf
41#endif /* MBEDTLS_PLATFORM_C */
42#endif /* MBEDTLS_SELF_TEST */
43
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020044#if !defined(MBEDTLS_CHACHA20_ALT)
45
Manuel Pégourié-Gonnard21a65e02018-06-07 11:54:17 +020046#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
47 !defined(inline) && !defined(__cplusplus)
48#define inline __inline
49#endif
50
Hanno Becker305e4e42018-12-11 15:03:16 +000051/* Parameter validation macros */
52#define CHACHA20_VALIDATE_RET( cond ) \
53 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
54#define CHACHA20_VALIDATE( cond ) \
55 MBEDTLS_INTERNAL_VALIDATE( cond )
56
Daniel Kinge6e79682016-05-24 11:16:17 -030057#define BYTES_TO_U32_LE( data, offset ) \
Hanno Becker1eeca412018-10-15 12:01:35 +010058 ( (uint32_t) (data)[offset] \
59 | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 ) \
60 | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 ) \
61 | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 ) \
Daniel King34b822c2016-05-15 17:28:08 -030062 )
63
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020064#define ROTL32( value, amount ) \
Hanno Becker1eeca412018-10-15 12:01:35 +010065 ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030066
67#define CHACHA20_CTR_INDEX ( 12U )
68
69#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
70
Daniel King34b822c2016-05-15 17:28:08 -030071/**
72 * \brief ChaCha20 quarter round operation.
73 *
74 * The quarter round is defined as follows (from RFC 7539):
75 * 1. a += b; d ^= a; d <<<= 16;
76 * 2. c += d; b ^= c; b <<<= 12;
77 * 3. a += b; d ^= a; d <<<= 8;
78 * 4. c += d; b ^= c; b <<<= 7;
79 *
80 * \param state ChaCha20 state to modify.
81 * \param a The index of 'a' in the state.
82 * \param b The index of 'b' in the state.
83 * \param c The index of 'c' in the state.
84 * \param d The index of 'd' in the state.
85 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020086static inline void chacha20_quarter_round( uint32_t state[16],
87 size_t a,
88 size_t b,
89 size_t c,
90 size_t d )
Daniel King34b822c2016-05-15 17:28:08 -030091{
92 /* a += b; d ^= a; d <<<= 16; */
93 state[a] += state[b];
94 state[d] ^= state[a];
95 state[d] = ROTL32( state[d], 16 );
96
97 /* c += d; b ^= c; b <<<= 12 */
98 state[c] += state[d];
99 state[b] ^= state[c];
100 state[b] = ROTL32( state[b], 12 );
101
102 /* a += b; d ^= a; d <<<= 8; */
103 state[a] += state[b];
104 state[d] ^= state[a];
105 state[d] = ROTL32( state[d], 8 );
106
107 /* c += d; b ^= c; b <<<= 7; */
108 state[c] += state[d];
109 state[b] ^= state[c];
110 state[b] = ROTL32( state[b], 7 );
111}
112
113/**
114 * \brief Perform the ChaCha20 inner block operation.
115 *
116 * This function performs two rounds: the column round and the
117 * diagonal round.
118 *
119 * \param state The ChaCha20 state to update.
120 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200121static void chacha20_inner_block( uint32_t state[16] )
Daniel King34b822c2016-05-15 17:28:08 -0300122{
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200123 chacha20_quarter_round( state, 0, 4, 8, 12 );
124 chacha20_quarter_round( state, 1, 5, 9, 13 );
125 chacha20_quarter_round( state, 2, 6, 10, 14 );
126 chacha20_quarter_round( state, 3, 7, 11, 15 );
Daniel King34b822c2016-05-15 17:28:08 -0300127
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200128 chacha20_quarter_round( state, 0, 5, 10, 15 );
129 chacha20_quarter_round( state, 1, 6, 11, 12 );
130 chacha20_quarter_round( state, 2, 7, 8, 13 );
131 chacha20_quarter_round( state, 3, 4, 9, 14 );
Daniel King34b822c2016-05-15 17:28:08 -0300132}
133
134/**
135 * \brief Generates a keystream block.
136 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200137 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300138 * \param keystream Generated keystream bytes are written to this buffer.
139 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200140static void chacha20_block( const uint32_t initial_state[16],
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200141 unsigned char keystream[64] )
Daniel King34b822c2016-05-15 17:28:08 -0300142{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200143 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300144 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300145
Daniel Kingb8025c52016-05-17 14:43:01 -0300146 memcpy( working_state,
147 initial_state,
148 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300149
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200150 for( i = 0U; i < 10U; i++ )
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200151 chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300152
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200153 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];
Daniel Kingb8025c52016-05-17 14:43:01 -0300163 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
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200170 for( i = 0U; i < 16; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300171 {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200172 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300173
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200174 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 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200179
180 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
Daniel King34b822c2016-05-15 17:28:08 -0300181}
182
183void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
184{
Hanno Becker305e4e42018-12-11 15:03:16 +0000185 CHACHA20_VALIDATE( ctx != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300186
Hanno Becker305e4e42018-12-11 15:03:16 +0000187 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
188 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
189
190 /* Initially, there's no keystream bytes available */
191 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300192}
193
194void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
195{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200196 if( ctx != NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300197 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200198 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300199 }
200}
201
202int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
203 const unsigned char key[32] )
204{
Hanno Becker305e4e42018-12-11 15:03:16 +0000205 CHACHA20_VALIDATE_RET( ctx != NULL );
206 CHACHA20_VALIDATE_RET( key != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300207
208 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200209 ctx->state[0] = 0x61707865;
210 ctx->state[1] = 0x3320646e;
211 ctx->state[2] = 0x79622d32;
212 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300213
214 /* Set key */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200215 ctx->state[4] = BYTES_TO_U32_LE( key, 0 );
216 ctx->state[5] = BYTES_TO_U32_LE( key, 4 );
217 ctx->state[6] = BYTES_TO_U32_LE( key, 8 );
218 ctx->state[7] = BYTES_TO_U32_LE( key, 12 );
219 ctx->state[8] = BYTES_TO_U32_LE( key, 16 );
220 ctx->state[9] = BYTES_TO_U32_LE( key, 20 );
221 ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
222 ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
Daniel King34b822c2016-05-15 17:28:08 -0300223
224 return( 0 );
225}
226
227int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
228 const unsigned char nonce[12],
229 uint32_t counter )
230{
Hanno Becker305e4e42018-12-11 15:03:16 +0000231 CHACHA20_VALIDATE_RET( ctx != NULL );
232 CHACHA20_VALIDATE_RET( nonce != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300233
234 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200235 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300236
237 /* Nonce */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200238 ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
239 ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
240 ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
Daniel King34b822c2016-05-15 17:28:08 -0300241
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200242 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
Hanno Becker305e4e42018-12-11 15:03:16 +0000258 CHACHA20_VALIDATE_RET( ctx != NULL );
259 CHACHA20_VALIDATE_RET( size == 0 || input != NULL );
260 CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300261
262 /* Use leftover keystream bytes, if available */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200263 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300264 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200265 output[offset] = input[offset]
266 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300267
268 ctx->keystream_bytes_used++;
269 offset++;
270 size--;
271 }
272
273 /* Process full blocks */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200274 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300275 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200276 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200277 chacha20_block( ctx->state, ctx->keystream8 );
278 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300279
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200280 for( i = 0U; i < 64U; i += 8U )
Daniel King34b822c2016-05-15 17:28:08 -0300281 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200282 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
283 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
284 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
285 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
286 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
287 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
288 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
289 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
Daniel King34b822c2016-05-15 17:28:08 -0300290 }
291
Daniel Kingb8025c52016-05-17 14:43:01 -0300292 offset += CHACHA20_BLOCK_SIZE_BYTES;
293 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300294 }
295
296 /* Last (partial) block */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200297 if( size > 0U )
Daniel King34b822c2016-05-15 17:28:08 -0300298 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200299 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200300 chacha20_block( ctx->state, ctx->keystream8 );
301 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300302
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200303 for( i = 0U; i < size; i++)
Daniel King34b822c2016-05-15 17:28:08 -0300304 {
305 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
306 }
307
308 ctx->keystream_bytes_used = size;
309
Daniel King34b822c2016-05-15 17:28:08 -0300310 }
311
Daniel Kinge6e79682016-05-24 11:16:17 -0300312 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300313}
314
Daniel King34b822c2016-05-15 17:28:08 -0300315int mbedtls_chacha20_crypt( const unsigned char key[32],
316 const unsigned char nonce[12],
317 uint32_t counter,
318 size_t data_len,
319 const unsigned char* input,
320 unsigned char* output )
321{
322 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000323 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300324
Hanno Becker305e4e42018-12-11 15:03:16 +0000325 CHACHA20_VALIDATE_RET( key != NULL );
326 CHACHA20_VALIDATE_RET( nonce != NULL );
327 CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL );
328 CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
329
Daniel King34b822c2016-05-15 17:28:08 -0300330 mbedtls_chacha20_init( &ctx );
331
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200332 ret = mbedtls_chacha20_setkey( &ctx, key );
333 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300334 goto cleanup;
335
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200336 ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
337 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300338 goto cleanup;
339
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200340 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300341
342cleanup:
343 mbedtls_chacha20_free( &ctx );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200344 return( ret );
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
Ouss4e0b26872020-08-11 16:07:09 +0100517/* Make sure no other definition is already present. */
518#undef ASSERT
519
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200520#define ASSERT( cond, args ) \
521 do \
522 { \
523 if( ! ( cond ) ) \
524 { \
525 if( verbose != 0 ) \
526 mbedtls_printf args; \
527 \
528 return( -1 ); \
529 } \
530 } \
531 while( 0 )
532
Daniel King34b822c2016-05-15 17:28:08 -0300533int mbedtls_chacha20_self_test( int verbose )
534{
535 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200536 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000537 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300538
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200539 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300540 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200541 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200542 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300543
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200544 ret = mbedtls_chacha20_crypt( test_keys[i],
545 test_nonces[i],
546 test_counters[i],
547 test_lengths[i],
548 test_input[i],
549 output );
Daniel King34b822c2016-05-15 17:28:08 -0300550
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200551 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
Daniel King34b822c2016-05-15 17:28:08 -0300552
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200553 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
554 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300555
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200556 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300557 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300558 }
559
560 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300561 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300562
563 return( 0 );
564}
565
566#endif /* MBEDTLS_SELF_TEST */
567
568#endif /* !MBEDTLS_CHACHA20_C */