1 /**
2 * \file chacha20.c
3 *
4 * \brief ChaCha20 cipher.
5 *
6 * \author Daniel King <damaki.gh@gmail.com>
7 *
8 * Copyright The Mbed TLS Contributors
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
24 #include "common.h"
25
26 #if defined(MBEDTLS_CHACHA20_C)
27
28 #include "mbedtls/chacha20.h"
29 #include "mbedtls/platform_util.h"
30 #include "mbedtls/error.h"
31
32 #include <stddef.h>
33 #include <string.h>
34
35 #if defined(MBEDTLS_SELF_TEST)
36 #if defined(MBEDTLS_PLATFORM_C)
37 #include "mbedtls/platform.h"
38 #else
39 #include <stdio.h>
40 #define mbedtls_printf printf
41 #endif /* MBEDTLS_PLATFORM_C */
42 #endif /* MBEDTLS_SELF_TEST */
43
44 #if !defined(MBEDTLS_CHACHA20_ALT)
45
46 #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
47 !defined(inline) && !defined(__cplusplus)
48 #define inline __inline
49 #endif
50
51 /* Parameter validation macros */
52 #define CHACHA20_VALIDATE_RET( cond ) \
53 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
54 #define CHACHA20_VALIDATE( cond ) \
55 MBEDTLS_INTERNAL_VALIDATE( cond )
56
57 #define BYTES_TO_U32_LE( data, offset ) \
58 ( (uint32_t) (data)[offset] \
59 | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 ) \
60 | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 ) \
61 | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 ) \
62 )
63
64 #define ROTL32( value, amount ) \
65 ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
66
67 #define CHACHA20_CTR_INDEX ( 12U )
68
69 #define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
70
71 /**
72 * \brief ChaCha20 quarter round operation.
73 *
74 * The quarter round is defined as follows (from RFC 7539):
75 * 1. a += b; d ^= a; d <<<= 16;
76 * 2. c += d; b ^= c; b <<<= 12;
77 * 3. a += b; d ^= a; d <<<= 8;
78 * 4. c += d; b ^= c; b <<<= 7;
79 *
80 * \param state ChaCha20 state to modify.
81 * \param a The index of 'a' in the state.
82 * \param b The index of 'b' in the state.
83 * \param c The index of 'c' in the state.
84 * \param d The index of 'd' in the state.
85 */
chacha20_quarter_round(uint32_t state[16],size_t a,size_t b,size_t c,size_t d)86 static inline void chacha20_quarter_round( uint32_t state[16],
87 size_t a,
88 size_t b,
89 size_t c,
90 size_t d )
91 {
92 /* a += b; d ^= a; d <<<= 16; */
93 state[a] += state[b];
94 state[d] ^= state[a];
95 state[d] = ROTL32( state[d], 16 );
96
97 /* c += d; b ^= c; b <<<= 12 */
98 state[c] += state[d];
99 state[b] ^= state[c];
100 state[b] = ROTL32( state[b], 12 );
101
102 /* a += b; d ^= a; d <<<= 8; */
103 state[a] += state[b];
104 state[d] ^= state[a];
105 state[d] = ROTL32( state[d], 8 );
106
107 /* c += d; b ^= c; b <<<= 7; */
108 state[c] += state[d];
109 state[b] ^= state[c];
110 state[b] = ROTL32( state[b], 7 );
111 }
112
113 /**
114 * \brief Perform the ChaCha20 inner block operation.
115 *
116 * This function performs two rounds: the column round and the
117 * diagonal round.
118 *
119 * \param state The ChaCha20 state to update.
120 */
chacha20_inner_block(uint32_t state[16])121 static void chacha20_inner_block( uint32_t state[16] )
122 {
123 chacha20_quarter_round( state, 0, 4, 8, 12 );
124 chacha20_quarter_round( state, 1, 5, 9, 13 );
125 chacha20_quarter_round( state, 2, 6, 10, 14 );
126 chacha20_quarter_round( state, 3, 7, 11, 15 );
127
128 chacha20_quarter_round( state, 0, 5, 10, 15 );
129 chacha20_quarter_round( state, 1, 6, 11, 12 );
130 chacha20_quarter_round( state, 2, 7, 8, 13 );
131 chacha20_quarter_round( state, 3, 4, 9, 14 );
132 }
133
134 /**
135 * \brief Generates a keystream block.
136 *
137 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
138 * \param keystream Generated keystream bytes are written to this buffer.
139 */
chacha20_block(const uint32_t initial_state[16],unsigned char keystream[64])140 static void chacha20_block( const uint32_t initial_state[16],
141 unsigned char keystream[64] )
142 {
143 uint32_t working_state[16];
144 size_t i;
145
146 memcpy( working_state,
147 initial_state,
148 CHACHA20_BLOCK_SIZE_BYTES );
149
150 for( i = 0U; i < 10U; i++ )
151 chacha20_inner_block( working_state );
152
153 working_state[ 0] += initial_state[ 0];
154 working_state[ 1] += initial_state[ 1];
155 working_state[ 2] += initial_state[ 2];
156 working_state[ 3] += initial_state[ 3];
157 working_state[ 4] += initial_state[ 4];
158 working_state[ 5] += initial_state[ 5];
159 working_state[ 6] += initial_state[ 6];
160 working_state[ 7] += initial_state[ 7];
161 working_state[ 8] += initial_state[ 8];
162 working_state[ 9] += initial_state[ 9];
163 working_state[10] += initial_state[10];
164 working_state[11] += initial_state[11];
165 working_state[12] += initial_state[12];
166 working_state[13] += initial_state[13];
167 working_state[14] += initial_state[14];
168 working_state[15] += initial_state[15];
169
170 for( i = 0U; i < 16; i++ )
171 {
172 size_t offset = i * 4U;
173
174 keystream[offset ] = (unsigned char)( working_state[i] );
175 keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 );
176 keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 );
177 keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 );
178 }
179
180 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
181 }
182
mbedtls_chacha20_init(mbedtls_chacha20_context * ctx)183 void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
184 {
185 CHACHA20_VALIDATE( ctx != NULL );
186
187 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
188 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
189
190 /* Initially, there's no keystream bytes available */
191 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
192 }
193
mbedtls_chacha20_free(mbedtls_chacha20_context * ctx)194 void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
195 {
196 if( ctx != NULL )
197 {
198 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
199 }
200 }
201
mbedtls_chacha20_setkey(mbedtls_chacha20_context * ctx,const unsigned char key[32])202 int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
203 const unsigned char key[32] )
204 {
205 CHACHA20_VALIDATE_RET( ctx != NULL );
206 CHACHA20_VALIDATE_RET( key != NULL );
207
208 /* ChaCha20 constants - the string "expand 32-byte k" */
209 ctx->state[0] = 0x61707865;
210 ctx->state[1] = 0x3320646e;
211 ctx->state[2] = 0x79622d32;
212 ctx->state[3] = 0x6b206574;
213
214 /* Set key */
215 ctx->state[4] = BYTES_TO_U32_LE( key, 0 );
216 ctx->state[5] = BYTES_TO_U32_LE( key, 4 );
217 ctx->state[6] = BYTES_TO_U32_LE( key, 8 );
218 ctx->state[7] = BYTES_TO_U32_LE( key, 12 );
219 ctx->state[8] = BYTES_TO_U32_LE( key, 16 );
220 ctx->state[9] = BYTES_TO_U32_LE( key, 20 );
221 ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
222 ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
223
224 return( 0 );
225 }
226
mbedtls_chacha20_starts(mbedtls_chacha20_context * ctx,const unsigned char nonce[12],uint32_t counter)227 int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
228 const unsigned char nonce[12],
229 uint32_t counter )
230 {
231 CHACHA20_VALIDATE_RET( ctx != NULL );
232 CHACHA20_VALIDATE_RET( nonce != NULL );
233
234 /* Counter */
235 ctx->state[12] = counter;
236
237 /* Nonce */
238 ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
239 ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
240 ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
241
242 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
243
244 /* Initially, there's no keystream bytes available */
245 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
246
247 return( 0 );
248 }
249
mbedtls_chacha20_update(mbedtls_chacha20_context * ctx,size_t size,const unsigned char * input,unsigned char * output)250 int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
251 size_t size,
252 const unsigned char *input,
253 unsigned char *output )
254 {
255 size_t offset = 0U;
256 size_t i;
257
258 CHACHA20_VALIDATE_RET( ctx != NULL );
259 CHACHA20_VALIDATE_RET( size == 0 || input != NULL );
260 CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
261
262 /* Use leftover keystream bytes, if available */
263 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
264 {
265 output[offset] = input[offset]
266 ^ ctx->keystream8[ctx->keystream_bytes_used];
267
268 ctx->keystream_bytes_used++;
269 offset++;
270 size--;
271 }
272
273 /* Process full blocks */
274 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
275 {
276 /* Generate new keystream block and increment counter */
277 chacha20_block( ctx->state, ctx->keystream8 );
278 ctx->state[CHACHA20_CTR_INDEX]++;
279
280 for( i = 0U; i < 64U; i += 8U )
281 {
282 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
283 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
284 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
285 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
286 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
287 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
288 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
289 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
290 }
291
292 offset += CHACHA20_BLOCK_SIZE_BYTES;
293 size -= CHACHA20_BLOCK_SIZE_BYTES;
294 }
295
296 /* Last (partial) block */
297 if( size > 0U )
298 {
299 /* Generate new keystream block and increment counter */
300 chacha20_block( ctx->state, ctx->keystream8 );
301 ctx->state[CHACHA20_CTR_INDEX]++;
302
303 for( i = 0U; i < size; i++)
304 {
305 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
306 }
307
308 ctx->keystream_bytes_used = size;
309
310 }
311
312 return( 0 );
313 }
314
mbedtls_chacha20_crypt(const unsigned char key[32],const unsigned char nonce[12],uint32_t counter,size_t data_len,const unsigned char * input,unsigned char * output)315 int mbedtls_chacha20_crypt( const unsigned char key[32],
316 const unsigned char nonce[12],
317 uint32_t counter,
318 size_t data_len,
319 const unsigned char* input,
320 unsigned char* output )
321 {
322 mbedtls_chacha20_context ctx;
323 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
324
325 CHACHA20_VALIDATE_RET( key != NULL );
326 CHACHA20_VALIDATE_RET( nonce != NULL );
327 CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL );
328 CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
329
330 mbedtls_chacha20_init( &ctx );
331
332 ret = mbedtls_chacha20_setkey( &ctx, key );
333 if( ret != 0 )
334 goto cleanup;
335
336 ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
337 if( ret != 0 )
338 goto cleanup;
339
340 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
341
342 cleanup:
343 mbedtls_chacha20_free( &ctx );
344 return( ret );
345 }
346
347 #endif /* !MBEDTLS_CHACHA20_ALT */
348
349 #if defined(MBEDTLS_SELF_TEST)
350
351 static 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
367 static 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
379 static const uint32_t test_counters[2] =
380 {
381 0U,
382 1U
383 };
384
385 static 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
448 static 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
511 static const size_t test_lengths[2] =
512 {
513 64U,
514 375U
515 };
516
517 /* Make sure no other definition is already present. */
518 #undef ASSERT
519
520 #define ASSERT( cond, args ) \
521 do \
522 { \
523 if( ! ( cond ) ) \
524 { \
525 if( verbose != 0 ) \
526 mbedtls_printf args; \
527 \
528 return( -1 ); \
529 } \
530 } \
531 while( 0 )
532
mbedtls_chacha20_self_test(int verbose)533 int mbedtls_chacha20_self_test( int verbose )
534 {
535 unsigned char output[381];
536 unsigned i;
537 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
538
539 for( i = 0U; i < 2U; i++ )
540 {
541 if( verbose != 0 )
542 mbedtls_printf( " ChaCha20 test %u ", i );
543
544 ret = mbedtls_chacha20_crypt( test_keys[i],
545 test_nonces[i],
546 test_counters[i],
547 test_lengths[i],
548 test_input[i],
549 output );
550
551 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
552
553 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
554 ( "failed (output)\n" ) );
555
556 if( verbose != 0 )
557 mbedtls_printf( "passed\n" );
558 }
559
560 if( verbose != 0 )
561 mbedtls_printf( "\n" );
562
563 return( 0 );
564 }
565
566 #endif /* MBEDTLS_SELF_TEST */
567
568 #endif /* !MBEDTLS_CHACHA20_C */
569