blob: f782e8c39f83fb43430904130faf69d676857dfd [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
Daniel Kinge6e79682016-05-24 11:16:17 -030058#define ROTL32( value, amount ) ( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) )
Daniel King34b822c2016-05-15 17:28:08 -030059
60#define CHACHA20_CTR_INDEX ( 12U )
61
62#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
63
Daniel King34b822c2016-05-15 17:28:08 -030064/**
65 * \brief ChaCha20 quarter round operation.
66 *
67 * The quarter round is defined as follows (from RFC 7539):
68 * 1. a += b; d ^= a; d <<<= 16;
69 * 2. c += d; b ^= c; b <<<= 12;
70 * 3. a += b; d ^= a; d <<<= 8;
71 * 4. c += d; b ^= c; b <<<= 7;
72 *
73 * \param state ChaCha20 state to modify.
74 * \param a The index of 'a' in the state.
75 * \param b The index of 'b' in the state.
76 * \param c The index of 'c' in the state.
77 * \param d The index of 'd' in the state.
78 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +020079static inline void chacha20_quarter_round( uint32_t state[16],
80 size_t a,
81 size_t b,
82 size_t c,
83 size_t d )
Daniel King34b822c2016-05-15 17:28:08 -030084{
85 /* a += b; d ^= a; d <<<= 16; */
86 state[a] += state[b];
87 state[d] ^= state[a];
88 state[d] = ROTL32( state[d], 16 );
89
90 /* c += d; b ^= c; b <<<= 12 */
91 state[c] += state[d];
92 state[b] ^= state[c];
93 state[b] = ROTL32( state[b], 12 );
94
95 /* a += b; d ^= a; d <<<= 8; */
96 state[a] += state[b];
97 state[d] ^= state[a];
98 state[d] = ROTL32( state[d], 8 );
99
100 /* c += d; b ^= c; b <<<= 7; */
101 state[c] += state[d];
102 state[b] ^= state[c];
103 state[b] = ROTL32( state[b], 7 );
104}
105
106/**
107 * \brief Perform the ChaCha20 inner block operation.
108 *
109 * This function performs two rounds: the column round and the
110 * diagonal round.
111 *
112 * \param state The ChaCha20 state to update.
113 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200114static void chacha20_inner_block( uint32_t state[16] )
Daniel King34b822c2016-05-15 17:28:08 -0300115{
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200116 chacha20_quarter_round( state, 0, 4, 8, 12 );
117 chacha20_quarter_round( state, 1, 5, 9, 13 );
118 chacha20_quarter_round( state, 2, 6, 10, 14 );
119 chacha20_quarter_round( state, 3, 7, 11, 15 );
Daniel King34b822c2016-05-15 17:28:08 -0300120
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200121 chacha20_quarter_round( state, 0, 5, 10, 15 );
122 chacha20_quarter_round( state, 1, 6, 11, 12 );
123 chacha20_quarter_round( state, 2, 7, 8, 13 );
124 chacha20_quarter_round( state, 3, 4, 9, 14 );
Daniel King34b822c2016-05-15 17:28:08 -0300125}
126
127/**
128 * \brief Generates a keystream block.
129 *
130 * \param initial_state The initial ChaCha20 state (containing the key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300131 * \param keystream Generated keystream bytes are written to this buffer.
132 */
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200133static void chacha20_block( const uint32_t initial_state[16],
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200134 unsigned char keystream[64] )
Daniel King34b822c2016-05-15 17:28:08 -0300135{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200136 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300137 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300138
Daniel Kingb8025c52016-05-17 14:43:01 -0300139 memcpy( working_state,
140 initial_state,
141 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300142
143 for ( i = 0U; i < 10U; i++ )
Manuel Pégourié-Gonnard9620f9b2018-05-24 16:52:19 +0200144 chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300145
Daniel Kingb8025c52016-05-17 14:43:01 -0300146 working_state[0] += initial_state[0];
147 working_state[1] += initial_state[1];
148 working_state[2] += initial_state[2];
149 working_state[3] += initial_state[3];
150 working_state[4] += initial_state[4];
151 working_state[5] += initial_state[5];
152 working_state[6] += initial_state[6];
153 working_state[7] += initial_state[7];
154 working_state[8] += initial_state[8];
155 working_state[9] += initial_state[9];
156 working_state[10] += initial_state[10];
157 working_state[11] += initial_state[11];
158 working_state[12] += initial_state[12];
159 working_state[13] += initial_state[13];
160 working_state[14] += initial_state[14];
161 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300162
163 for ( i = 0U; i < 16; i++ )
164 {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200165 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300166
Daniel Kinge6e79682016-05-24 11:16:17 -0300167 keystream[offset ] = (unsigned char) working_state[i];
168 keystream[offset + 1U] = (unsigned char) ( working_state[i] >> 8 );
169 keystream[offset + 2U] = (unsigned char) ( working_state[i] >> 16 );
170 keystream[offset + 3U] = (unsigned char) ( working_state[i] >> 24 );
Daniel King34b822c2016-05-15 17:28:08 -0300171 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200172
173 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
Daniel King34b822c2016-05-15 17:28:08 -0300174}
175
176void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
177{
178 if ( ctx != NULL )
179 {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200180 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200181 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Daniel King34b822c2016-05-15 17:28:08 -0300182
183 /* Initially, there's no keystream bytes available */
184 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
185 }
186}
187
188void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
189{
190 if ( ctx != NULL )
191 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200192 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300193 }
194}
195
196int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
197 const unsigned char key[32] )
198{
199 if ( ( ctx == NULL ) || ( key == NULL ) )
200 {
201 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
202 }
203
204 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200205 ctx->state[0] = 0x61707865;
206 ctx->state[1] = 0x3320646e;
207 ctx->state[2] = 0x79622d32;
208 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300209
210 /* Set key */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200211 ctx->state[4] = BYTES_TO_U32_LE( key, 0 );
212 ctx->state[5] = BYTES_TO_U32_LE( key, 4 );
213 ctx->state[6] = BYTES_TO_U32_LE( key, 8 );
214 ctx->state[7] = BYTES_TO_U32_LE( key, 12 );
215 ctx->state[8] = BYTES_TO_U32_LE( key, 16 );
216 ctx->state[9] = BYTES_TO_U32_LE( key, 20 );
217 ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
218 ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
Daniel King34b822c2016-05-15 17:28:08 -0300219
220 return( 0 );
221}
222
223int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
224 const unsigned char nonce[12],
225 uint32_t counter )
226{
227 if ( ( ctx == NULL ) || ( nonce == NULL ) )
228 {
229 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
230 }
231
232 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200233 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300234
235 /* Nonce */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200236 ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
237 ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
238 ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
Daniel King34b822c2016-05-15 17:28:08 -0300239
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200240 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200241
242 /* Initially, there's no keystream bytes available */
243 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
244
Daniel King34b822c2016-05-15 17:28:08 -0300245 return( 0 );
246}
247
Daniel Kingbd920622016-05-15 19:56:20 -0300248int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
Daniel King34b822c2016-05-15 17:28:08 -0300249 size_t size,
250 const unsigned char *input,
251 unsigned char *output )
252{
253 size_t offset = 0U;
254 size_t i;
255
Daniel Kinga310c5e2016-05-17 15:56:26 -0300256 if ( ctx == NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300257 {
258 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
259 }
Daniel Kinga310c5e2016-05-17 15:56:26 -0300260 else if ( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
261 {
262 /* input and output pointers are allowed to be NULL only if size == 0 */
263 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
264 }
Daniel King34b822c2016-05-15 17:28:08 -0300265
266 /* Use leftover keystream bytes, if available */
267 while ( ( size > 0U ) && ( ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) )
268 {
269 output[offset] = input[offset] ^ ctx->keystream8[ctx->keystream_bytes_used];
270
271 ctx->keystream_bytes_used++;
272 offset++;
273 size--;
274 }
275
276 /* Process full blocks */
277 while ( size >= CHACHA20_BLOCK_SIZE_BYTES )
278 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200279 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200280 chacha20_block( ctx->state, ctx->keystream8 );
281 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300282
283 for ( i = 0U; i < 64U; i += 8U )
284 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200285 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
286 output[offset + i + 1U ] = input[offset + i + 1U ] ^ ctx->keystream8[i + 1U ];
287 output[offset + i + 2U ] = input[offset + i + 2U ] ^ ctx->keystream8[i + 2U ];
288 output[offset + i + 3U ] = input[offset + i + 3U ] ^ ctx->keystream8[i + 3U ];
289 output[offset + i + 4U ] = input[offset + i + 4U ] ^ ctx->keystream8[i + 4U ];
290 output[offset + i + 5U ] = input[offset + i + 5U ] ^ ctx->keystream8[i + 5U ];
291 output[offset + i + 6U ] = input[offset + i + 6U ] ^ ctx->keystream8[i + 6U ];
292 output[offset + i + 7U ] = input[offset + i + 7U ] ^ ctx->keystream8[i + 7U ];
Daniel King34b822c2016-05-15 17:28:08 -0300293 }
294
Daniel Kingb8025c52016-05-17 14:43:01 -0300295 offset += CHACHA20_BLOCK_SIZE_BYTES;
296 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300297 }
298
299 /* Last (partial) block */
300 if ( size > 0U )
301 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200302 /* Generate new keystream block and increment counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200303 chacha20_block( ctx->state, ctx->keystream8 );
304 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300305
306 for ( i = 0U; i < size; i++)
307 {
308 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
309 }
310
311 ctx->keystream_bytes_used = size;
312
Daniel King34b822c2016-05-15 17:28:08 -0300313 }
314
Daniel Kinge6e79682016-05-24 11:16:17 -0300315 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300316}
317
Daniel King34b822c2016-05-15 17:28:08 -0300318int mbedtls_chacha20_crypt( const unsigned char key[32],
319 const unsigned char nonce[12],
320 uint32_t counter,
321 size_t data_len,
322 const unsigned char* input,
323 unsigned char* output )
324{
325 mbedtls_chacha20_context ctx;
326 int result;
327
328 mbedtls_chacha20_init( &ctx );
329
330 result = mbedtls_chacha20_setkey( &ctx, key );
331 if ( result != 0 )
332 goto cleanup;
333
334 result = mbedtls_chacha20_starts( &ctx, nonce, counter );
335 if ( result != 0 )
336 goto cleanup;
337
Daniel Kingbd920622016-05-15 19:56:20 -0300338 result = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300339
340cleanup:
341 mbedtls_chacha20_free( &ctx );
Daniel Kinge6e79682016-05-24 11:16:17 -0300342 return( result );
Daniel King34b822c2016-05-15 17:28:08 -0300343}
344
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200345#endif /* !MBEDTLS_CHACHA20_ALT */
346
Daniel King34b822c2016-05-15 17:28:08 -0300347#if defined(MBEDTLS_SELF_TEST)
348
349static const unsigned char test_keys[2][32] =
350{
351 {
352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
356 },
357 {
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
362 }
363};
364
365static const unsigned char test_nonces[2][12] =
366{
367 {
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0x00
370 },
371 {
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x02
374 }
375};
376
377static const uint32_t test_counters[2] =
378{
379 0U,
380 1U
381};
382
383static const unsigned char test_input[2][375] =
384{
385 {
386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 },
395 {
396 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
397 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
398 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
399 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
400 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
401 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
402 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
403 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
404 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
405 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
406 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
407 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
408 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
409 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
410 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
411 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
412 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
413 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
414 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
415 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
416 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
417 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
418 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
419 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
420 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
421 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
422 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
423 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
424 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
425 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
426 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
427 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
428 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
429 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
430 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
431 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
432 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
433 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
434 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
435 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
436 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
437 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
438 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
439 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
440 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
441 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
442 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
443 }
444};
445
446static const unsigned char test_output[2][375] =
447{
448 {
449 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
450 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
451 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
452 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
453 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
454 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
455 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
456 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
457 },
458 {
459 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
460 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
461 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
462 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
463 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
464 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
465 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
466 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
467 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
468 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
469 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
470 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
471 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
472 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
473 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
474 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
475 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
476 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
477 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
478 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
479 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
480 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
481 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
482 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
483 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
484 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
485 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
486 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
487 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
488 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
489 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
490 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
491 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
492 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
493 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
494 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
495 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
496 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
497 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
498 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
499 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
500 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
501 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
502 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
503 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
504 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
505 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
506 }
507};
508
509static const size_t test_lengths[2] =
510{
511 64U,
512 375U
513};
514
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200515#define ASSERT( cond, args ) \
516 do \
517 { \
518 if( ! ( cond ) ) \
519 { \
520 if( verbose != 0 ) \
521 mbedtls_printf args; \
522 \
523 return( -1 ); \
524 } \
525 } \
526 while( 0 )
527
Daniel King34b822c2016-05-15 17:28:08 -0300528int mbedtls_chacha20_self_test( int verbose )
529{
530 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200531 unsigned i;
Daniel King34b822c2016-05-15 17:28:08 -0300532 int result;
533
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200534 for( i = 0U; i < 2U; i++ )
Daniel King34b822c2016-05-15 17:28:08 -0300535 {
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200536 if( verbose != 0 )
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200537 mbedtls_printf( " ChaCha20 test %u ", i );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300538
Daniel King34b822c2016-05-15 17:28:08 -0300539 result = mbedtls_chacha20_crypt( test_keys[i],
540 test_nonces[i],
541 test_counters[i],
542 test_lengths[i],
543 test_input[i],
544 output );
Daniel King34b822c2016-05-15 17:28:08 -0300545
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200546 ASSERT( 0 == result, ( "error code: %i\n", result ) );
Daniel King34b822c2016-05-15 17:28:08 -0300547
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200548 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
549 ( "failed (output)\n" ) );
Daniel King34b822c2016-05-15 17:28:08 -0300550
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200551 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300552 mbedtls_printf( "passed\n" );
Daniel Kingdedf4a32016-05-18 10:07:53 -0300553 }
554
555 if( verbose != 0 )
Daniel Kingdedf4a32016-05-18 10:07:53 -0300556 mbedtls_printf( "\n" );
Daniel King34b822c2016-05-15 17:28:08 -0300557
558 return( 0 );
559}
560
561#endif /* MBEDTLS_SELF_TEST */
562
563#endif /* !MBEDTLS_CHACHA20_C */