blob: 658f0469017059962da6e68537a8be65cd13bd23 [file] [log] [blame]
Daniel King34b822c2016-05-15 17:28:08 -03001/**
2 * \file chacha20.c
3 *
4 * \brief ChaCha20 cipher.
5 *
6 * \author Daniel King <damaki.gh@gmail.com>
7 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02008 * Copyright The Mbed TLS Contributors
Daniel King34b822c2016-05-15 17:28:08 -03009 * SPDX-License-Identifier: Apache-2.0
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License"); you may
12 * not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
19 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
Daniel King34b822c2016-05-15 17:28:08 -030022 */
Daniel King34b822c2016-05-15 17:28:08 -030023
Gilles Peskinedb09ef62020-06-03 01:43:33 +020024#include "common.h"
Daniel King34b822c2016-05-15 17:28:08 -030025
26#if defined(MBEDTLS_CHACHA20_C)
27
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020028#include "mbedtls/chacha20.h"
29#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000030#include "mbedtls/error.h"
Daniel King34b822c2016-05-15 17:28:08 -030031
32#include <stddef.h>
33#include <string.h>
34
35#if defined(MBEDTLS_SELF_TEST)
36#if defined(MBEDTLS_PLATFORM_C)
37#include "mbedtls/platform.h"
38#else
39#include <stdio.h>
40#define mbedtls_printf printf
41#endif /* MBEDTLS_PLATFORM_C */
42#endif /* MBEDTLS_SELF_TEST */
43
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020044#if !defined(MBEDTLS_CHACHA20_ALT)
45
Manuel Pégourié-Gonnard21a65e02018-06-07 11:54:17 +020046#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
47 !defined(inline) && !defined(__cplusplus)
48#define inline __inline
49#endif
50
Hanno Becker305e4e42018-12-11 15:03:16 +000051/* Parameter validation macros */
52#define CHACHA20_VALIDATE_RET( cond ) \
53 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
54#define CHACHA20_VALIDATE( cond ) \
55 MBEDTLS_INTERNAL_VALIDATE( cond )
56
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020057#define ROTL32( value, amount ) \
Hanno Becker1eeca412018-10-15 12:01:35 +010058 ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030059
60#define CHACHA20_CTR_INDEX ( 12U )
61
62#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
63
Daniel King34b822c2016-05-15 17:28:08 -030064/**
65 * \brief ChaCha20 quarter round operation.
66 *
67 * The quarter round is defined as follows (from RFC 7539):
68 * 1. a += b; d ^= a; d <<<= 16;
69 * 2. c += d; b ^= c; b <<<= 12;
70 * 3. a += b; d ^= a; d <<<= 8;
71 * 4. c += d; b ^= c; b <<<= 7;
72 *
73 * \param state ChaCha20 state to modify.
74 * \param a The index of 'a' in the state.
75 * \param b The index of 'b' in the state.
76 * \param c The index of 'c' in the state.
77 * \param d The index of 'd' in the state.
78 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020079static inline void chacha20_quarter_round( uint32_t state[16],
80 size_t a,
81 size_t b,
82 size_t c,
83 size_t d )
Daniel King34b822c2016-05-15 17:28:08 -030084{
85 /* a += b; d ^= a; d <<<= 16; */
86 state[a] += state[b];
87 state[d] ^= state[a];
88 state[d] = ROTL32( state[d], 16 );
89
90 /* c += d; b ^= c; b <<<= 12 */
91 state[c] += state[d];
92 state[b] ^= state[c];
93 state[b] = ROTL32( state[b], 12 );
94
95 /* a += b; d ^= a; d <<<= 8; */
96 state[a] += state[b];
97 state[d] ^= state[a];
98 state[d] = ROTL32( state[d], 8 );
99
100 /* c += d; b ^= c; b <<<= 7; */
101 state[c] += state[d];
102 state[b] ^= state[c];
103 state[b] = ROTL32( state[b], 7 );
104}
105
106/**
107 * \brief Perform the ChaCha20 inner block operation.
108 *
109 * This function performs two rounds: the column round and the
110 * diagonal round.
111 *
112 * \param state The ChaCha20 state to update.
113 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200114static void chacha20_inner_block( uint32_t state[16] )
Daniel King34b822c2016-05-15 17:28:08 -0300115{
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200116 chacha20_quarter_round( state, 0, 4, 8, 12 );
117 chacha20_quarter_round( state, 1, 5, 9, 13 );
118 chacha20_quarter_round( state, 2, 6, 10, 14 );
119 chacha20_quarter_round( state, 3, 7, 11, 15 );
Daniel King34b822c2016-05-15 17:28:08 -0300120
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200121 chacha20_quarter_round( state, 0, 5, 10, 15 );
122 chacha20_quarter_round( state, 1, 6, 11, 12 );
123 chacha20_quarter_round( state, 2, 7, 8, 13 );
124 chacha20_quarter_round( state, 3, 4, 9, 14 );
Daniel King34b822c2016-05-15 17:28:08 -0300125}
126
127/**
128 * \brief Generates a keystream block.
129 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200130 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300131 * \param keystream Generated keystream bytes are written to this buffer.
132 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200133static void chacha20_block( const uint32_t initial_state[16],
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200134 unsigned char keystream[64] )
Daniel King34b822c2016-05-15 17:28:08 -0300135{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200136 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300137 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300138
Daniel Kingb8025c52016-05-17 14:43:01 -0300139 memcpy( working_state,
140 initial_state,
141 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300142
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200143 for( i = 0U; i < 10U; i++ )
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200144 chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300145
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200146 working_state[ 0] += initial_state[ 0];
147 working_state[ 1] += initial_state[ 1];
148 working_state[ 2] += initial_state[ 2];
149 working_state[ 3] += initial_state[ 3];
150 working_state[ 4] += initial_state[ 4];
151 working_state[ 5] += initial_state[ 5];
152 working_state[ 6] += initial_state[ 6];
153 working_state[ 7] += initial_state[ 7];
154 working_state[ 8] += initial_state[ 8];
155 working_state[ 9] += initial_state[ 9];
Daniel Kingb8025c52016-05-17 14:43:01 -0300156 working_state[10] += initial_state[10];
157 working_state[11] += initial_state[11];
158 working_state[12] += initial_state[12];
159 working_state[13] += initial_state[13];
160 working_state[14] += initial_state[14];
161 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300162
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200163 for( i = 0U; i < 16; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300164 {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200165 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300166
Joe Subbiani6627fb22021-07-16 15:02:55 +0100167 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Daniel King34b822c2016-05-15 17:28:08 -0300168 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200169
170 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
Daniel King34b822c2016-05-15 17:28:08 -0300171}
172
173void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
174{
Hanno Becker305e4e42018-12-11 15:03:16 +0000175 CHACHA20_VALIDATE( ctx != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300176
Hanno Becker305e4e42018-12-11 15:03:16 +0000177 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
178 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
179
180 /* Initially, there's no keystream bytes available */
181 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300182}
183
184void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
185{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200186 if( ctx != NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300187 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200188 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300189 }
190}
191
192int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
193 const unsigned char key[32] )
194{
Hanno Becker305e4e42018-12-11 15:03:16 +0000195 CHACHA20_VALIDATE_RET( ctx != NULL );
196 CHACHA20_VALIDATE_RET( key != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300197
198 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200199 ctx->state[0] = 0x61707865;
200 ctx->state[1] = 0x3320646e;
201 ctx->state[2] = 0x79622d32;
202 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300203
204 /* Set key */
Joe Subbiani9231d5f2021-07-07 16:56:29 +0100205 ctx->state[4] = MBEDTLS_GET_UINT32_LE( key, 0 );
206 ctx->state[5] = MBEDTLS_GET_UINT32_LE( key, 4 );
207 ctx->state[6] = MBEDTLS_GET_UINT32_LE( key, 8 );
208 ctx->state[7] = MBEDTLS_GET_UINT32_LE( key, 12 );
209 ctx->state[8] = MBEDTLS_GET_UINT32_LE( key, 16 );
210 ctx->state[9] = MBEDTLS_GET_UINT32_LE( key, 20 );
211 ctx->state[10] = MBEDTLS_GET_UINT32_LE( key, 24 );
212 ctx->state[11] = MBEDTLS_GET_UINT32_LE( key, 28 );
Daniel King34b822c2016-05-15 17:28:08 -0300213
214 return( 0 );
215}
216
217int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
218 const unsigned char nonce[12],
219 uint32_t counter )
220{
Hanno Becker305e4e42018-12-11 15:03:16 +0000221 CHACHA20_VALIDATE_RET( ctx != NULL );
222 CHACHA20_VALIDATE_RET( nonce != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300223
224 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200225 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300226
227 /* Nonce */
Joe Subbiani9231d5f2021-07-07 16:56:29 +0100228 ctx->state[13] = MBEDTLS_GET_UINT32_LE( nonce, 0 );
229 ctx->state[14] = MBEDTLS_GET_UINT32_LE( nonce, 4 );
230 ctx->state[15] = MBEDTLS_GET_UINT32_LE( nonce, 8 );
Daniel King34b822c2016-05-15 17:28:08 -0300231
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200232 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200233
234 /* Initially, there's no keystream bytes available */
235 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
236
Daniel King34b822c2016-05-15 17:28:08 -0300237 return( 0 );
238}
239
Daniel Kingbd920622016-05-15 19:56:20 -0300240int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel King34b822c2016-05-15 17:28:08 -0300241 size_t size,
242 const unsigned char *input,
243 unsigned char *output )
244{
245 size_t offset = 0U;
246 size_t i;
247
Hanno Becker305e4e42018-12-11 15:03:16 +0000248 CHACHA20_VALIDATE_RET( ctx != NULL );
249 CHACHA20_VALIDATE_RET( size == 0 || input != NULL );
250 CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300251
252 /* Use leftover keystream bytes, if available */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200253 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300254 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200255 output[offset] = input[offset]
256 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300257
258 ctx->keystream_bytes_used++;
259 offset++;
260 size--;
261 }
262
263 /* Process full blocks */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200264 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300265 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200266 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200267 chacha20_block( ctx->state, ctx->keystream8 );
268 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300269
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200270 for( i = 0U; i < 64U; i += 8U )
Daniel King34b822c2016-05-15 17:28:08 -0300271 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200272 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
273 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
274 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
275 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
276 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
277 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
278 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
279 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
Daniel King34b822c2016-05-15 17:28:08 -0300280 }
281
Daniel Kingb8025c52016-05-17 14:43:01 -0300282 offset += CHACHA20_BLOCK_SIZE_BYTES;
283 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300284 }
285
286 /* Last (partial) block */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200287 if( size > 0U )
Daniel King34b822c2016-05-15 17:28:08 -0300288 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200289 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200290 chacha20_block( ctx->state, ctx->keystream8 );
291 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300292
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200293 for( i = 0U; i < size; i++)
Daniel King34b822c2016-05-15 17:28:08 -0300294 {
295 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
296 }
297
298 ctx->keystream_bytes_used = size;
299
Daniel King34b822c2016-05-15 17:28:08 -0300300 }
301
Daniel Kinge6e79682016-05-24 11:16:17 -0300302 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300303}
304
Daniel King34b822c2016-05-15 17:28:08 -0300305int mbedtls_chacha20_crypt( const unsigned char key[32],
306 const unsigned char nonce[12],
307 uint32_t counter,
308 size_t data_len,
309 const unsigned char* input,
310 unsigned char* output )
311{
312 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000313 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300314
Hanno Becker305e4e42018-12-11 15:03:16 +0000315 CHACHA20_VALIDATE_RET( key != NULL );
316 CHACHA20_VALIDATE_RET( nonce != NULL );
317 CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL );
318 CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
319
Daniel King34b822c2016-05-15 17:28:08 -0300320 mbedtls_chacha20_init( &ctx );
321
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200322 ret = mbedtls_chacha20_setkey( &ctx, key );
323 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300324 goto cleanup;
325
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200326 ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
327 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300328 goto cleanup;
329
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200330 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300331
332cleanup:
333 mbedtls_chacha20_free( &ctx );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200334 return( ret );
Daniel King34b822c2016-05-15 17:28:08 -0300335}
336
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200337#endif /* !MBEDTLS_CHACHA20_ALT */
338
Daniel King34b822c2016-05-15 17:28:08 -0300339#if defined(MBEDTLS_SELF_TEST)
340
341static const unsigned char test_keys[2][32] =
342{
343 {
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 },
349 {
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, 0x01
354 }
355};
356
357static const unsigned char test_nonces[2][12] =
358{
359 {
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00
362 },
363 {
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x02
366 }
367};
368
369static const uint32_t test_counters[2] =
370{
371 0U,
372 1U
373};
374
375static const unsigned char test_input[2][375] =
376{
377 {
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
386 },
387 {
388 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
389 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
390 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
391 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
392 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
393 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
394 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
395 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
396 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
397 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
398 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
399 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
400 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
401 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
402 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
403 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
404 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
405 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
406 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
407 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
408 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
409 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
410 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
411 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
412 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
413 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
414 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
415 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
416 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
417 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
418 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
419 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
420 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
421 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
422 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
423 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
424 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
425 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
426 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
427 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
428 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
429 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
430 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
431 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
432 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
433 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
434 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
435 }
436};
437
438static const unsigned char test_output[2][375] =
439{
440 {
441 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
442 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
443 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
444 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
445 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
446 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
447 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
448 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
449 },
450 {
451 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
452 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
453 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
454 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
455 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
456 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
457 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
458 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
459 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
460 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
461 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
462 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
463 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
464 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
465 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
466 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
467 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
468 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
469 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
470 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
471 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
472 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
473 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
474 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
475 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
476 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
477 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
478 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
479 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
480 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
481 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
482 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
483 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
484 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
485 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
486 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
487 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
488 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
489 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
490 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
491 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
492 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
493 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
494 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
495 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
496 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
497 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
498 }
499};
500
501static const size_t test_lengths[2] =
502{
503 64U,
504 375U
505};
506
Ouss4e0b26872020-08-11 16:07:09 +0100507/* Make sure no other definition is already present. */
508#undef ASSERT
509
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200510#define ASSERT( cond, args ) \
511 do \
512 { \
513 if( ! ( cond ) ) \
514 { \
515 if( verbose != 0 ) \
516 mbedtls_printf args; \
517 \
518 return( -1 ); \
519 } \
520 } \
521 while( 0 )
522
Daniel King34b822c2016-05-15 17:28:08 -0300523int mbedtls_chacha20_self_test( int verbose )
524{
525 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200526 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000527 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300528
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200529 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300530 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200531 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200532 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300533
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200534 ret = mbedtls_chacha20_crypt( test_keys[i],
535 test_nonces[i],
536 test_counters[i],
537 test_lengths[i],
538 test_input[i],
539 output );
Daniel King34b822c2016-05-15 17:28:08 -0300540
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200541 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
Daniel King34b822c2016-05-15 17:28:08 -0300542
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200543 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
544 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300545
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200546 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300547 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300548 }
549
550 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300551 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300552
553 return( 0 );
554}
555
556#endif /* MBEDTLS_SELF_TEST */
557
558#endif /* !MBEDTLS_CHACHA20_C */