blob: 343b2167cd52126cebeefecee8a844d6a01c356c [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
26#if !defined(MBEDTLS_CONFIG_FILE)
27#include "mbedtls/config.h"
28#else
29#include MBEDTLS_CONFIG_FILE
30#endif
31
32#if defined(MBEDTLS_CHACHA20_C)
33
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020034#include "mbedtls/chacha20.h"
35#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000036#include "mbedtls/error.h"
Daniel King34b822c2016-05-15 17:28:08 -030037
38#include <stddef.h>
39#include <string.h>
40
41#if defined(MBEDTLS_SELF_TEST)
42#if defined(MBEDTLS_PLATFORM_C)
43#include "mbedtls/platform.h"
44#else
45#include <stdio.h>
46#define mbedtls_printf printf
47#endif /* MBEDTLS_PLATFORM_C */
48#endif /* MBEDTLS_SELF_TEST */
49
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020050#if !defined(MBEDTLS_CHACHA20_ALT)
51
Manuel Pégourié-Gonnard21a65e02018-06-07 11:54:17 +020052#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
53 !defined(inline) && !defined(__cplusplus)
54#define inline __inline
55#endif
56
Hanno Becker305e4e42018-12-11 15:03:16 +000057/* Parameter validation macros */
58#define CHACHA20_VALIDATE_RET( cond ) \
59 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
60#define CHACHA20_VALIDATE( cond ) \
61 MBEDTLS_INTERNAL_VALIDATE( cond )
62
Daniel Kinge6e79682016-05-24 11:16:17 -030063#define BYTES_TO_U32_LE( data, offset ) \
Hanno Becker1eeca412018-10-15 12:01:35 +010064 ( (uint32_t) (data)[offset] \
65 | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 ) \
66 | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 ) \
67 | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 ) \
Daniel King34b822c2016-05-15 17:28:08 -030068 )
69
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020070#define ROTL32( value, amount ) \
Hanno Becker1eeca412018-10-15 12:01:35 +010071 ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030072
73#define CHACHA20_CTR_INDEX ( 12U )
74
75#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
76
Daniel King34b822c2016-05-15 17:28:08 -030077/**
78 * \brief ChaCha20 quarter round operation.
79 *
80 * The quarter round is defined as follows (from RFC 7539):
81 * 1. a += b; d ^= a; d <<<= 16;
82 * 2. c += d; b ^= c; b <<<= 12;
83 * 3. a += b; d ^= a; d <<<= 8;
84 * 4. c += d; b ^= c; b <<<= 7;
85 *
86 * \param state ChaCha20 state to modify.
87 * \param a The index of 'a' in the state.
88 * \param b The index of 'b' in the state.
89 * \param c The index of 'c' in the state.
90 * \param d The index of 'd' in the state.
91 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020092static inline void chacha20_quarter_round( uint32_t state[16],
93 size_t a,
94 size_t b,
95 size_t c,
96 size_t d )
Daniel King34b822c2016-05-15 17:28:08 -030097{
98 /* a += b; d ^= a; d <<<= 16; */
99 state[a] += state[b];
100 state[d] ^= state[a];
101 state[d] = ROTL32( state[d], 16 );
102
103 /* c += d; b ^= c; b <<<= 12 */
104 state[c] += state[d];
105 state[b] ^= state[c];
106 state[b] = ROTL32( state[b], 12 );
107
108 /* a += b; d ^= a; d <<<= 8; */
109 state[a] += state[b];
110 state[d] ^= state[a];
111 state[d] = ROTL32( state[d], 8 );
112
113 /* c += d; b ^= c; b <<<= 7; */
114 state[c] += state[d];
115 state[b] ^= state[c];
116 state[b] = ROTL32( state[b], 7 );
117}
118
119/**
120 * \brief Perform the ChaCha20 inner block operation.
121 *
122 * This function performs two rounds: the column round and the
123 * diagonal round.
124 *
125 * \param state The ChaCha20 state to update.
126 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200127static void chacha20_inner_block( uint32_t state[16] )
Daniel King34b822c2016-05-15 17:28:08 -0300128{
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200129 chacha20_quarter_round( state, 0, 4, 8, 12 );
130 chacha20_quarter_round( state, 1, 5, 9, 13 );
131 chacha20_quarter_round( state, 2, 6, 10, 14 );
132 chacha20_quarter_round( state, 3, 7, 11, 15 );
Daniel King34b822c2016-05-15 17:28:08 -0300133
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200134 chacha20_quarter_round( state, 0, 5, 10, 15 );
135 chacha20_quarter_round( state, 1, 6, 11, 12 );
136 chacha20_quarter_round( state, 2, 7, 8, 13 );
137 chacha20_quarter_round( state, 3, 4, 9, 14 );
Daniel King34b822c2016-05-15 17:28:08 -0300138}
139
140/**
141 * \brief Generates a keystream block.
142 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200143 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300144 * \param keystream Generated keystream bytes are written to this buffer.
145 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200146static void chacha20_block( const uint32_t initial_state[16],
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200147 unsigned char keystream[64] )
Daniel King34b822c2016-05-15 17:28:08 -0300148{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200149 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300150 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300151
Daniel Kingb8025c52016-05-17 14:43:01 -0300152 memcpy( working_state,
153 initial_state,
154 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300155
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200156 for( i = 0U; i < 10U; i++ )
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200157 chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300158
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200159 working_state[ 0] += initial_state[ 0];
160 working_state[ 1] += initial_state[ 1];
161 working_state[ 2] += initial_state[ 2];
162 working_state[ 3] += initial_state[ 3];
163 working_state[ 4] += initial_state[ 4];
164 working_state[ 5] += initial_state[ 5];
165 working_state[ 6] += initial_state[ 6];
166 working_state[ 7] += initial_state[ 7];
167 working_state[ 8] += initial_state[ 8];
168 working_state[ 9] += initial_state[ 9];
Daniel Kingb8025c52016-05-17 14:43:01 -0300169 working_state[10] += initial_state[10];
170 working_state[11] += initial_state[11];
171 working_state[12] += initial_state[12];
172 working_state[13] += initial_state[13];
173 working_state[14] += initial_state[14];
174 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300175
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200176 for( i = 0U; i < 16; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300177 {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200178 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300179
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200180 keystream[offset ] = (unsigned char)( working_state[i] );
181 keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 );
182 keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 );
183 keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 );
Daniel King34b822c2016-05-15 17:28:08 -0300184 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200185
186 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
Daniel King34b822c2016-05-15 17:28:08 -0300187}
188
189void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
190{
Hanno Becker305e4e42018-12-11 15:03:16 +0000191 CHACHA20_VALIDATE( ctx != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300192
Hanno Becker305e4e42018-12-11 15:03:16 +0000193 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
194 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
195
196 /* Initially, there's no keystream bytes available */
197 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300198}
199
200void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
201{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200202 if( ctx != NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300203 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200204 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300205 }
206}
207
208int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
209 const unsigned char key[32] )
210{
Hanno Becker305e4e42018-12-11 15:03:16 +0000211 CHACHA20_VALIDATE_RET( ctx != NULL );
212 CHACHA20_VALIDATE_RET( key != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300213
214 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200215 ctx->state[0] = 0x61707865;
216 ctx->state[1] = 0x3320646e;
217 ctx->state[2] = 0x79622d32;
218 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300219
220 /* Set key */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200221 ctx->state[4] = BYTES_TO_U32_LE( key, 0 );
222 ctx->state[5] = BYTES_TO_U32_LE( key, 4 );
223 ctx->state[6] = BYTES_TO_U32_LE( key, 8 );
224 ctx->state[7] = BYTES_TO_U32_LE( key, 12 );
225 ctx->state[8] = BYTES_TO_U32_LE( key, 16 );
226 ctx->state[9] = BYTES_TO_U32_LE( key, 20 );
227 ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
228 ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
Daniel King34b822c2016-05-15 17:28:08 -0300229
230 return( 0 );
231}
232
233int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
234 const unsigned char nonce[12],
235 uint32_t counter )
236{
Hanno Becker305e4e42018-12-11 15:03:16 +0000237 CHACHA20_VALIDATE_RET( ctx != NULL );
238 CHACHA20_VALIDATE_RET( nonce != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300239
240 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200241 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300242
243 /* Nonce */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200244 ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
245 ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
246 ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
Daniel King34b822c2016-05-15 17:28:08 -0300247
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200248 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200249
250 /* Initially, there's no keystream bytes available */
251 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
252
Daniel King34b822c2016-05-15 17:28:08 -0300253 return( 0 );
254}
255
Daniel Kingbd920622016-05-15 19:56:20 -0300256int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel King34b822c2016-05-15 17:28:08 -0300257 size_t size,
258 const unsigned char *input,
259 unsigned char *output )
260{
261 size_t offset = 0U;
262 size_t i;
263
Hanno Becker305e4e42018-12-11 15:03:16 +0000264 CHACHA20_VALIDATE_RET( ctx != NULL );
265 CHACHA20_VALIDATE_RET( size == 0 || input != NULL );
266 CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
Daniel King34b822c2016-05-15 17:28:08 -0300267
268 /* Use leftover keystream bytes, if available */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200269 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300270 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200271 output[offset] = input[offset]
272 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300273
274 ctx->keystream_bytes_used++;
275 offset++;
276 size--;
277 }
278
279 /* Process full blocks */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200280 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
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 < 64U; i += 8U )
Daniel King34b822c2016-05-15 17:28:08 -0300287 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200288 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
289 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
290 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
291 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
292 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
293 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
294 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
295 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
Daniel King34b822c2016-05-15 17:28:08 -0300296 }
297
Daniel Kingb8025c52016-05-17 14:43:01 -0300298 offset += CHACHA20_BLOCK_SIZE_BYTES;
299 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300300 }
301
302 /* Last (partial) block */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200303 if( size > 0U )
Daniel King34b822c2016-05-15 17:28:08 -0300304 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200305 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200306 chacha20_block( ctx->state, ctx->keystream8 );
307 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300308
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200309 for( i = 0U; i < size; i++)
Daniel King34b822c2016-05-15 17:28:08 -0300310 {
311 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
312 }
313
314 ctx->keystream_bytes_used = size;
315
Daniel King34b822c2016-05-15 17:28:08 -0300316 }
317
Daniel Kinge6e79682016-05-24 11:16:17 -0300318 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300319}
320
Daniel King34b822c2016-05-15 17:28:08 -0300321int mbedtls_chacha20_crypt( const unsigned char key[32],
322 const unsigned char nonce[12],
323 uint32_t counter,
324 size_t data_len,
325 const unsigned char* input,
326 unsigned char* output )
327{
328 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000329 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300330
Hanno Becker305e4e42018-12-11 15:03:16 +0000331 CHACHA20_VALIDATE_RET( key != NULL );
332 CHACHA20_VALIDATE_RET( nonce != NULL );
333 CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL );
334 CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
335
Daniel King34b822c2016-05-15 17:28:08 -0300336 mbedtls_chacha20_init( &ctx );
337
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200338 ret = mbedtls_chacha20_setkey( &ctx, key );
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_starts( &ctx, nonce, counter );
343 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300344 goto cleanup;
345
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200346 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300347
348cleanup:
349 mbedtls_chacha20_free( &ctx );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200350 return( ret );
Daniel King34b822c2016-05-15 17:28:08 -0300351}
352
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200353#endif /* !MBEDTLS_CHACHA20_ALT */
354
Daniel King34b822c2016-05-15 17:28:08 -0300355#if defined(MBEDTLS_SELF_TEST)
356
357static const unsigned char test_keys[2][32] =
358{
359 {
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
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, 0x01
370 }
371};
372
373static const unsigned char test_nonces[2][12] =
374{
375 {
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00
378 },
379 {
380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381 0x00, 0x00, 0x00, 0x02
382 }
383};
384
385static const uint32_t test_counters[2] =
386{
387 0U,
388 1U
389};
390
391static const unsigned char test_input[2][375] =
392{
393 {
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
402 },
403 {
404 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
405 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
406 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
407 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
408 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
409 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
410 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
411 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
412 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
413 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
414 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
415 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
416 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
417 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
418 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
419 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
420 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
421 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
422 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
423 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
424 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
425 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
426 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
427 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
428 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
429 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
430 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
431 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
432 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
433 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
434 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
435 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
436 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
437 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
438 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
439 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
440 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
441 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
442 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
443 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
444 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
445 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
446 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
447 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
448 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
449 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
450 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
451 }
452};
453
454static const unsigned char test_output[2][375] =
455{
456 {
457 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
458 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
459 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
460 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
461 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
462 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
463 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
464 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
465 },
466 {
467 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
468 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
469 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
470 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
471 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
472 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
473 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
474 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
475 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
476 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
477 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
478 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
479 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
480 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
481 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
482 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
483 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
484 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
485 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
486 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
487 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
488 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
489 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
490 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
491 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
492 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
493 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
494 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
495 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
496 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
497 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
498 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
499 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
500 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
501 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
502 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
503 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
504 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
505 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
506 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
507 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
508 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
509 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
510 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
511 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
512 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
513 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
514 }
515};
516
517static const size_t test_lengths[2] =
518{
519 64U,
520 375U
521};
522
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200523#define ASSERT( cond, args ) \
524 do \
525 { \
526 if( ! ( cond ) ) \
527 { \
528 if( verbose != 0 ) \
529 mbedtls_printf args; \
530 \
531 return( -1 ); \
532 } \
533 } \
534 while( 0 )
535
Daniel King34b822c2016-05-15 17:28:08 -0300536int mbedtls_chacha20_self_test( int verbose )
537{
538 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200539 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000540 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300541
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200542 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300543 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200544 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200545 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300546
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200547 ret = mbedtls_chacha20_crypt( test_keys[i],
548 test_nonces[i],
549 test_counters[i],
550 test_lengths[i],
551 test_input[i],
552 output );
Daniel King34b822c2016-05-15 17:28:08 -0300553
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200554 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
Daniel King34b822c2016-05-15 17:28:08 -0300555
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200556 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
557 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300558
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200559 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300560 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300561 }
562
563 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300564 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300565
566 return( 0 );
567}
568
569#endif /* MBEDTLS_SELF_TEST */
570
571#endif /* !MBEDTLS_CHACHA20_C */