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 ROTL32( value, amount ) \
58 ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
59
60 #define CHACHA20_CTR_INDEX ( 12U )
61
62 #define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
63
64 /**
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 */
chacha20_quarter_round(uint32_t state[16],size_t a,size_t b,size_t c,size_t d)79 static 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 )
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 */
chacha20_inner_block(uint32_t state[16])114 static void chacha20_inner_block( uint32_t state[16] )
115 {
116 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 );
120
121 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 );
125 }
126
127 /**
128 * \brief Generates a keystream block.
129 *
130 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
131 * \param keystream Generated keystream bytes are written to this buffer.
132 */
chacha20_block(const uint32_t initial_state[16],unsigned char keystream[64])133 static void chacha20_block( const uint32_t initial_state[16],
134 unsigned char keystream[64] )
135 {
136 uint32_t working_state[16];
137 size_t i;
138
139 memcpy( working_state,
140 initial_state,
141 CHACHA20_BLOCK_SIZE_BYTES );
142
143 for( i = 0U; i < 10U; i++ )
144 chacha20_inner_block( working_state );
145
146 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];
162
163 for( i = 0U; i < 16; i++ )
164 {
165 size_t offset = i * 4U;
166
167 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
168 }
169
170 mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
171 }
172
mbedtls_chacha20_init(mbedtls_chacha20_context * ctx)173 void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
174 {
175 CHACHA20_VALIDATE( ctx != NULL );
176
177 mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
178 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
179
180 /* Initially, there's no keystream bytes available */
181 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
182 }
183
mbedtls_chacha20_free(mbedtls_chacha20_context * ctx)184 void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
185 {
186 if( ctx != NULL )
187 {
188 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
189 }
190 }
191
mbedtls_chacha20_setkey(mbedtls_chacha20_context * ctx,const unsigned char key[32])192 int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
193 const unsigned char key[32] )
194 {
195 CHACHA20_VALIDATE_RET( ctx != NULL );
196 CHACHA20_VALIDATE_RET( key != NULL );
197
198 /* ChaCha20 constants - the string "expand 32-byte k" */
199 ctx->state[0] = 0x61707865;
200 ctx->state[1] = 0x3320646e;
201 ctx->state[2] = 0x79622d32;
202 ctx->state[3] = 0x6b206574;
203
204 /* Set key */
205 ctx->state[4] = MBEDTLS_GET_UINT32_LE( key, 0 );
206 ctx->state[5] = MBEDTLS_GET_UINT32_LE( key, 4 );
207 ctx->state[6] = MBEDTLS_GET_UINT32_LE( key, 8 );
208 ctx->state[7] = MBEDTLS_GET_UINT32_LE( key, 12 );
209 ctx->state[8] = MBEDTLS_GET_UINT32_LE( key, 16 );
210 ctx->state[9] = MBEDTLS_GET_UINT32_LE( key, 20 );
211 ctx->state[10] = MBEDTLS_GET_UINT32_LE( key, 24 );
212 ctx->state[11] = MBEDTLS_GET_UINT32_LE( key, 28 );
213
214 return( 0 );
215 }
216
mbedtls_chacha20_starts(mbedtls_chacha20_context * ctx,const unsigned char nonce[12],uint32_t counter)217 int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
218 const unsigned char nonce[12],
219 uint32_t counter )
220 {
221 CHACHA20_VALIDATE_RET( ctx != NULL );
222 CHACHA20_VALIDATE_RET( nonce != NULL );
223
224 /* Counter */
225 ctx->state[12] = counter;
226
227 /* Nonce */
228 ctx->state[13] = MBEDTLS_GET_UINT32_LE( nonce, 0 );
229 ctx->state[14] = MBEDTLS_GET_UINT32_LE( nonce, 4 );
230 ctx->state[15] = MBEDTLS_GET_UINT32_LE( nonce, 8 );
231
232 mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
233
234 /* Initially, there's no keystream bytes available */
235 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
236
237 return( 0 );
238 }
239
mbedtls_chacha20_update(mbedtls_chacha20_context * ctx,size_t size,const unsigned char * input,unsigned char * output)240 int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
241 size_t size,
242 const unsigned char *input,
243 unsigned char *output )
244 {
245 size_t offset = 0U;
246 size_t i;
247
248 CHACHA20_VALIDATE_RET( ctx != NULL );
249 CHACHA20_VALIDATE_RET( size == 0 || input != NULL );
250 CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
251
252 /* Use leftover keystream bytes, if available */
253 while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
254 {
255 output[offset] = input[offset]
256 ^ ctx->keystream8[ctx->keystream_bytes_used];
257
258 ctx->keystream_bytes_used++;
259 offset++;
260 size--;
261 }
262
263 /* Process full blocks */
264 while( size >= CHACHA20_BLOCK_SIZE_BYTES )
265 {
266 /* Generate new keystream block and increment counter */
267 chacha20_block( ctx->state, ctx->keystream8 );
268 ctx->state[CHACHA20_CTR_INDEX]++;
269
270 for( i = 0U; i < 64U; i += 8U )
271 {
272 output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
273 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
274 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
275 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
276 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
277 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
278 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
279 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
280 }
281
282 offset += CHACHA20_BLOCK_SIZE_BYTES;
283 size -= CHACHA20_BLOCK_SIZE_BYTES;
284 }
285
286 /* Last (partial) block */
287 if( size > 0U )
288 {
289 /* Generate new keystream block and increment counter */
290 chacha20_block( ctx->state, ctx->keystream8 );
291 ctx->state[CHACHA20_CTR_INDEX]++;
292
293 for( i = 0U; i < size; i++)
294 {
295 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
296 }
297
298 ctx->keystream_bytes_used = size;
299
300 }
301
302 return( 0 );
303 }
304
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)305 int mbedtls_chacha20_crypt( const unsigned char key[32],
306 const unsigned char nonce[12],
307 uint32_t counter,
308 size_t data_len,
309 const unsigned char* input,
310 unsigned char* output )
311 {
312 mbedtls_chacha20_context ctx;
313 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
314
315 CHACHA20_VALIDATE_RET( key != NULL );
316 CHACHA20_VALIDATE_RET( nonce != NULL );
317 CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL );
318 CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
319
320 mbedtls_chacha20_init( &ctx );
321
322 ret = mbedtls_chacha20_setkey( &ctx, key );
323 if( ret != 0 )
324 goto cleanup;
325
326 ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
327 if( ret != 0 )
328 goto cleanup;
329
330 ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
331
332 cleanup:
333 mbedtls_chacha20_free( &ctx );
334 return( ret );
335 }
336
337 #endif /* !MBEDTLS_CHACHA20_ALT */
338
339 #if defined(MBEDTLS_SELF_TEST)
340
341 static const unsigned char test_keys[2][32] =
342 {
343 {
344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
348 },
349 {
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
354 }
355 };
356
357 static const unsigned char test_nonces[2][12] =
358 {
359 {
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00
362 },
363 {
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x02
366 }
367 };
368
369 static const uint32_t test_counters[2] =
370 {
371 0U,
372 1U
373 };
374
375 static const unsigned char test_input[2][375] =
376 {
377 {
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
386 },
387 {
388 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
389 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
390 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
391 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
392 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
393 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
394 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
395 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
396 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
397 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
398 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
399 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
400 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
401 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
402 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
403 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
404 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
405 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
406 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
407 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
408 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
409 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
410 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
411 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
412 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
413 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
414 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
415 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
416 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
417 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
418 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
419 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
420 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
421 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
422 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
423 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
424 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
425 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
426 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
427 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
428 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
429 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
430 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
431 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
432 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
433 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
434 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
435 }
436 };
437
438 static const unsigned char test_output[2][375] =
439 {
440 {
441 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
442 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
443 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
444 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
445 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
446 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
447 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
448 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
449 },
450 {
451 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
452 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
453 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
454 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
455 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
456 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
457 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
458 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
459 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
460 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
461 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
462 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
463 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
464 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
465 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
466 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
467 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
468 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
469 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
470 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
471 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
472 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
473 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
474 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
475 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
476 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
477 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
478 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
479 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
480 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
481 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
482 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
483 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
484 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
485 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
486 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
487 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
488 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
489 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
490 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
491 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
492 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
493 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
494 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
495 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
496 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
497 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
498 }
499 };
500
501 static const size_t test_lengths[2] =
502 {
503 64U,
504 375U
505 };
506
507 /* Make sure no other definition is already present. */
508 #undef ASSERT
509
510 #define ASSERT( cond, args ) \
511 do \
512 { \
513 if( ! ( cond ) ) \
514 { \
515 if( verbose != 0 ) \
516 mbedtls_printf args; \
517 \
518 return( -1 ); \
519 } \
520 } \
521 while( 0 )
522
mbedtls_chacha20_self_test(int verbose)523 int mbedtls_chacha20_self_test( int verbose )
524 {
525 unsigned char output[381];
526 unsigned i;
527 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
528
529 for( i = 0U; i < 2U; i++ )
530 {
531 if( verbose != 0 )
532 mbedtls_printf( " ChaCha20 test %u ", i );
533
534 ret = mbedtls_chacha20_crypt( test_keys[i],
535 test_nonces[i],
536 test_counters[i],
537 test_lengths[i],
538 test_input[i],
539 output );
540
541 ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
542
543 ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
544 ( "failed (output)\n" ) );
545
546 if( verbose != 0 )
547 mbedtls_printf( "passed\n" );
548 }
549
550 if( verbose != 0 )
551 mbedtls_printf( "\n" );
552
553 return( 0 );
554 }
555
556 #endif /* MBEDTLS_SELF_TEST */
557
558 #endif /* !MBEDTLS_CHACHA20_C */
559