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