blob: 7f7603549e73689fb40780f6c83c6a1921e2bc7c [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 */
79static inline void mbedtls_chacha20_quarter_round( uint32_t state[16],
80 size_t a,
81 size_t b,
82 size_t c,
83 size_t d )
84{
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 */
114static void mbedtls_chacha20_inner_block( uint32_t state[16] )
115{
116 mbedtls_chacha20_quarter_round( state, 0, 4, 8, 12 );
117 mbedtls_chacha20_quarter_round( state, 1, 5, 9, 13 );
118 mbedtls_chacha20_quarter_round( state, 2, 6, 10, 14 );
119 mbedtls_chacha20_quarter_round( state, 3, 7, 11, 15 );
120
121 mbedtls_chacha20_quarter_round( state, 0, 5, 10, 15 );
122 mbedtls_chacha20_quarter_round( state, 1, 6, 11, 12 );
123 mbedtls_chacha20_quarter_round( state, 2, 7, 8, 13 );
124 mbedtls_chacha20_quarter_round( state, 3, 4, 9, 14 );
125}
126
127/**
128 * \brief Generates a keystream block.
129 *
130 * \param initial_state The initial ChaCha20 state (containing the key, nonce, counter).
131 * \param working_state This state is used as a temporary working area.
132 * \param keystream Generated keystream bytes are written to this buffer.
133 */
Daniel Kingb8025c52016-05-17 14:43:01 -0300134static void mbedtls_chacha20_block( const uint32_t initial_state[16],
135 uint32_t working_state[16],
Daniel King34b822c2016-05-15 17:28:08 -0300136 unsigned char keystream[64] )
137{
138 size_t i;
139 size_t offset;
140
Daniel Kingb8025c52016-05-17 14:43:01 -0300141 memcpy( working_state,
142 initial_state,
143 CHACHA20_BLOCK_SIZE_BYTES );
Daniel King34b822c2016-05-15 17:28:08 -0300144
145 for ( i = 0U; i < 10U; i++ )
146 {
Daniel Kingb8025c52016-05-17 14:43:01 -0300147 mbedtls_chacha20_inner_block( working_state );
Daniel King34b822c2016-05-15 17:28:08 -0300148 }
149
Daniel Kingb8025c52016-05-17 14:43:01 -0300150 working_state[0] += initial_state[0];
151 working_state[1] += initial_state[1];
152 working_state[2] += initial_state[2];
153 working_state[3] += initial_state[3];
154 working_state[4] += initial_state[4];
155 working_state[5] += initial_state[5];
156 working_state[6] += initial_state[6];
157 working_state[7] += initial_state[7];
158 working_state[8] += initial_state[8];
159 working_state[9] += initial_state[9];
160 working_state[10] += initial_state[10];
161 working_state[11] += initial_state[11];
162 working_state[12] += initial_state[12];
163 working_state[13] += initial_state[13];
164 working_state[14] += initial_state[14];
165 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300166
167 for ( i = 0U; i < 16; i++ )
168 {
169 offset = i * 4U;
170
Daniel Kinge6e79682016-05-24 11:16:17 -0300171 keystream[offset ] = (unsigned char) working_state[i];
172 keystream[offset + 1U] = (unsigned char) ( working_state[i] >> 8 );
173 keystream[offset + 2U] = (unsigned char) ( working_state[i] >> 16 );
174 keystream[offset + 3U] = (unsigned char) ( working_state[i] >> 24 );
Daniel King34b822c2016-05-15 17:28:08 -0300175 }
176}
177
178void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
179{
180 if ( ctx != NULL )
181 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200182 mbedtls_platform_zeroize( ctx->initial_state, sizeof( ctx->initial_state ) );
183 mbedtls_platform_zeroize( ctx->working_state, sizeof( ctx->working_state ) );
184 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
Daniel King34b822c2016-05-15 17:28:08 -0300185
186 /* Initially, there's no keystream bytes available */
187 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
188 }
189}
190
191void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
192{
193 if ( ctx != NULL )
194 {
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200195 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
Daniel King34b822c2016-05-15 17:28:08 -0300196 }
197}
198
199int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
200 const unsigned char key[32] )
201{
202 if ( ( ctx == NULL ) || ( key == NULL ) )
203 {
204 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
205 }
206
207 /* ChaCha20 constants - the string "expand 32-byte k" */
208 ctx->initial_state[0] = 0x61707865;
209 ctx->initial_state[1] = 0x3320646e;
210 ctx->initial_state[2] = 0x79622d32;
211 ctx->initial_state[3] = 0x6b206574;
212
213 /* Set key */
214 ctx->initial_state[4] = BYTES_TO_U32_LE( key, 0 );
215 ctx->initial_state[5] = BYTES_TO_U32_LE( key, 4 );
216 ctx->initial_state[6] = BYTES_TO_U32_LE( key, 8 );
217 ctx->initial_state[7] = BYTES_TO_U32_LE( key, 12 );
218 ctx->initial_state[8] = BYTES_TO_U32_LE( key, 16 );
219 ctx->initial_state[9] = BYTES_TO_U32_LE( key, 20 );
220 ctx->initial_state[10] = BYTES_TO_U32_LE( key, 24 );
221 ctx->initial_state[11] = BYTES_TO_U32_LE( key, 28 );
222
223 return( 0 );
224}
225
226int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
227 const unsigned char nonce[12],
228 uint32_t counter )
229{
230 if ( ( ctx == NULL ) || ( nonce == NULL ) )
231 {
232 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
233 }
234
235 /* Counter */
236 ctx->initial_state[12] = counter;
237
238 /* Nonce */
239 ctx->initial_state[13] = BYTES_TO_U32_LE( nonce, 0 );
240 ctx->initial_state[14] = BYTES_TO_U32_LE( nonce, 4 );
241 ctx->initial_state[15] = BYTES_TO_U32_LE( nonce, 8 );
242
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +0200243 mbedtls_platform_zeroize( ctx->working_state, sizeof( ctx->working_state ) );
244 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
Daniel Kinga310c5e2016-05-17 15:56:26 -0300260 if ( ctx == NULL )
Daniel King34b822c2016-05-15 17:28:08 -0300261 {
262 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
263 }
Daniel Kinga310c5e2016-05-17 15:56:26 -0300264 else if ( ( size > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
265 {
266 /* input and output pointers are allowed to be NULL only if size == 0 */
267 return( MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA );
268 }
Daniel King34b822c2016-05-15 17:28:08 -0300269
270 /* Use leftover keystream bytes, if available */
271 while ( ( size > 0U ) && ( ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) )
272 {
273 output[offset] = input[offset] ^ ctx->keystream8[ctx->keystream_bytes_used];
274
275 ctx->keystream_bytes_used++;
276 offset++;
277 size--;
278 }
279
280 /* Process full blocks */
281 while ( size >= CHACHA20_BLOCK_SIZE_BYTES )
282 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200283 /* Generate new keystream block and increment counter */
284 mbedtls_chacha20_block( ctx->initial_state, ctx->working_state, ctx->keystream8 );
285 ctx->initial_state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300286
287 for ( i = 0U; i < 64U; i += 8U )
288 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200289 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
290 output[offset + i + 1U ] = input[offset + i + 1U ] ^ ctx->keystream8[i + 1U ];
291 output[offset + i + 2U ] = input[offset + i + 2U ] ^ ctx->keystream8[i + 2U ];
292 output[offset + i + 3U ] = input[offset + i + 3U ] ^ ctx->keystream8[i + 3U ];
293 output[offset + i + 4U ] = input[offset + i + 4U ] ^ ctx->keystream8[i + 4U ];
294 output[offset + i + 5U ] = input[offset + i + 5U ] ^ ctx->keystream8[i + 5U ];
295 output[offset + i + 6U ] = input[offset + i + 6U ] ^ ctx->keystream8[i + 6U ];
296 output[offset + i + 7U ] = input[offset + i + 7U ] ^ ctx->keystream8[i + 7U ];
Daniel King34b822c2016-05-15 17:28:08 -0300297 }
298
Daniel Kingb8025c52016-05-17 14:43:01 -0300299 offset += CHACHA20_BLOCK_SIZE_BYTES;
300 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300301 }
302
303 /* Last (partial) block */
304 if ( size > 0U )
305 {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200306 /* Generate new keystream block and increment counter */
Daniel Kingb8025c52016-05-17 14:43:01 -0300307 mbedtls_chacha20_block( ctx->initial_state, ctx->working_state, ctx->keystream8 );
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200308 ctx->initial_state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300309
310 for ( i = 0U; i < size; i++)
311 {
312 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
313 }
314
315 ctx->keystream_bytes_used = size;
316
Daniel King34b822c2016-05-15 17:28:08 -0300317 }
318
Daniel Kinge6e79682016-05-24 11:16:17 -0300319 return( 0 );
Daniel King34b822c2016-05-15 17:28:08 -0300320}
321
Daniel King34b822c2016-05-15 17:28:08 -0300322int mbedtls_chacha20_crypt( const unsigned char key[32],
323 const unsigned char nonce[12],
324 uint32_t counter,
325 size_t data_len,
326 const unsigned char* input,
327 unsigned char* output )
328{
329 mbedtls_chacha20_context ctx;
330 int result;
331
332 mbedtls_chacha20_init( &ctx );
333
334 result = mbedtls_chacha20_setkey( &ctx, key );
335 if ( result != 0 )
336 goto cleanup;
337
338 result = mbedtls_chacha20_starts( &ctx, nonce, counter );
339 if ( result != 0 )
340 goto cleanup;
341
Daniel Kingbd920622016-05-15 19:56:20 -0300342 result = mbedtls_chacha20_update( &ctx, data_len, input, output );
Daniel King34b822c2016-05-15 17:28:08 -0300343
344cleanup:
345 mbedtls_chacha20_free( &ctx );
Daniel Kinge6e79682016-05-24 11:16:17 -0300346 return( result );
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;
Daniel King34b822c2016-05-15 17:28:08 -0300536 int result;
537
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
Daniel King34b822c2016-05-15 17:28:08 -0300543 result = 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é-Gonnardc0dfcd42018-05-10 11:42:07 +0200550 ASSERT( 0 == result, ( "error code: %i\n", result ) );
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 */