blob: 44d1612bfec528bed29561376ac8a7336a453a58 [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
Hanno Becker305e4e42018-12-11 15:03:16 +000044/* Parameter validation macros */
45#define CHACHA20_VALIDATE_RET( cond ) \
46 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
47#define CHACHA20_VALIDATE( cond ) \
48 MBEDTLS_INTERNAL_VALIDATE( cond )
49
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020050#define ROTL32( value, amount ) \
Hanno Becker1eeca412018-10-15 12:01:35 +010051 ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030052
53#define CHACHA20_CTR_INDEX ( 12U )
54
55#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
56
Daniel King34b822c2016-05-15 17:28:08 -030057/**
58 * \brief ChaCha20 quarter round operation.
59 *
60 * The quarter round is defined as follows (from RFC 7539):
61 * 1. a += b; d ^= a; d <<<= 16;
62 * 2. c += d; b ^= c; b <<<= 12;
63 * 3. a += b; d ^= a; d <<<= 8;
64 * 4. c += d; b ^= c; b <<<= 7;
65 *
66 * \param state ChaCha20 state to modify.
67 * \param a The index of 'a' in the state.
68 * \param b The index of 'b' in the state.
69 * \param c The index of 'c' in the state.
70 * \param d The index of 'd' in the state.
71 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020072static inline void chacha20_quarter_round( uint32_t state[16],
73 size_t a,
74 size_t b,
75 size_t c,
76 size_t d )
Daniel King34b822c2016-05-15 17:28:08 -030077{
78 /* a += b; d ^= a; d <<<= 16; */
79 state[a] += state[b];
80 state[d] ^= state[a];
81 state[d] = ROTL32( state[d], 16 );
82
83 /* c += d; b ^= c; b <<<= 12 */
84 state[c] += state[d];
85 state[b] ^= state[c];
86 state[b] = ROTL32( state[b], 12 );
87
88 /* a += b; d ^= a; d <<<= 8; */
89 state[a] += state[b];
90 state[d] ^= state[a];
91 state[d] = ROTL32( state[d], 8 );
92
93 /* c += d; b ^= c; b <<<= 7; */
94 state[c] += state[d];
95 state[b] ^= state[c];
96 state[b] = ROTL32( state[b], 7 );
97}
98
99/**
100 * \brief Perform the ChaCha20 inner block operation.
101 *
102 * This function performs two rounds: the column round and the
103 * diagonal round.
104 *
105 * \param state The ChaCha20 state to update.
106 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200107static void chacha20_inner_block( uint32_t state[16] )
Daniel King34b822c2016-05-15 17:28:08 -0300108{
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200109 chacha20_quarter_round( state, 0, 4, 8, 12 );
110 chacha20_quarter_round( state, 1, 5, 9, 13 );
111 chacha20_quarter_round( state, 2, 6, 10, 14 );
112 chacha20_quarter_round( state, 3, 7, 11, 15 );
Daniel King34b822c2016-05-15 17:28:08 -0300113
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200114 chacha20_quarter_round( state, 0, 5, 10, 15 );
115 chacha20_quarter_round( state, 1, 6, 11, 12 );
116 chacha20_quarter_round( state, 2, 7, 8, 13 );
117 chacha20_quarter_round( state, 3, 4, 9, 14 );
Daniel King34b822c2016-05-15 17:28:08 -0300118}
119
120/**
121 * \brief Generates a keystream block.
122 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200123 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300124 * \param keystream Generated keystream bytes are written to this buffer.
125 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200126static void chacha20_block( const uint32_t initial_state[16],
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200127 unsigned char keystream[64] )
Daniel King34b822c2016-05-15 17:28:08 -0300128{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200129 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300130 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300131
Daniel Kingb8025c52016-05-17 14:43:01 -0300132 memcpy( working_state,
133 initial_state,
134 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300135
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200136 for( i = 0U; i < 10U; i++ )
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200137 chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300138
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200139 working_state[ 0] += initial_state[ 0];
140 working_state[ 1] += initial_state[ 1];
141 working_state[ 2] += initial_state[ 2];
142 working_state[ 3] += initial_state[ 3];
143 working_state[ 4] += initial_state[ 4];
144 working_state[ 5] += initial_state[ 5];
145 working_state[ 6] += initial_state[ 6];
146 working_state[ 7] += initial_state[ 7];
147 working_state[ 8] += initial_state[ 8];
148 working_state[ 9] += initial_state[ 9];
Daniel Kingb8025c52016-05-17 14:43:01 -0300149 working_state[10] += initial_state[10];
150 working_state[11] += initial_state[11];
151 working_state[12] += initial_state[12];
152 working_state[13] += initial_state[13];
153 working_state[14] += initial_state[14];
154 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300155
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200156 for( i = 0U; i < 16; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300157 {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200158 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300159
Joe Subbiani6627fb22021-07-16 15:02:55 +0100160 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Daniel King34b822c2016-05-15 17:28:08 -0300161 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200162
163 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
Daniel King34b822c2016-05-15 17:28:08 -0300164}
165
166void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
167{
Hanno Becker305e4e42018-12-11 15:03:16 +0000168 CHACHA20_VALIDATE( ctx != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300169
Hanno Becker305e4e42018-12-11 15:03:16 +0000170 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
171 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
172
173 /* Initially, there's no keystream bytes available */
174 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300175}
176
177void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
178{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200179 if( ctx != NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300180 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200181 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300182 }
183}
184
185int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
186 const unsigned char key[32] )
187{
Hanno Becker305e4e42018-12-11 15:03:16 +0000188 CHACHA20_VALIDATE_RET( ctx != NULL );
189 CHACHA20_VALIDATE_RET( key != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300190
191 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200192 ctx->state[0] = 0x61707865;
193 ctx->state[1] = 0x3320646e;
194 ctx->state[2] = 0x79622d32;
195 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300196
197 /* Set key */
Joe Subbiani9231d5f2021-07-07 16:56:29 +0100198 ctx->state[4] = MBEDTLS_GET_UINT32_LE( key, 0 );
199 ctx->state[5] = MBEDTLS_GET_UINT32_LE( key, 4 );
200 ctx->state[6] = MBEDTLS_GET_UINT32_LE( key, 8 );
201 ctx->state[7] = MBEDTLS_GET_UINT32_LE( key, 12 );
202 ctx->state[8] = MBEDTLS_GET_UINT32_LE( key, 16 );
203 ctx->state[9] = MBEDTLS_GET_UINT32_LE( key, 20 );
204 ctx->state[10] = MBEDTLS_GET_UINT32_LE( key, 24 );
205 ctx->state[11] = MBEDTLS_GET_UINT32_LE( key, 28 );
Daniel King34b822c2016-05-15 17:28:08 -0300206
207 return( 0 );
208}
209
210int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
211 const unsigned char nonce[12],
212 uint32_t counter )
213{
Hanno Becker305e4e42018-12-11 15:03:16 +0000214 CHACHA20_VALIDATE_RET( ctx != NULL );
215 CHACHA20_VALIDATE_RET( nonce != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300216
217 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200218 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300219
220 /* Nonce */
Joe Subbiani9231d5f2021-07-07 16:56:29 +0100221 ctx->state[13] = MBEDTLS_GET_UINT32_LE( nonce, 0 );
222 ctx->state[14] = MBEDTLS_GET_UINT32_LE( nonce, 4 );
223 ctx->state[15] = MBEDTLS_GET_UINT32_LE( nonce, 8 );
Daniel King34b822c2016-05-15 17:28:08 -0300224
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200225 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200226
227 /* Initially, there's no keystream bytes available */
228 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
229
Daniel King34b822c2016-05-15 17:28:08 -0300230 return( 0 );
231}
232
Daniel Kingbd920622016-05-15 19:56:20 -0300233int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel King34b822c2016-05-15 17:28:08 -0300234 size_t size,
235 const unsigned char *input,
236 unsigned char *output )
237{
238 size_t offset = 0U;
239 size_t i;
240
Hanno Becker305e4e42018-12-11 15:03:16 +0000241 CHACHA20_VALIDATE_RET( ctx != NULL );
242 CHACHA20_VALIDATE_RET( size == 0 || input != NULL );
243 CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300244
245 /* Use leftover keystream bytes, if available */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200246 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300247 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200248 output[offset] = input[offset]
249 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300250
251 ctx->keystream_bytes_used++;
252 offset++;
253 size--;
254 }
255
256 /* Process full blocks */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200257 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
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 < 64U; i += 8U )
Daniel King34b822c2016-05-15 17:28:08 -0300264 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200265 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
266 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
267 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
268 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
269 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
270 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
271 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
272 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
Daniel King34b822c2016-05-15 17:28:08 -0300273 }
274
Daniel Kingb8025c52016-05-17 14:43:01 -0300275 offset += CHACHA20_BLOCK_SIZE_BYTES;
276 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300277 }
278
279 /* Last (partial) block */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200280 if( size > 0U )
Daniel King34b822c2016-05-15 17:28:08 -0300281 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200282 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200283 chacha20_block( ctx->state, ctx->keystream8 );
284 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300285
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200286 for( i = 0U; i < size; i++)
Daniel King34b822c2016-05-15 17:28:08 -0300287 {
288 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
289 }
290
291 ctx->keystream_bytes_used = size;
292
Daniel King34b822c2016-05-15 17:28:08 -0300293 }
294
Daniel Kinge6e79682016-05-24 11:16:17 -0300295 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300296}
297
Daniel King34b822c2016-05-15 17:28:08 -0300298int mbedtls_chacha20_crypt( const unsigned char key[32],
299 const unsigned char nonce[12],
300 uint32_t counter,
301 size_t data_len,
302 const unsigned char* input,
303 unsigned char* output )
304{
305 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000306 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300307
Hanno Becker305e4e42018-12-11 15:03:16 +0000308 CHACHA20_VALIDATE_RET( key != NULL );
309 CHACHA20_VALIDATE_RET( nonce != NULL );
310 CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL );
311 CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
312
Daniel King34b822c2016-05-15 17:28:08 -0300313 mbedtls_chacha20_init( &ctx );
314
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200315 ret = mbedtls_chacha20_setkey( &ctx, key );
316 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300317 goto cleanup;
318
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200319 ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
320 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300321 goto cleanup;
322
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200323 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300324
325cleanup:
326 mbedtls_chacha20_free( &ctx );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200327 return( ret );
Daniel King34b822c2016-05-15 17:28:08 -0300328}
329
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200330#endif /* !MBEDTLS_CHACHA20_ALT */
331
Daniel King34b822c2016-05-15 17:28:08 -0300332#if defined(MBEDTLS_SELF_TEST)
333
334static const unsigned char test_keys[2][32] =
335{
336 {
337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 },
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, 0x01
347 }
348};
349
350static const unsigned char test_nonces[2][12] =
351{
352 {
353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354 0x00, 0x00, 0x00, 0x00
355 },
356 {
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358 0x00, 0x00, 0x00, 0x02
359 }
360};
361
362static const uint32_t test_counters[2] =
363{
364 0U,
365 1U
366};
367
368static const unsigned char test_input[2][375] =
369{
370 {
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
379 },
380 {
381 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
382 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
383 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
384 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
385 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
386 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
387 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
388 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
389 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
390 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
391 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
392 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
393 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
394 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
395 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
396 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
397 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
398 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
399 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
400 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
401 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
402 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
403 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
404 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
405 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
406 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
407 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
408 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
409 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
410 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
411 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
412 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
413 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
414 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
415 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
416 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
417 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
418 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
419 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
420 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
421 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
422 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
423 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
424 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
425 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
426 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
427 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
428 }
429};
430
431static const unsigned char test_output[2][375] =
432{
433 {
434 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
435 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
436 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
437 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
438 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
439 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
440 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
441 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
442 },
443 {
444 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
445 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
446 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
447 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
448 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
449 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
450 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
451 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
452 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
453 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
454 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
455 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
456 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
457 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
458 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
459 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
460 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
461 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
462 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
463 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
464 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
465 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
466 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
467 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
468 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
469 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
470 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
471 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
472 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
473 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
474 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
475 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
476 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
477 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
478 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
479 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
480 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
481 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
482 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
483 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
484 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
485 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
486 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
487 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
488 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
489 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
490 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
491 }
492};
493
494static const size_t test_lengths[2] =
495{
496 64U,
497 375U
498};
499
Ouss4e0b26872020-08-11 16:07:09 +0100500/* Make sure no other definition is already present. */
501#undef ASSERT
502
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200503#define ASSERT( cond, args ) \
504 do \
505 { \
506 if( ! ( cond ) ) \
507 { \
508 if( verbose != 0 ) \
509 mbedtls_printf args; \
510 \
511 return( -1 ); \
512 } \
513 } \
514 while( 0 )
515
Daniel King34b822c2016-05-15 17:28:08 -0300516int mbedtls_chacha20_self_test( int verbose )
517{
518 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200519 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000520 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300521
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200522 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300523 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200524 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200525 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300526
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200527 ret = mbedtls_chacha20_crypt( test_keys[i],
528 test_nonces[i],
529 test_counters[i],
530 test_lengths[i],
531 test_input[i],
532 output );
Daniel King34b822c2016-05-15 17:28:08 -0300533
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200534 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
Daniel King34b822c2016-05-15 17:28:08 -0300535
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200536 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
537 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300538
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200539 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300540 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300541 }
542
543 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300544 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300545
546 return( 0 );
547}
548
549#endif /* MBEDTLS_SELF_TEST */
550
551#endif /* !MBEDTLS_CHACHA20_C */