blob: bda39b2ae13abfbe6c5d6e529010adaf8025f815 [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 *
8 * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
9 * 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.
22 *
23 * This file is part of mbed TLS (https://tls.mbed.org)
24 */
Daniel King34b822c2016-05-15 17:28:08 -030025
Gilles Peskinedb09ef62020-06-03 01:43:33 +020026#include "common.h"
Daniel King34b822c2016-05-15 17:28:08 -030027
28#if defined(MBEDTLS_CHACHA20_C)
29
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020030#include "mbedtls/chacha20.h"
31#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000032#include "mbedtls/error.h"
Daniel King34b822c2016-05-15 17:28:08 -030033
34#include <stddef.h>
35#include <string.h>
36
37#if defined(MBEDTLS_SELF_TEST)
38#if defined(MBEDTLS_PLATFORM_C)
39#include "mbedtls/platform.h"
40#else
41#include <stdio.h>
42#define mbedtls_printf printf
43#endif /* MBEDTLS_PLATFORM_C */
44#endif /* MBEDTLS_SELF_TEST */
45
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020046#if !defined(MBEDTLS_CHACHA20_ALT)
47
Manuel Pégourié-Gonnard21a65e02018-06-07 11:54:17 +020048#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
49 !defined(inline) && !defined(__cplusplus)
50#define inline __inline
51#endif
52
Hanno Becker305e4e42018-12-11 15:03:16 +000053/* Parameter validation macros */
54#define CHACHA20_VALIDATE_RET( cond ) \
55 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
56#define CHACHA20_VALIDATE( cond ) \
57 MBEDTLS_INTERNAL_VALIDATE( cond )
58
Daniel Kinge6e79682016-05-24 11:16:17 -030059#define BYTES_TO_U32_LE( data, offset ) \
Hanno Becker1eeca412018-10-15 12:01:35 +010060 ( (uint32_t) (data)[offset] \
61 | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 ) \
62 | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 ) \
63 | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 ) \
Daniel King34b822c2016-05-15 17:28:08 -030064 )
65
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020066#define ROTL32( value, amount ) \
Hanno Becker1eeca412018-10-15 12:01:35 +010067 ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030068
69#define CHACHA20_CTR_INDEX ( 12U )
70
71#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
72
Daniel King34b822c2016-05-15 17:28:08 -030073/**
74 * \brief ChaCha20 quarter round operation.
75 *
76 * The quarter round is defined as follows (from RFC 7539):
77 * 1. a += b; d ^= a; d <<<= 16;
78 * 2. c += d; b ^= c; b <<<= 12;
79 * 3. a += b; d ^= a; d <<<= 8;
80 * 4. c += d; b ^= c; b <<<= 7;
81 *
82 * \param state ChaCha20 state to modify.
83 * \param a The index of 'a' in the state.
84 * \param b The index of 'b' in the state.
85 * \param c The index of 'c' in the state.
86 * \param d The index of 'd' in the state.
87 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020088static inline void chacha20_quarter_round( uint32_t state[16],
89 size_t a,
90 size_t b,
91 size_t c,
92 size_t d )
Daniel King34b822c2016-05-15 17:28:08 -030093{
94 /* a += b; d ^= a; d <<<= 16; */
95 state[a] += state[b];
96 state[d] ^= state[a];
97 state[d] = ROTL32( state[d], 16 );
98
99 /* c += d; b ^= c; b <<<= 12 */
100 state[c] += state[d];
101 state[b] ^= state[c];
102 state[b] = ROTL32( state[b], 12 );
103
104 /* a += b; d ^= a; d <<<= 8; */
105 state[a] += state[b];
106 state[d] ^= state[a];
107 state[d] = ROTL32( state[d], 8 );
108
109 /* c += d; b ^= c; b <<<= 7; */
110 state[c] += state[d];
111 state[b] ^= state[c];
112 state[b] = ROTL32( state[b], 7 );
113}
114
115/**
116 * \brief Perform the ChaCha20 inner block operation.
117 *
118 * This function performs two rounds: the column round and the
119 * diagonal round.
120 *
121 * \param state The ChaCha20 state to update.
122 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200123static void chacha20_inner_block( uint32_t state[16] )
Daniel King34b822c2016-05-15 17:28:08 -0300124{
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200125 chacha20_quarter_round( state, 0, 4, 8, 12 );
126 chacha20_quarter_round( state, 1, 5, 9, 13 );
127 chacha20_quarter_round( state, 2, 6, 10, 14 );
128 chacha20_quarter_round( state, 3, 7, 11, 15 );
Daniel King34b822c2016-05-15 17:28:08 -0300129
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200130 chacha20_quarter_round( state, 0, 5, 10, 15 );
131 chacha20_quarter_round( state, 1, 6, 11, 12 );
132 chacha20_quarter_round( state, 2, 7, 8, 13 );
133 chacha20_quarter_round( state, 3, 4, 9, 14 );
Daniel King34b822c2016-05-15 17:28:08 -0300134}
135
136/**
137 * \brief Generates a keystream block.
138 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200139 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300140 * \param keystream Generated keystream bytes are written to this buffer.
141 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200142static void chacha20_block( const uint32_t initial_state[16],
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200143 unsigned char keystream[64] )
Daniel King34b822c2016-05-15 17:28:08 -0300144{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200145 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300146 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300147
Daniel Kingb8025c52016-05-17 14:43:01 -0300148 memcpy( working_state,
149 initial_state,
150 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300151
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200152 for( i = 0U; i < 10U; i++ )
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200153 chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300154
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200155 working_state[ 0] += initial_state[ 0];
156 working_state[ 1] += initial_state[ 1];
157 working_state[ 2] += initial_state[ 2];
158 working_state[ 3] += initial_state[ 3];
159 working_state[ 4] += initial_state[ 4];
160 working_state[ 5] += initial_state[ 5];
161 working_state[ 6] += initial_state[ 6];
162 working_state[ 7] += initial_state[ 7];
163 working_state[ 8] += initial_state[ 8];
164 working_state[ 9] += initial_state[ 9];
Daniel Kingb8025c52016-05-17 14:43:01 -0300165 working_state[10] += initial_state[10];
166 working_state[11] += initial_state[11];
167 working_state[12] += initial_state[12];
168 working_state[13] += initial_state[13];
169 working_state[14] += initial_state[14];
170 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300171
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200172 for( i = 0U; i < 16; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300173 {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200174 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300175
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200176 keystream[offset ] = (unsigned char)( working_state[i] );
177 keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 );
178 keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 );
179 keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 );
Daniel King34b822c2016-05-15 17:28:08 -0300180 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200181
182 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
Daniel King34b822c2016-05-15 17:28:08 -0300183}
184
185void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
186{
Hanno Becker305e4e42018-12-11 15:03:16 +0000187 CHACHA20_VALIDATE( ctx != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300188
Hanno Becker305e4e42018-12-11 15:03:16 +0000189 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
190 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
191
192 /* Initially, there's no keystream bytes available */
193 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300194}
195
196void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
197{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200198 if( ctx != NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300199 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200200 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300201 }
202}
203
204int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
205 const unsigned char key[32] )
206{
Hanno Becker305e4e42018-12-11 15:03:16 +0000207 CHACHA20_VALIDATE_RET( ctx != NULL );
208 CHACHA20_VALIDATE_RET( key != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300209
210 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200211 ctx->state[0] = 0x61707865;
212 ctx->state[1] = 0x3320646e;
213 ctx->state[2] = 0x79622d32;
214 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300215
216 /* Set key */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200217 ctx->state[4] = BYTES_TO_U32_LE( key, 0 );
218 ctx->state[5] = BYTES_TO_U32_LE( key, 4 );
219 ctx->state[6] = BYTES_TO_U32_LE( key, 8 );
220 ctx->state[7] = BYTES_TO_U32_LE( key, 12 );
221 ctx->state[8] = BYTES_TO_U32_LE( key, 16 );
222 ctx->state[9] = BYTES_TO_U32_LE( key, 20 );
223 ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
224 ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
Daniel King34b822c2016-05-15 17:28:08 -0300225
226 return( 0 );
227}
228
229int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
230 const unsigned char nonce[12],
231 uint32_t counter )
232{
Hanno Becker305e4e42018-12-11 15:03:16 +0000233 CHACHA20_VALIDATE_RET( ctx != NULL );
234 CHACHA20_VALIDATE_RET( nonce != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300235
236 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200237 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300238
239 /* Nonce */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200240 ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
241 ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
242 ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
Daniel King34b822c2016-05-15 17:28:08 -0300243
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200244 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200245
246 /* Initially, there's no keystream bytes available */
247 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
248
Daniel King34b822c2016-05-15 17:28:08 -0300249 return( 0 );
250}
251
Daniel Kingbd920622016-05-15 19:56:20 -0300252int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel King34b822c2016-05-15 17:28:08 -0300253 size_t size,
254 const unsigned char *input,
255 unsigned char *output )
256{
257 size_t offset = 0U;
258 size_t i;
259
Hanno Becker305e4e42018-12-11 15:03:16 +0000260 CHACHA20_VALIDATE_RET( ctx != NULL );
261 CHACHA20_VALIDATE_RET( size == 0 || input != NULL );
262 CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300263
264 /* Use leftover keystream bytes, if available */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200265 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300266 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200267 output[offset] = input[offset]
268 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300269
270 ctx->keystream_bytes_used++;
271 offset++;
272 size--;
273 }
274
275 /* Process full blocks */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200276 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300277 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200278 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200279 chacha20_block( ctx->state, ctx->keystream8 );
280 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300281
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200282 for( i = 0U; i < 64U; i += 8U )
Daniel King34b822c2016-05-15 17:28:08 -0300283 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200284 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
285 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
286 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
287 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
288 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
289 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
290 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
291 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
Daniel King34b822c2016-05-15 17:28:08 -0300292 }
293
Daniel Kingb8025c52016-05-17 14:43:01 -0300294 offset += CHACHA20_BLOCK_SIZE_BYTES;
295 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300296 }
297
298 /* Last (partial) block */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200299 if( size > 0U )
Daniel King34b822c2016-05-15 17:28:08 -0300300 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200301 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200302 chacha20_block( ctx->state, ctx->keystream8 );
303 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300304
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200305 for( i = 0U; i < size; i++)
Daniel King34b822c2016-05-15 17:28:08 -0300306 {
307 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
308 }
309
310 ctx->keystream_bytes_used = size;
311
Daniel King34b822c2016-05-15 17:28:08 -0300312 }
313
Daniel Kinge6e79682016-05-24 11:16:17 -0300314 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300315}
316
Daniel King34b822c2016-05-15 17:28:08 -0300317int mbedtls_chacha20_crypt( const unsigned char key[32],
318 const unsigned char nonce[12],
319 uint32_t counter,
320 size_t data_len,
321 const unsigned char* input,
322 unsigned char* output )
323{
324 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000325 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300326
Hanno Becker305e4e42018-12-11 15:03:16 +0000327 CHACHA20_VALIDATE_RET( key != NULL );
328 CHACHA20_VALIDATE_RET( nonce != NULL );
329 CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL );
330 CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
331
Daniel King34b822c2016-05-15 17:28:08 -0300332 mbedtls_chacha20_init( &ctx );
333
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200334 ret = mbedtls_chacha20_setkey( &ctx, key );
335 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300336 goto cleanup;
337
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200338 ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
339 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300340 goto cleanup;
341
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200342 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300343
344cleanup:
345 mbedtls_chacha20_free( &ctx );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200346 return( ret );
Daniel King34b822c2016-05-15 17:28:08 -0300347}
348
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200349#endif /* !MBEDTLS_CHACHA20_ALT */
350
Daniel King34b822c2016-05-15 17:28:08 -0300351#if defined(MBEDTLS_SELF_TEST)
352
353static const unsigned char test_keys[2][32] =
354{
355 {
356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
360 },
361 {
362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
366 }
367};
368
369static const unsigned char test_nonces[2][12] =
370{
371 {
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00
374 },
375 {
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x02
378 }
379};
380
381static const uint32_t test_counters[2] =
382{
383 0U,
384 1U
385};
386
387static const unsigned char test_input[2][375] =
388{
389 {
390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
398 },
399 {
400 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
401 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
402 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
403 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
404 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
405 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
406 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
407 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
408 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
409 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
410 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
411 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
412 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
413 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
414 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
415 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
416 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
417 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
418 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
419 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
420 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
421 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
422 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
423 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
424 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
425 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
426 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
427 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
428 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
429 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
430 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
431 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
432 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
433 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
434 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
435 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
436 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
437 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
438 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
439 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
440 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
441 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
442 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
443 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
444 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
445 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
446 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
447 }
448};
449
450static const unsigned char test_output[2][375] =
451{
452 {
453 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
454 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
455 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
456 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
457 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
458 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
459 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
460 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
461 },
462 {
463 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
464 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
465 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
466 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
467 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
468 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
469 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
470 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
471 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
472 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
473 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
474 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
475 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
476 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
477 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
478 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
479 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
480 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
481 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
482 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
483 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
484 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
485 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
486 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
487 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
488 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
489 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
490 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
491 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
492 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
493 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
494 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
495 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
496 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
497 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
498 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
499 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
500 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
501 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
502 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
503 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
504 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
505 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
506 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
507 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
508 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
509 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
510 }
511};
512
513static const size_t test_lengths[2] =
514{
515 64U,
516 375U
517};
518
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200519#define ASSERT( cond, args ) \
520 do \
521 { \
522 if( ! ( cond ) ) \
523 { \
524 if( verbose != 0 ) \
525 mbedtls_printf args; \
526 \
527 return( -1 ); \
528 } \
529 } \
530 while( 0 )
531
Daniel King34b822c2016-05-15 17:28:08 -0300532int mbedtls_chacha20_self_test( int verbose )
533{
534 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200535 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000536 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300537
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200538 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300539 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200540 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200541 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300542
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200543 ret = mbedtls_chacha20_crypt( test_keys[i],
544 test_nonces[i],
545 test_counters[i],
546 test_lengths[i],
547 test_input[i],
548 output );
Daniel King34b822c2016-05-15 17:28:08 -0300549
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200550 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
Daniel King34b822c2016-05-15 17:28:08 -0300551
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200552 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
553 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300554
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200555 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300556 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300557 }
558
559 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300560 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300561
562 return( 0 );
563}
564
565#endif /* MBEDTLS_SELF_TEST */
566
567#endif /* !MBEDTLS_CHACHA20_C */