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