blob: d17c58c269a553f007afc1506479150f0ed1c4ba [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
Daniel King34b822c2016-05-15 17:28:08 -030035#include "mbedtls/platform.h"
Daniel King34b822c2016-05-15 17:28:08 -030036
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020037#if !defined(MBEDTLS_CHACHA20_ALT)
38
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020039#define ROTL32( value, amount ) \
Hanno Becker1eeca412018-10-15 12:01:35 +010040 ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030041
42#define CHACHA20_CTR_INDEX ( 12U )
43
44#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
45
Daniel King34b822c2016-05-15 17:28:08 -030046/**
47 * \brief ChaCha20 quarter round operation.
48 *
49 * The quarter round is defined as follows (from RFC 7539):
50 * 1. a += b; d ^= a; d <<<= 16;
51 * 2. c += d; b ^= c; b <<<= 12;
52 * 3. a += b; d ^= a; d <<<= 8;
53 * 4. c += d; b ^= c; b <<<= 7;
54 *
55 * \param state ChaCha20 state to modify.
56 * \param a The index of 'a' in the state.
57 * \param b The index of 'b' in the state.
58 * \param c The index of 'c' in the state.
59 * \param d The index of 'd' in the state.
60 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020061static inline void chacha20_quarter_round( uint32_t state[16],
62 size_t a,
63 size_t b,
64 size_t c,
65 size_t d )
Daniel King34b822c2016-05-15 17:28:08 -030066{
67 /* a += b; d ^= a; d <<<= 16; */
68 state[a] += state[b];
69 state[d] ^= state[a];
70 state[d] = ROTL32( state[d], 16 );
71
72 /* c += d; b ^= c; b <<<= 12 */
73 state[c] += state[d];
74 state[b] ^= state[c];
75 state[b] = ROTL32( state[b], 12 );
76
77 /* a += b; d ^= a; d <<<= 8; */
78 state[a] += state[b];
79 state[d] ^= state[a];
80 state[d] = ROTL32( state[d], 8 );
81
82 /* c += d; b ^= c; b <<<= 7; */
83 state[c] += state[d];
84 state[b] ^= state[c];
85 state[b] = ROTL32( state[b], 7 );
86}
87
88/**
89 * \brief Perform the ChaCha20 inner block operation.
90 *
91 * This function performs two rounds: the column round and the
92 * diagonal round.
93 *
94 * \param state The ChaCha20 state to update.
95 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020096static void chacha20_inner_block( uint32_t state[16] )
Daniel King34b822c2016-05-15 17:28:08 -030097{
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020098 chacha20_quarter_round( state, 0, 4, 8, 12 );
99 chacha20_quarter_round( state, 1, 5, 9, 13 );
100 chacha20_quarter_round( state, 2, 6, 10, 14 );
101 chacha20_quarter_round( state, 3, 7, 11, 15 );
Daniel King34b822c2016-05-15 17:28:08 -0300102
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200103 chacha20_quarter_round( state, 0, 5, 10, 15 );
104 chacha20_quarter_round( state, 1, 6, 11, 12 );
105 chacha20_quarter_round( state, 2, 7, 8, 13 );
106 chacha20_quarter_round( state, 3, 4, 9, 14 );
Daniel King34b822c2016-05-15 17:28:08 -0300107}
108
109/**
110 * \brief Generates a keystream block.
111 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200112 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300113 * \param keystream Generated keystream bytes are written to this buffer.
114 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200115static void chacha20_block( const uint32_t initial_state[16],
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200116 unsigned char keystream[64] )
Daniel King34b822c2016-05-15 17:28:08 -0300117{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200118 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300119 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300120
Daniel Kingb8025c52016-05-17 14:43:01 -0300121 memcpy( working_state,
122 initial_state,
123 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300124
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200125 for( i = 0U; i < 10U; i++ )
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200126 chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300127
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200128 working_state[ 0] += initial_state[ 0];
129 working_state[ 1] += initial_state[ 1];
130 working_state[ 2] += initial_state[ 2];
131 working_state[ 3] += initial_state[ 3];
132 working_state[ 4] += initial_state[ 4];
133 working_state[ 5] += initial_state[ 5];
134 working_state[ 6] += initial_state[ 6];
135 working_state[ 7] += initial_state[ 7];
136 working_state[ 8] += initial_state[ 8];
137 working_state[ 9] += initial_state[ 9];
Daniel Kingb8025c52016-05-17 14:43:01 -0300138 working_state[10] += initial_state[10];
139 working_state[11] += initial_state[11];
140 working_state[12] += initial_state[12];
141 working_state[13] += initial_state[13];
142 working_state[14] += initial_state[14];
143 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300144
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200145 for( i = 0U; i < 16; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300146 {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200147 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300148
Joe Subbianib6511b02021-07-16 15:02:55 +0100149 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Daniel King34b822c2016-05-15 17:28:08 -0300150 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200151
152 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
Daniel King34b822c2016-05-15 17:28:08 -0300153}
154
155void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
156{
Hanno Becker305e4e42018-12-11 15:03:16 +0000157 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
158 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
159
160 /* Initially, there's no keystream bytes available */
161 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300162}
163
164void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
165{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200166 if( ctx != NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300167 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200168 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300169 }
170}
171
172int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
173 const unsigned char key[32] )
174{
Daniel King34b822c2016-05-15 17:28:08 -0300175 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200176 ctx->state[0] = 0x61707865;
177 ctx->state[1] = 0x3320646e;
178 ctx->state[2] = 0x79622d32;
179 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300180
181 /* Set key */
Joe Subbiani6a506312021-07-07 16:56:29 +0100182 ctx->state[4] = MBEDTLS_GET_UINT32_LE( key, 0 );
183 ctx->state[5] = MBEDTLS_GET_UINT32_LE( key, 4 );
184 ctx->state[6] = MBEDTLS_GET_UINT32_LE( key, 8 );
185 ctx->state[7] = MBEDTLS_GET_UINT32_LE( key, 12 );
186 ctx->state[8] = MBEDTLS_GET_UINT32_LE( key, 16 );
187 ctx->state[9] = MBEDTLS_GET_UINT32_LE( key, 20 );
188 ctx->state[10] = MBEDTLS_GET_UINT32_LE( key, 24 );
189 ctx->state[11] = MBEDTLS_GET_UINT32_LE( key, 28 );
Daniel King34b822c2016-05-15 17:28:08 -0300190
191 return( 0 );
192}
193
194int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
195 const unsigned char nonce[12],
196 uint32_t counter )
197{
Daniel King34b822c2016-05-15 17:28:08 -0300198 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200199 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300200
201 /* Nonce */
Joe Subbiani6a506312021-07-07 16:56:29 +0100202 ctx->state[13] = MBEDTLS_GET_UINT32_LE( nonce, 0 );
203 ctx->state[14] = MBEDTLS_GET_UINT32_LE( nonce, 4 );
204 ctx->state[15] = MBEDTLS_GET_UINT32_LE( nonce, 8 );
Daniel King34b822c2016-05-15 17:28:08 -0300205
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200206 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200207
208 /* Initially, there's no keystream bytes available */
209 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
210
Daniel King34b822c2016-05-15 17:28:08 -0300211 return( 0 );
212}
213
Daniel Kingbd920622016-05-15 19:56:20 -0300214int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel King34b822c2016-05-15 17:28:08 -0300215 size_t size,
216 const unsigned char *input,
217 unsigned char *output )
218{
219 size_t offset = 0U;
Daniel King34b822c2016-05-15 17:28:08 -0300220
Daniel King34b822c2016-05-15 17:28:08 -0300221 /* Use leftover keystream bytes, if available */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200222 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300223 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200224 output[offset] = input[offset]
225 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300226
227 ctx->keystream_bytes_used++;
228 offset++;
229 size--;
230 }
231
232 /* Process full blocks */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200233 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300234 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200235 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200236 chacha20_block( ctx->state, ctx->keystream8 );
237 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300238
Dave Rodgmanc1d90222022-11-22 16:35:42 +0000239 mbedtls_xor( output + offset, input + offset, ctx->keystream8, 64U );
Daniel King34b822c2016-05-15 17:28:08 -0300240
Daniel Kingb8025c52016-05-17 14:43:01 -0300241 offset += CHACHA20_BLOCK_SIZE_BYTES;
242 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300243 }
244
245 /* Last (partial) block */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200246 if( size > 0U )
Daniel King34b822c2016-05-15 17:28:08 -0300247 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200248 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200249 chacha20_block( ctx->state, ctx->keystream8 );
250 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300251
Dave Rodgmanc1d90222022-11-22 16:35:42 +0000252 mbedtls_xor( output + offset, input + offset, ctx->keystream8, size );
Daniel King34b822c2016-05-15 17:28:08 -0300253
254 ctx->keystream_bytes_used = size;
255
Daniel King34b822c2016-05-15 17:28:08 -0300256 }
257
Daniel Kinge6e79682016-05-24 11:16:17 -0300258 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300259}
260
Daniel King34b822c2016-05-15 17:28:08 -0300261int mbedtls_chacha20_crypt( const unsigned char key[32],
262 const unsigned char nonce[12],
263 uint32_t counter,
264 size_t data_len,
265 const unsigned char* input,
266 unsigned char* output )
267{
268 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000269 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300270
271 mbedtls_chacha20_init( &ctx );
272
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200273 ret = mbedtls_chacha20_setkey( &ctx, key );
274 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300275 goto cleanup;
276
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200277 ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
278 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300279 goto cleanup;
280
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200281 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300282
283cleanup:
284 mbedtls_chacha20_free( &ctx );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200285 return( ret );
Daniel King34b822c2016-05-15 17:28:08 -0300286}
287
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200288#endif /* !MBEDTLS_CHACHA20_ALT */
289
Daniel King34b822c2016-05-15 17:28:08 -0300290#if defined(MBEDTLS_SELF_TEST)
291
292static const unsigned char test_keys[2][32] =
293{
294 {
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
299 },
300 {
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
305 }
306};
307
308static const unsigned char test_nonces[2][12] =
309{
310 {
311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x00
313 },
314 {
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x02
317 }
318};
319
320static const uint32_t test_counters[2] =
321{
322 0U,
323 1U
324};
325
326static const unsigned char test_input[2][375] =
327{
328 {
329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
337 },
338 {
339 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
340 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
341 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
342 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
343 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
344 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
345 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
346 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
347 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
348 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
349 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
350 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
351 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
352 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
353 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
354 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
355 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
356 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
357 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
358 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
359 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
360 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
361 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
362 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
363 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
364 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
365 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
366 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
367 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
368 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
369 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
370 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
371 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
372 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
373 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
374 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
375 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
376 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
377 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
378 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
379 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
380 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
381 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
382 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
383 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
384 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
385 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
386 }
387};
388
389static const unsigned char test_output[2][375] =
390{
391 {
392 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
393 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
394 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
395 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
396 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
397 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
398 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
399 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
400 },
401 {
402 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
403 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
404 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
405 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
406 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
407 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
408 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
409 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
410 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
411 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
412 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
413 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
414 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
415 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
416 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
417 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
418 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
419 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
420 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
421 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
422 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
423 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
424 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
425 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
426 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
427 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
428 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
429 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
430 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
431 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
432 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
433 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
434 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
435 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
436 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
437 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
438 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
439 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
440 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
441 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
442 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
443 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
444 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
445 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
446 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
447 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
448 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
449 }
450};
451
452static const size_t test_lengths[2] =
453{
454 64U,
455 375U
456};
457
Ouss4e0b26872020-08-11 16:07:09 +0100458/* Make sure no other definition is already present. */
459#undef ASSERT
460
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200461#define ASSERT( cond, args ) \
462 do \
463 { \
464 if( ! ( cond ) ) \
465 { \
466 if( verbose != 0 ) \
467 mbedtls_printf args; \
468 \
469 return( -1 ); \
470 } \
471 } \
472 while( 0 )
473
Daniel King34b822c2016-05-15 17:28:08 -0300474int mbedtls_chacha20_self_test( int verbose )
475{
476 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200477 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000478 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300479
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200480 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300481 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200482 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200483 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300484
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200485 ret = mbedtls_chacha20_crypt( test_keys[i],
486 test_nonces[i],
487 test_counters[i],
488 test_lengths[i],
489 test_input[i],
490 output );
Daniel King34b822c2016-05-15 17:28:08 -0300491
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200492 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
Daniel King34b822c2016-05-15 17:28:08 -0300493
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200494 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
495 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300496
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200497 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300498 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300499 }
500
501 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300502 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300503
504 return( 0 );
505}
506
507#endif /* MBEDTLS_SELF_TEST */
508
509#endif /* !MBEDTLS_CHACHA20_C */