• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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