blob: e53eb82f544b6b6725bb396919842eeebb547f28 [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é-Gonnard21a65e02018-06-07 11:54:17 +020039#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
40 !defined(inline) && !defined(__cplusplus)
41#define inline __inline
42#endif
43
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020044#define ROTL32( value, amount ) \
Hanno Becker1eeca412018-10-15 12:01:35 +010045 ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030046
47#define CHACHA20_CTR_INDEX ( 12U )
48
49#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
50
Daniel King34b822c2016-05-15 17:28:08 -030051/**
52 * \brief ChaCha20 quarter round operation.
53 *
54 * The quarter round is defined as follows (from RFC 7539):
55 * 1. a += b; d ^= a; d <<<= 16;
56 * 2. c += d; b ^= c; b <<<= 12;
57 * 3. a += b; d ^= a; d <<<= 8;
58 * 4. c += d; b ^= c; b <<<= 7;
59 *
60 * \param state ChaCha20 state to modify.
61 * \param a The index of 'a' in the state.
62 * \param b The index of 'b' in the state.
63 * \param c The index of 'c' in the state.
64 * \param d The index of 'd' in the state.
65 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020066static inline void chacha20_quarter_round( uint32_t state[16],
67 size_t a,
68 size_t b,
69 size_t c,
70 size_t d )
Daniel King34b822c2016-05-15 17:28:08 -030071{
72 /* a += b; d ^= a; d <<<= 16; */
73 state[a] += state[b];
74 state[d] ^= state[a];
75 state[d] = ROTL32( state[d], 16 );
76
77 /* c += d; b ^= c; b <<<= 12 */
78 state[c] += state[d];
79 state[b] ^= state[c];
80 state[b] = ROTL32( state[b], 12 );
81
82 /* a += b; d ^= a; d <<<= 8; */
83 state[a] += state[b];
84 state[d] ^= state[a];
85 state[d] = ROTL32( state[d], 8 );
86
87 /* c += d; b ^= c; b <<<= 7; */
88 state[c] += state[d];
89 state[b] ^= state[c];
90 state[b] = ROTL32( state[b], 7 );
91}
92
93/**
94 * \brief Perform the ChaCha20 inner block operation.
95 *
96 * This function performs two rounds: the column round and the
97 * diagonal round.
98 *
99 * \param state The ChaCha20 state to update.
100 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200101static void chacha20_inner_block( uint32_t state[16] )
Daniel King34b822c2016-05-15 17:28:08 -0300102{
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200103 chacha20_quarter_round( state, 0, 4, 8, 12 );
104 chacha20_quarter_round( state, 1, 5, 9, 13 );
105 chacha20_quarter_round( state, 2, 6, 10, 14 );
106 chacha20_quarter_round( state, 3, 7, 11, 15 );
Daniel King34b822c2016-05-15 17:28:08 -0300107
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200108 chacha20_quarter_round( state, 0, 5, 10, 15 );
109 chacha20_quarter_round( state, 1, 6, 11, 12 );
110 chacha20_quarter_round( state, 2, 7, 8, 13 );
111 chacha20_quarter_round( state, 3, 4, 9, 14 );
Daniel King34b822c2016-05-15 17:28:08 -0300112}
113
114/**
115 * \brief Generates a keystream block.
116 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200117 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300118 * \param keystream Generated keystream bytes are written to this buffer.
119 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200120static void chacha20_block( const uint32_t initial_state[16],
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200121 unsigned char keystream[64] )
Daniel King34b822c2016-05-15 17:28:08 -0300122{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200123 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300124 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300125
Daniel Kingb8025c52016-05-17 14:43:01 -0300126 memcpy( working_state,
127 initial_state,
128 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300129
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200130 for( i = 0U; i < 10U; i++ )
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200131 chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300132
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200133 working_state[ 0] += initial_state[ 0];
134 working_state[ 1] += initial_state[ 1];
135 working_state[ 2] += initial_state[ 2];
136 working_state[ 3] += initial_state[ 3];
137 working_state[ 4] += initial_state[ 4];
138 working_state[ 5] += initial_state[ 5];
139 working_state[ 6] += initial_state[ 6];
140 working_state[ 7] += initial_state[ 7];
141 working_state[ 8] += initial_state[ 8];
142 working_state[ 9] += initial_state[ 9];
Daniel Kingb8025c52016-05-17 14:43:01 -0300143 working_state[10] += initial_state[10];
144 working_state[11] += initial_state[11];
145 working_state[12] += initial_state[12];
146 working_state[13] += initial_state[13];
147 working_state[14] += initial_state[14];
148 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300149
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200150 for( i = 0U; i < 16; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300151 {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200152 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300153
Joe Subbianib6511b02021-07-16 15:02:55 +0100154 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Daniel King34b822c2016-05-15 17:28:08 -0300155 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200156
157 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
Daniel King34b822c2016-05-15 17:28:08 -0300158}
159
160void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
161{
Hanno Becker305e4e42018-12-11 15:03:16 +0000162 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
163 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
164
165 /* Initially, there's no keystream bytes available */
166 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300167}
168
169void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
170{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200171 if( ctx != NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300172 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200173 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300174 }
175}
176
177int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
178 const unsigned char key[32] )
179{
Daniel King34b822c2016-05-15 17:28:08 -0300180 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200181 ctx->state[0] = 0x61707865;
182 ctx->state[1] = 0x3320646e;
183 ctx->state[2] = 0x79622d32;
184 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300185
186 /* Set key */
Joe Subbiani6a506312021-07-07 16:56:29 +0100187 ctx->state[4] = MBEDTLS_GET_UINT32_LE( key, 0 );
188 ctx->state[5] = MBEDTLS_GET_UINT32_LE( key, 4 );
189 ctx->state[6] = MBEDTLS_GET_UINT32_LE( key, 8 );
190 ctx->state[7] = MBEDTLS_GET_UINT32_LE( key, 12 );
191 ctx->state[8] = MBEDTLS_GET_UINT32_LE( key, 16 );
192 ctx->state[9] = MBEDTLS_GET_UINT32_LE( key, 20 );
193 ctx->state[10] = MBEDTLS_GET_UINT32_LE( key, 24 );
194 ctx->state[11] = MBEDTLS_GET_UINT32_LE( key, 28 );
Daniel King34b822c2016-05-15 17:28:08 -0300195
196 return( 0 );
197}
198
199int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
200 const unsigned char nonce[12],
201 uint32_t counter )
202{
Daniel King34b822c2016-05-15 17:28:08 -0300203 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200204 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300205
206 /* Nonce */
Joe Subbiani6a506312021-07-07 16:56:29 +0100207 ctx->state[13] = MBEDTLS_GET_UINT32_LE( nonce, 0 );
208 ctx->state[14] = MBEDTLS_GET_UINT32_LE( nonce, 4 );
209 ctx->state[15] = MBEDTLS_GET_UINT32_LE( nonce, 8 );
Daniel King34b822c2016-05-15 17:28:08 -0300210
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200211 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200212
213 /* Initially, there's no keystream bytes available */
214 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
215
Daniel King34b822c2016-05-15 17:28:08 -0300216 return( 0 );
217}
218
Daniel Kingbd920622016-05-15 19:56:20 -0300219int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel King34b822c2016-05-15 17:28:08 -0300220 size_t size,
221 const unsigned char *input,
222 unsigned char *output )
223{
224 size_t offset = 0U;
225 size_t i;
226
Daniel King34b822c2016-05-15 17:28:08 -0300227 /* Use leftover keystream bytes, if available */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200228 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300229 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200230 output[offset] = input[offset]
231 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300232
233 ctx->keystream_bytes_used++;
234 offset++;
235 size--;
236 }
237
238 /* Process full blocks */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200239 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300240 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200241 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200242 chacha20_block( ctx->state, ctx->keystream8 );
243 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300244
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200245 for( i = 0U; i < 64U; i += 8U )
Daniel King34b822c2016-05-15 17:28:08 -0300246 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200247 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
248 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
249 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
250 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
251 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
252 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
253 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
254 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
Daniel King34b822c2016-05-15 17:28:08 -0300255 }
256
Daniel Kingb8025c52016-05-17 14:43:01 -0300257 offset += CHACHA20_BLOCK_SIZE_BYTES;
258 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300259 }
260
261 /* Last (partial) block */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200262 if( size > 0U )
Daniel King34b822c2016-05-15 17:28:08 -0300263 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200264 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200265 chacha20_block( ctx->state, ctx->keystream8 );
266 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300267
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200268 for( i = 0U; i < size; i++)
Daniel King34b822c2016-05-15 17:28:08 -0300269 {
270 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
271 }
272
273 ctx->keystream_bytes_used = size;
274
Daniel King34b822c2016-05-15 17:28:08 -0300275 }
276
Daniel Kinge6e79682016-05-24 11:16:17 -0300277 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300278}
279
Daniel King34b822c2016-05-15 17:28:08 -0300280int mbedtls_chacha20_crypt( const unsigned char key[32],
281 const unsigned char nonce[12],
282 uint32_t counter,
283 size_t data_len,
284 const unsigned char* input,
285 unsigned char* output )
286{
287 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000288 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300289
290 mbedtls_chacha20_init( &ctx );
291
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200292 ret = mbedtls_chacha20_setkey( &ctx, key );
293 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300294 goto cleanup;
295
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200296 ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
297 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300298 goto cleanup;
299
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200300 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300301
302cleanup:
303 mbedtls_chacha20_free( &ctx );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200304 return( ret );
Daniel King34b822c2016-05-15 17:28:08 -0300305}
306
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200307#endif /* !MBEDTLS_CHACHA20_ALT */
308
Daniel King34b822c2016-05-15 17:28:08 -0300309#if defined(MBEDTLS_SELF_TEST)
310
311static const unsigned char test_keys[2][32] =
312{
313 {
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 },
319 {
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
324 }
325};
326
327static const unsigned char test_nonces[2][12] =
328{
329 {
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x00, 0x00, 0x00, 0x00
332 },
333 {
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0x02
336 }
337};
338
339static const uint32_t test_counters[2] =
340{
341 0U,
342 1U
343};
344
345static const unsigned char test_input[2][375] =
346{
347 {
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
356 },
357 {
358 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
359 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
360 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
361 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
362 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
363 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
364 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
365 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
366 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
367 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
368 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
369 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
370 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
371 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
372 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
373 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
374 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
375 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
376 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
377 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
378 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
379 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
380 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
381 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
382 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
383 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
384 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
385 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
386 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
387 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
388 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
389 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
390 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
391 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
392 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
393 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
394 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
395 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
396 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
397 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
398 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
399 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
400 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
401 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
402 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
403 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
404 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
405 }
406};
407
408static const unsigned char test_output[2][375] =
409{
410 {
411 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
412 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
413 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
414 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
415 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
416 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
417 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
418 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
419 },
420 {
421 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
422 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
423 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
424 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
425 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
426 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
427 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
428 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
429 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
430 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
431 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
432 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
433 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
434 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
435 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
436 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
437 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
438 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
439 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
440 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
441 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
442 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
443 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
444 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
445 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
446 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
447 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
448 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
449 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
450 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
451 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
452 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
453 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
454 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
455 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
456 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
457 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
458 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
459 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
460 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
461 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
462 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
463 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
464 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
465 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
466 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
467 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
468 }
469};
470
471static const size_t test_lengths[2] =
472{
473 64U,
474 375U
475};
476
Ouss4e0b26872020-08-11 16:07:09 +0100477/* Make sure no other definition is already present. */
478#undef ASSERT
479
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200480#define ASSERT( cond, args ) \
481 do \
482 { \
483 if( ! ( cond ) ) \
484 { \
485 if( verbose != 0 ) \
486 mbedtls_printf args; \
487 \
488 return( -1 ); \
489 } \
490 } \
491 while( 0 )
492
Daniel King34b822c2016-05-15 17:28:08 -0300493int mbedtls_chacha20_self_test( int verbose )
494{
495 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200496 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000497 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300498
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200499 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300500 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200501 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200502 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300503
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200504 ret = mbedtls_chacha20_crypt( test_keys[i],
505 test_nonces[i],
506 test_counters[i],
507 test_lengths[i],
508 test_input[i],
509 output );
Daniel King34b822c2016-05-15 17:28:08 -0300510
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200511 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
Daniel King34b822c2016-05-15 17:28:08 -0300512
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200513 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
514 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300515
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200516 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300517 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300518 }
519
520 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300521 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300522
523 return( 0 );
524}
525
526#endif /* MBEDTLS_SELF_TEST */
527
528#endif /* !MBEDTLS_CHACHA20_C */