blob: bd0701482c090dce8612dfe34bee2d7a0ffc138d [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
Hanno Becker305e4e42018-12-11 15:03:16 +000039/* Parameter validation macros */
40#define CHACHA20_VALIDATE_RET( cond ) \
41 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
42#define CHACHA20_VALIDATE( cond ) \
43 MBEDTLS_INTERNAL_VALIDATE( cond )
44
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020045#define ROTL32( value, amount ) \
Hanno Becker1eeca412018-10-15 12:01:35 +010046 ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030047
48#define CHACHA20_CTR_INDEX ( 12U )
49
50#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
51
Daniel King34b822c2016-05-15 17:28:08 -030052/**
53 * \brief ChaCha20 quarter round operation.
54 *
55 * The quarter round is defined as follows (from RFC 7539):
56 * 1. a += b; d ^= a; d <<<= 16;
57 * 2. c += d; b ^= c; b <<<= 12;
58 * 3. a += b; d ^= a; d <<<= 8;
59 * 4. c += d; b ^= c; b <<<= 7;
60 *
61 * \param state ChaCha20 state to modify.
62 * \param a The index of 'a' in the state.
63 * \param b The index of 'b' in the state.
64 * \param c The index of 'c' in the state.
65 * \param d The index of 'd' in the state.
66 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020067static inline void chacha20_quarter_round( uint32_t state[16],
68 size_t a,
69 size_t b,
70 size_t c,
71 size_t d )
Daniel King34b822c2016-05-15 17:28:08 -030072{
73 /* a += b; d ^= a; d <<<= 16; */
74 state[a] += state[b];
75 state[d] ^= state[a];
76 state[d] = ROTL32( state[d], 16 );
77
78 /* c += d; b ^= c; b <<<= 12 */
79 state[c] += state[d];
80 state[b] ^= state[c];
81 state[b] = ROTL32( state[b], 12 );
82
83 /* a += b; d ^= a; d <<<= 8; */
84 state[a] += state[b];
85 state[d] ^= state[a];
86 state[d] = ROTL32( state[d], 8 );
87
88 /* c += d; b ^= c; b <<<= 7; */
89 state[c] += state[d];
90 state[b] ^= state[c];
91 state[b] = ROTL32( state[b], 7 );
92}
93
94/**
95 * \brief Perform the ChaCha20 inner block operation.
96 *
97 * This function performs two rounds: the column round and the
98 * diagonal round.
99 *
100 * \param state The ChaCha20 state to update.
101 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200102static void chacha20_inner_block( uint32_t state[16] )
Daniel King34b822c2016-05-15 17:28:08 -0300103{
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200104 chacha20_quarter_round( state, 0, 4, 8, 12 );
105 chacha20_quarter_round( state, 1, 5, 9, 13 );
106 chacha20_quarter_round( state, 2, 6, 10, 14 );
107 chacha20_quarter_round( state, 3, 7, 11, 15 );
Daniel King34b822c2016-05-15 17:28:08 -0300108
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200109 chacha20_quarter_round( state, 0, 5, 10, 15 );
110 chacha20_quarter_round( state, 1, 6, 11, 12 );
111 chacha20_quarter_round( state, 2, 7, 8, 13 );
112 chacha20_quarter_round( state, 3, 4, 9, 14 );
Daniel King34b822c2016-05-15 17:28:08 -0300113}
114
115/**
116 * \brief Generates a keystream block.
117 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200118 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300119 * \param keystream Generated keystream bytes are written to this buffer.
120 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200121static void chacha20_block( const uint32_t initial_state[16],
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200122 unsigned char keystream[64] )
Daniel King34b822c2016-05-15 17:28:08 -0300123{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200124 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300125 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300126
Daniel Kingb8025c52016-05-17 14:43:01 -0300127 memcpy( working_state,
128 initial_state,
129 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300130
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200131 for( i = 0U; i < 10U; i++ )
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200132 chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300133
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200134 working_state[ 0] += initial_state[ 0];
135 working_state[ 1] += initial_state[ 1];
136 working_state[ 2] += initial_state[ 2];
137 working_state[ 3] += initial_state[ 3];
138 working_state[ 4] += initial_state[ 4];
139 working_state[ 5] += initial_state[ 5];
140 working_state[ 6] += initial_state[ 6];
141 working_state[ 7] += initial_state[ 7];
142 working_state[ 8] += initial_state[ 8];
143 working_state[ 9] += initial_state[ 9];
Daniel Kingb8025c52016-05-17 14:43:01 -0300144 working_state[10] += initial_state[10];
145 working_state[11] += initial_state[11];
146 working_state[12] += initial_state[12];
147 working_state[13] += initial_state[13];
148 working_state[14] += initial_state[14];
149 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300150
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200151 for( i = 0U; i < 16; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300152 {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200153 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300154
Joe Subbiani6627fb22021-07-16 15:02:55 +0100155 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Daniel King34b822c2016-05-15 17:28:08 -0300156 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200157
158 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
Daniel King34b822c2016-05-15 17:28:08 -0300159}
160
161void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
162{
Hanno Becker305e4e42018-12-11 15:03:16 +0000163 CHACHA20_VALIDATE( ctx != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300164
Hanno Becker305e4e42018-12-11 15:03:16 +0000165 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
166 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
167
168 /* Initially, there's no keystream bytes available */
169 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300170}
171
172void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
173{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200174 if( ctx != NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300175 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200176 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300177 }
178}
179
180int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
181 const unsigned char key[32] )
182{
Hanno Becker305e4e42018-12-11 15:03:16 +0000183 CHACHA20_VALIDATE_RET( ctx != NULL );
184 CHACHA20_VALIDATE_RET( key != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300185
186 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200187 ctx->state[0] = 0x61707865;
188 ctx->state[1] = 0x3320646e;
189 ctx->state[2] = 0x79622d32;
190 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300191
192 /* Set key */
Joe Subbiani9231d5f2021-07-07 16:56:29 +0100193 ctx->state[4] = MBEDTLS_GET_UINT32_LE( key, 0 );
194 ctx->state[5] = MBEDTLS_GET_UINT32_LE( key, 4 );
195 ctx->state[6] = MBEDTLS_GET_UINT32_LE( key, 8 );
196 ctx->state[7] = MBEDTLS_GET_UINT32_LE( key, 12 );
197 ctx->state[8] = MBEDTLS_GET_UINT32_LE( key, 16 );
198 ctx->state[9] = MBEDTLS_GET_UINT32_LE( key, 20 );
199 ctx->state[10] = MBEDTLS_GET_UINT32_LE( key, 24 );
200 ctx->state[11] = MBEDTLS_GET_UINT32_LE( key, 28 );
Daniel King34b822c2016-05-15 17:28:08 -0300201
202 return( 0 );
203}
204
205int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
206 const unsigned char nonce[12],
207 uint32_t counter )
208{
Hanno Becker305e4e42018-12-11 15:03:16 +0000209 CHACHA20_VALIDATE_RET( ctx != NULL );
210 CHACHA20_VALIDATE_RET( nonce != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300211
212 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200213 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300214
215 /* Nonce */
Joe Subbiani9231d5f2021-07-07 16:56:29 +0100216 ctx->state[13] = MBEDTLS_GET_UINT32_LE( nonce, 0 );
217 ctx->state[14] = MBEDTLS_GET_UINT32_LE( nonce, 4 );
218 ctx->state[15] = MBEDTLS_GET_UINT32_LE( nonce, 8 );
Daniel King34b822c2016-05-15 17:28:08 -0300219
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200220 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200221
222 /* Initially, there's no keystream bytes available */
223 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
224
Daniel King34b822c2016-05-15 17:28:08 -0300225 return( 0 );
226}
227
Daniel Kingbd920622016-05-15 19:56:20 -0300228int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel King34b822c2016-05-15 17:28:08 -0300229 size_t size,
230 const unsigned char *input,
231 unsigned char *output )
232{
233 size_t offset = 0U;
234 size_t i;
235
Hanno Becker305e4e42018-12-11 15:03:16 +0000236 CHACHA20_VALIDATE_RET( ctx != NULL );
237 CHACHA20_VALIDATE_RET( size == 0 || input != NULL );
238 CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300239
240 /* Use leftover keystream bytes, if available */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200241 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300242 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200243 output[offset] = input[offset]
244 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300245
246 ctx->keystream_bytes_used++;
247 offset++;
248 size--;
249 }
250
251 /* Process full blocks */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200252 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300253 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200254 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200255 chacha20_block( ctx->state, ctx->keystream8 );
256 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300257
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200258 for( i = 0U; i < 64U; i += 8U )
Daniel King34b822c2016-05-15 17:28:08 -0300259 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200260 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
261 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
262 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
263 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
264 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
265 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
266 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
267 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
Daniel King34b822c2016-05-15 17:28:08 -0300268 }
269
Daniel Kingb8025c52016-05-17 14:43:01 -0300270 offset += CHACHA20_BLOCK_SIZE_BYTES;
271 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300272 }
273
274 /* Last (partial) block */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200275 if( size > 0U )
Daniel King34b822c2016-05-15 17:28:08 -0300276 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200277 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200278 chacha20_block( ctx->state, ctx->keystream8 );
279 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300280
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200281 for( i = 0U; i < size; i++)
Daniel King34b822c2016-05-15 17:28:08 -0300282 {
283 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
284 }
285
286 ctx->keystream_bytes_used = size;
287
Daniel King34b822c2016-05-15 17:28:08 -0300288 }
289
Daniel Kinge6e79682016-05-24 11:16:17 -0300290 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300291}
292
Daniel King34b822c2016-05-15 17:28:08 -0300293int mbedtls_chacha20_crypt( const unsigned char key[32],
294 const unsigned char nonce[12],
295 uint32_t counter,
296 size_t data_len,
297 const unsigned char* input,
298 unsigned char* output )
299{
300 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000301 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300302
Hanno Becker305e4e42018-12-11 15:03:16 +0000303 CHACHA20_VALIDATE_RET( key != NULL );
304 CHACHA20_VALIDATE_RET( nonce != NULL );
305 CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL );
306 CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
307
Daniel King34b822c2016-05-15 17:28:08 -0300308 mbedtls_chacha20_init( &ctx );
309
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200310 ret = mbedtls_chacha20_setkey( &ctx, key );
311 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300312 goto cleanup;
313
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200314 ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
315 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300316 goto cleanup;
317
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200318 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300319
320cleanup:
321 mbedtls_chacha20_free( &ctx );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200322 return( ret );
Daniel King34b822c2016-05-15 17:28:08 -0300323}
324
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200325#endif /* !MBEDTLS_CHACHA20_ALT */
326
Daniel King34b822c2016-05-15 17:28:08 -0300327#if defined(MBEDTLS_SELF_TEST)
328
329static const unsigned char test_keys[2][32] =
330{
331 {
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 },
337 {
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
342 }
343};
344
345static const unsigned char test_nonces[2][12] =
346{
347 {
348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
349 0x00, 0x00, 0x00, 0x00
350 },
351 {
352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353 0x00, 0x00, 0x00, 0x02
354 }
355};
356
357static const uint32_t test_counters[2] =
358{
359 0U,
360 1U
361};
362
363static const unsigned char test_input[2][375] =
364{
365 {
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
374 },
375 {
376 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
377 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
378 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
379 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
380 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
381 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
382 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
383 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
384 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
385 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
386 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
387 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
388 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
389 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
390 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
391 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
392 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
393 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
394 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
395 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
396 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
397 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
398 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
399 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
400 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
401 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
402 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
403 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
404 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
405 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
406 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
407 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
408 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
409 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
410 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
411 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
412 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
413 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
414 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
415 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
416 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
417 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
418 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
419 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
420 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
421 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
422 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
423 }
424};
425
426static const unsigned char test_output[2][375] =
427{
428 {
429 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
430 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
431 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
432 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
433 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
434 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
435 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
436 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
437 },
438 {
439 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
440 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
441 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
442 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
443 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
444 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
445 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
446 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
447 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
448 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
449 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
450 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
451 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
452 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
453 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
454 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
455 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
456 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
457 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
458 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
459 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
460 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
461 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
462 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
463 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
464 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
465 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
466 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
467 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
468 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
469 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
470 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
471 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
472 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
473 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
474 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
475 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
476 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
477 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
478 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
479 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
480 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
481 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
482 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
483 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
484 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
485 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
486 }
487};
488
489static const size_t test_lengths[2] =
490{
491 64U,
492 375U
493};
494
Ouss4e0b26872020-08-11 16:07:09 +0100495/* Make sure no other definition is already present. */
496#undef ASSERT
497
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200498#define ASSERT( cond, args ) \
499 do \
500 { \
501 if( ! ( cond ) ) \
502 { \
503 if( verbose != 0 ) \
504 mbedtls_printf args; \
505 \
506 return( -1 ); \
507 } \
508 } \
509 while( 0 )
510
Daniel King34b822c2016-05-15 17:28:08 -0300511int mbedtls_chacha20_self_test( int verbose )
512{
513 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200514 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000515 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300516
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200517 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300518 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200519 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200520 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300521
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200522 ret = mbedtls_chacha20_crypt( test_keys[i],
523 test_nonces[i],
524 test_counters[i],
525 test_lengths[i],
526 test_input[i],
527 output );
Daniel King34b822c2016-05-15 17:28:08 -0300528
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200529 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
Daniel King34b822c2016-05-15 17:28:08 -0300530
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200531 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
532 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300533
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200534 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300535 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300536 }
537
538 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300539 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300540
541 return( 0 );
542}
543
544#endif /* MBEDTLS_SELF_TEST */
545
546#endif /* !MBEDTLS_CHACHA20_C */