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