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