blob: 85d7461aac341c5f372b7f7603197a6a8e0748e4 [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;
220 size_t i;
221
Daniel King34b822c2016-05-15 17:28:08 -0300222 /* Use leftover keystream bytes, if available */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200223 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300224 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200225 output[offset] = input[offset]
226 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300227
228 ctx->keystream_bytes_used++;
229 offset++;
230 size--;
231 }
232
233 /* Process full blocks */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200234 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300235 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200236 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200237 chacha20_block( ctx->state, ctx->keystream8 );
238 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300239
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200240 for( i = 0U; i < 64U; i += 8U )
Daniel King34b822c2016-05-15 17:28:08 -0300241 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200242 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
243 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
244 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
245 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
246 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
247 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
248 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
249 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
Daniel King34b822c2016-05-15 17:28:08 -0300250 }
251
Daniel Kingb8025c52016-05-17 14:43:01 -0300252 offset += CHACHA20_BLOCK_SIZE_BYTES;
253 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300254 }
255
256 /* Last (partial) block */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200257 if( size > 0U )
Daniel King34b822c2016-05-15 17:28:08 -0300258 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200259 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200260 chacha20_block( ctx->state, ctx->keystream8 );
261 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300262
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200263 for( i = 0U; i < size; i++)
Daniel King34b822c2016-05-15 17:28:08 -0300264 {
265 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
266 }
267
268 ctx->keystream_bytes_used = size;
269
Daniel King34b822c2016-05-15 17:28:08 -0300270 }
271
Daniel Kinge6e79682016-05-24 11:16:17 -0300272 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300273}
274
Daniel King34b822c2016-05-15 17:28:08 -0300275int mbedtls_chacha20_crypt( const unsigned char key[32],
276 const unsigned char nonce[12],
277 uint32_t counter,
278 size_t data_len,
279 const unsigned char* input,
280 unsigned char* output )
281{
282 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000283 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300284
285 mbedtls_chacha20_init( &ctx );
286
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200287 ret = mbedtls_chacha20_setkey( &ctx, key );
288 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300289 goto cleanup;
290
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200291 ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
292 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300293 goto cleanup;
294
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200295 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300296
297cleanup:
298 mbedtls_chacha20_free( &ctx );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200299 return( ret );
Daniel King34b822c2016-05-15 17:28:08 -0300300}
301
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200302#endif /* !MBEDTLS_CHACHA20_ALT */
303
Daniel King34b822c2016-05-15 17:28:08 -0300304#if defined(MBEDTLS_SELF_TEST)
305
306static const unsigned char test_keys[2][32] =
307{
308 {
309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
313 },
314 {
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
319 }
320};
321
322static const unsigned char test_nonces[2][12] =
323{
324 {
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
326 0x00, 0x00, 0x00, 0x00
327 },
328 {
329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330 0x00, 0x00, 0x00, 0x02
331 }
332};
333
334static const uint32_t test_counters[2] =
335{
336 0U,
337 1U
338};
339
340static const unsigned char test_input[2][375] =
341{
342 {
343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
351 },
352 {
353 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
354 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
355 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
356 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
357 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
358 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
359 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
360 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
361 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
362 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
363 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
364 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
365 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
366 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
367 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
368 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
369 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
370 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
371 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
372 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
373 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
374 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
375 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
376 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
377 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
378 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
379 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
380 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
381 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
382 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
383 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
384 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
385 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
386 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
387 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
388 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
389 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
390 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
391 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
392 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
393 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
394 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
395 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
396 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
397 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
398 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
399 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
400 }
401};
402
403static const unsigned char test_output[2][375] =
404{
405 {
406 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
407 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
408 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
409 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
410 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
411 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
412 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
413 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
414 },
415 {
416 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
417 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
418 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
419 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
420 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
421 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
422 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
423 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
424 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
425 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
426 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
427 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
428 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
429 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
430 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
431 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
432 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
433 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
434 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
435 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
436 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
437 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
438 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
439 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
440 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
441 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
442 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
443 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
444 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
445 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
446 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
447 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
448 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
449 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
450 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
451 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
452 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
453 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
454 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
455 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
456 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
457 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
458 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
459 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
460 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
461 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
462 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
463 }
464};
465
466static const size_t test_lengths[2] =
467{
468 64U,
469 375U
470};
471
Ouss4e0b26872020-08-11 16:07:09 +0100472/* Make sure no other definition is already present. */
473#undef ASSERT
474
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200475#define ASSERT( cond, args ) \
476 do \
477 { \
478 if( ! ( cond ) ) \
479 { \
480 if( verbose != 0 ) \
481 mbedtls_printf args; \
482 \
483 return( -1 ); \
484 } \
485 } \
486 while( 0 )
487
Daniel King34b822c2016-05-15 17:28:08 -0300488int mbedtls_chacha20_self_test( int verbose )
489{
490 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200491 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000492 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300493
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200494 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300495 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200496 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200497 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300498
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200499 ret = mbedtls_chacha20_crypt( test_keys[i],
500 test_nonces[i],
501 test_counters[i],
502 test_lengths[i],
503 test_input[i],
504 output );
Daniel King34b822c2016-05-15 17:28:08 -0300505
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200506 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
Daniel King34b822c2016-05-15 17:28:08 -0300507
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200508 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
509 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300510
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200511 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300512 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300513 }
514
515 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300516 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300517
518 return( 0 );
519}
520
521#endif /* MBEDTLS_SELF_TEST */
522
523#endif /* !MBEDTLS_CHACHA20_C */