blob: 903f55f3bc0bbac94791c2e8af245cb41845ba39 [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"
Daniel King34b822c2016-05-15 17:28:08 -030036
37#include <stddef.h>
38#include <string.h>
39
40#if defined(MBEDTLS_SELF_TEST)
41#if defined(MBEDTLS_PLATFORM_C)
42#include "mbedtls/platform.h"
43#else
44#include <stdio.h>
45#define mbedtls_printf printf
46#endif /* MBEDTLS_PLATFORM_C */
47#endif /* MBEDTLS_SELF_TEST */
48
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020049#if !defined(MBEDTLS_CHACHA20_ALT)
50
Daniel Kinge6e79682016-05-24 11:16:17 -030051#define BYTES_TO_U32_LE( data, offset ) \
52 ( (uint32_t) data[offset] \
53 | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \
54 | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \
55 | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \
Daniel King34b822c2016-05-15 17:28:08 -030056 )
57
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020058#define ROTL32( value, amount ) \
59 ( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030060
61#define CHACHA20_CTR_INDEX ( 12U )
62
63#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
64
Daniel King34b822c2016-05-15 17:28:08 -030065/**
66 * \brief ChaCha20 quarter round operation.
67 *
68 * The quarter round is defined as follows (from RFC 7539):
69 * 1. a += b; d ^= a; d <<<= 16;
70 * 2. c += d; b ^= c; b <<<= 12;
71 * 3. a += b; d ^= a; d <<<= 8;
72 * 4. c += d; b ^= c; b <<<= 7;
73 *
74 * \param state ChaCha20 state to modify.
75 * \param a The index of 'a' in the state.
76 * \param b The index of 'b' in the state.
77 * \param c The index of 'c' in the state.
78 * \param d The index of 'd' in the state.
79 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020080static inline void chacha20_quarter_round( uint32_t state[16],
81 size_t a,
82 size_t b,
83 size_t c,
84 size_t d )
Daniel King34b822c2016-05-15 17:28:08 -030085{
86 /* a += b; d ^= a; d <<<= 16; */
87 state[a] += state[b];
88 state[d] ^= state[a];
89 state[d] = ROTL32( state[d], 16 );
90
91 /* c += d; b ^= c; b <<<= 12 */
92 state[c] += state[d];
93 state[b] ^= state[c];
94 state[b] = ROTL32( state[b], 12 );
95
96 /* a += b; d ^= a; d <<<= 8; */
97 state[a] += state[b];
98 state[d] ^= state[a];
99 state[d] = ROTL32( state[d], 8 );
100
101 /* c += d; b ^= c; b <<<= 7; */
102 state[c] += state[d];
103 state[b] ^= state[c];
104 state[b] = ROTL32( state[b], 7 );
105}
106
107/**
108 * \brief Perform the ChaCha20 inner block operation.
109 *
110 * This function performs two rounds: the column round and the
111 * diagonal round.
112 *
113 * \param state The ChaCha20 state to update.
114 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200115static void chacha20_inner_block( uint32_t state[16] )
Daniel King34b822c2016-05-15 17:28:08 -0300116{
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200117 chacha20_quarter_round( state, 0, 4, 8, 12 );
118 chacha20_quarter_round( state, 1, 5, 9, 13 );
119 chacha20_quarter_round( state, 2, 6, 10, 14 );
120 chacha20_quarter_round( state, 3, 7, 11, 15 );
Daniel King34b822c2016-05-15 17:28:08 -0300121
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200122 chacha20_quarter_round( state, 0, 5, 10, 15 );
123 chacha20_quarter_round( state, 1, 6, 11, 12 );
124 chacha20_quarter_round( state, 2, 7, 8, 13 );
125 chacha20_quarter_round( state, 3, 4, 9, 14 );
Daniel King34b822c2016-05-15 17:28:08 -0300126}
127
128/**
129 * \brief Generates a keystream block.
130 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200131 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300132 * \param keystream Generated keystream bytes are written to this buffer.
133 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200134static void chacha20_block( const uint32_t initial_state[16],
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200135 unsigned char keystream[64] )
Daniel King34b822c2016-05-15 17:28:08 -0300136{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200137 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300138 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300139
Daniel Kingb8025c52016-05-17 14:43:01 -0300140 memcpy( working_state,
141 initial_state,
142 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300143
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200144 for( i = 0U; i < 10U; i++ )
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200145 chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300146
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200147 working_state[ 0] += initial_state[ 0];
148 working_state[ 1] += initial_state[ 1];
149 working_state[ 2] += initial_state[ 2];
150 working_state[ 3] += initial_state[ 3];
151 working_state[ 4] += initial_state[ 4];
152 working_state[ 5] += initial_state[ 5];
153 working_state[ 6] += initial_state[ 6];
154 working_state[ 7] += initial_state[ 7];
155 working_state[ 8] += initial_state[ 8];
156 working_state[ 9] += initial_state[ 9];
Daniel Kingb8025c52016-05-17 14:43:01 -0300157 working_state[10] += initial_state[10];
158 working_state[11] += initial_state[11];
159 working_state[12] += initial_state[12];
160 working_state[13] += initial_state[13];
161 working_state[14] += initial_state[14];
162 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300163
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200164 for( i = 0U; i < 16; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300165 {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200166 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300167
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200168 keystream[offset ] = (unsigned char)( working_state[i] );
169 keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 );
170 keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 );
171 keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 );
Daniel King34b822c2016-05-15 17:28:08 -0300172 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200173
174 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
Daniel King34b822c2016-05-15 17:28:08 -0300175}
176
177void mbedtls_chacha20_init( 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é-Gonnard98fae6d2018-05-24 17:23:41 +0200181 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200182 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Daniel King34b822c2016-05-15 17:28:08 -0300183
184 /* Initially, there's no keystream bytes available */
185 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
186 }
187}
188
189void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
190{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200191 if( ctx != NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300192 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200193 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300194 }
195}
196
197int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
198 const unsigned char key[32] )
199{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200200 if( ( ctx == NULL ) || ( key == NULL ) )
Daniel King34b822c2016-05-15 17:28:08 -0300201 {
202 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
203 }
204
205 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200206 ctx->state[0] = 0x61707865;
207 ctx->state[1] = 0x3320646e;
208 ctx->state[2] = 0x79622d32;
209 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300210
211 /* Set key */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200212 ctx->state[4] = BYTES_TO_U32_LE( key, 0 );
213 ctx->state[5] = BYTES_TO_U32_LE( key, 4 );
214 ctx->state[6] = BYTES_TO_U32_LE( key, 8 );
215 ctx->state[7] = BYTES_TO_U32_LE( key, 12 );
216 ctx->state[8] = BYTES_TO_U32_LE( key, 16 );
217 ctx->state[9] = BYTES_TO_U32_LE( key, 20 );
218 ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
219 ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
Daniel King34b822c2016-05-15 17:28:08 -0300220
221 return( 0 );
222}
223
224int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
225 const unsigned char nonce[12],
226 uint32_t counter )
227{
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200228 if( ( ctx == NULL ) || ( nonce == NULL ) )
Daniel King34b822c2016-05-15 17:28:08 -0300229 {
230 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
231 }
232
233 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200234 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300235
236 /* Nonce */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200237 ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
238 ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
239 ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
Daniel King34b822c2016-05-15 17:28:08 -0300240
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200241 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200242
243 /* Initially, there's no keystream bytes available */
244 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
245
Daniel King34b822c2016-05-15 17:28:08 -0300246 return( 0 );
247}
248
Daniel Kingbd920622016-05-15 19:56:20 -0300249int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel King34b822c2016-05-15 17:28:08 -0300250 size_t size,
251 const unsigned char *input,
252 unsigned char *output )
253{
254 size_t offset = 0U;
255 size_t i;
256
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200257 if( ctx == NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300258 {
259 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
260 }
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200261 else if( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
Daniel Kinga310c5e2016-05-17 15:56:26 -0300262 {
263 /* input and output pointers are allowed to be NULL only if size == 0 */
264 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
265 }
Daniel King34b822c2016-05-15 17:28:08 -0300266
267 /* Use leftover keystream bytes, if available */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200268 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300269 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200270 output[offset] = input[offset]
271 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300272
273 ctx->keystream_bytes_used++;
274 offset++;
275 size--;
276 }
277
278 /* Process full blocks */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200279 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
Daniel King34b822c2016-05-15 17:28:08 -0300280 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200281 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200282 chacha20_block( ctx->state, ctx->keystream8 );
283 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300284
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200285 for( i = 0U; i < 64U; i += 8U )
Daniel King34b822c2016-05-15 17:28:08 -0300286 {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200287 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
288 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
289 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
290 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
291 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
292 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
293 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
294 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
Daniel King34b822c2016-05-15 17:28:08 -0300295 }
296
Daniel Kingb8025c52016-05-17 14:43:01 -0300297 offset += CHACHA20_BLOCK_SIZE_BYTES;
298 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300299 }
300
301 /* Last (partial) block */
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200302 if( size > 0U )
Daniel King34b822c2016-05-15 17:28:08 -0300303 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200304 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200305 chacha20_block( ctx->state, ctx->keystream8 );
306 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300307
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200308 for( i = 0U; i < size; i++)
Daniel King34b822c2016-05-15 17:28:08 -0300309 {
310 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
311 }
312
313 ctx->keystream_bytes_used = size;
314
Daniel King34b822c2016-05-15 17:28:08 -0300315 }
316
Daniel Kinge6e79682016-05-24 11:16:17 -0300317 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300318}
319
Daniel King34b822c2016-05-15 17:28:08 -0300320int mbedtls_chacha20_crypt( const unsigned char key[32],
321 const unsigned char nonce[12],
322 uint32_t counter,
323 size_t data_len,
324 const unsigned char* input,
325 unsigned char* output )
326{
327 mbedtls_chacha20_context ctx;
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200328 int ret;
Daniel King34b822c2016-05-15 17:28:08 -0300329
330 mbedtls_chacha20_init( &ctx );
331
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200332 ret = mbedtls_chacha20_setkey( &ctx, key );
333 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300334 goto cleanup;
335
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200336 ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
337 if( ret != 0 )
Daniel King34b822c2016-05-15 17:28:08 -0300338 goto cleanup;
339
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200340 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300341
342cleanup:
343 mbedtls_chacha20_free( &ctx );
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200344 return( ret );
Daniel King34b822c2016-05-15 17:28:08 -0300345}
346
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200347#endif /* !MBEDTLS_CHACHA20_ALT */
348
Daniel King34b822c2016-05-15 17:28:08 -0300349#if defined(MBEDTLS_SELF_TEST)
350
351static const unsigned char test_keys[2][32] =
352{
353 {
354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
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, 0x01
364 }
365};
366
367static const unsigned char test_nonces[2][12] =
368{
369 {
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00
372 },
373 {
374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x02
376 }
377};
378
379static const uint32_t test_counters[2] =
380{
381 0U,
382 1U
383};
384
385static const unsigned char test_input[2][375] =
386{
387 {
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 },
397 {
398 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
399 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
400 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
401 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
402 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
403 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
404 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
405 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
406 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
407 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
408 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
409 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
410 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
411 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
412 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
413 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
414 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
415 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
416 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
417 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
418 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
419 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
420 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
421 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
422 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
423 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
424 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
425 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
426 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
427 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
428 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
429 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
430 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
431 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
432 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
433 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
434 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
435 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
436 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
437 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
438 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
439 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
440 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
441 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
442 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
443 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
444 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
445 }
446};
447
448static const unsigned char test_output[2][375] =
449{
450 {
451 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
452 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
453 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
454 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
455 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
456 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
457 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
458 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
459 },
460 {
461 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
462 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
463 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
464 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
465 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
466 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
467 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
468 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
469 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
470 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
471 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
472 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
473 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
474 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
475 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
476 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
477 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
478 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
479 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
480 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
481 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
482 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
483 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
484 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
485 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
486 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
487 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
488 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
489 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
490 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
491 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
492 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
493 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
494 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
495 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
496 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
497 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
498 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
499 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
500 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
501 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
502 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
503 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
504 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
505 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
506 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
507 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
508 }
509};
510
511static const size_t test_lengths[2] =
512{
513 64U,
514 375U
515};
516
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200517#define ASSERT( cond, args ) \
518 do \
519 { \
520 if( ! ( cond ) ) \
521 { \
522 if( verbose != 0 ) \
523 mbedtls_printf args; \
524 \
525 return( -1 ); \
526 } \
527 } \
528 while( 0 )
529
Daniel King34b822c2016-05-15 17:28:08 -0300530int mbedtls_chacha20_self_test( int verbose )
531{
532 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200533 unsigned i;
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200534 int ret;
Daniel King34b822c2016-05-15 17:28:08 -0300535
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200536 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300537 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200538 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200539 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300540
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200541 ret = mbedtls_chacha20_crypt( test_keys[i],
542 test_nonces[i],
543 test_counters[i],
544 test_lengths[i],
545 test_input[i],
546 output );
Daniel King34b822c2016-05-15 17:28:08 -0300547
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200548 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
Daniel King34b822c2016-05-15 17:28:08 -0300549
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200550 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
551 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300552
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200553 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300554 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300555 }
556
557 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300558 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300559
560 return( 0 );
561}
562
563#endif /* MBEDTLS_SELF_TEST */
564
565#endif /* !MBEDTLS_CHACHA20_C */