blob: acaae5b2e98d279c18cdedcd62a31efe8172584a [file] [log] [blame]
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001/**
2 * \file chacha20.c
3 *
4 * \brief ChaCha20 cipher.
5 *
6 * \author Daniel King <damaki.gh@gmail.com>
7 *
Jerome Forissier79013242021-07-28 10:24:04 +02008 * Copyright The Mbed TLS Contributors
Tom Van Eyckc1633172024-04-09 18:44:13 +02009 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander3d3b0592019-03-20 15:30:29 +010010 */
11
Jerome Forissier79013242021-07-28 10:24:04 +020012#include "common.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010013
14#if defined(MBEDTLS_CHACHA20_C)
15
16#include "mbedtls/chacha20.h"
17#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020018#include "mbedtls/error.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010019
20#include <stddef.h>
21#include <string.h>
22
Jens Wiklander3d3b0592019-03-20 15:30:29 +010023#include "mbedtls/platform.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010024
25#if !defined(MBEDTLS_CHACHA20_ALT)
26
Jens Wiklander32b31802023-10-06 16:59:46 +020027#define ROTL32(value, amount) \
28 ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
Jens Wiklander3d3b0592019-03-20 15:30:29 +010029
Jens Wiklander32b31802023-10-06 16:59:46 +020030#define CHACHA20_CTR_INDEX (12U)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010031
Jens Wiklander32b31802023-10-06 16:59:46 +020032#define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010033
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 */
Jens Wiklander32b31802023-10-06 16:59:46 +020049static 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)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010054{
55 /* a += b; d ^= a; d <<<= 16; */
56 state[a] += state[b];
57 state[d] ^= state[a];
Jens Wiklander32b31802023-10-06 16:59:46 +020058 state[d] = ROTL32(state[d], 16);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010059
60 /* c += d; b ^= c; b <<<= 12 */
61 state[c] += state[d];
62 state[b] ^= state[c];
Jens Wiklander32b31802023-10-06 16:59:46 +020063 state[b] = ROTL32(state[b], 12);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010064
65 /* a += b; d ^= a; d <<<= 8; */
66 state[a] += state[b];
67 state[d] ^= state[a];
Jens Wiklander32b31802023-10-06 16:59:46 +020068 state[d] = ROTL32(state[d], 8);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010069
70 /* c += d; b ^= c; b <<<= 7; */
71 state[c] += state[d];
72 state[b] ^= state[c];
Jens Wiklander32b31802023-10-06 16:59:46 +020073 state[b] = ROTL32(state[b], 7);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010074}
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 */
Jens Wiklander32b31802023-10-06 16:59:46 +020084static void chacha20_inner_block(uint32_t state[16])
Jens Wiklander3d3b0592019-03-20 15:30:29 +010085{
Jens Wiklander32b31802023-10-06 16:59:46 +020086 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);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010090
Jens Wiklander32b31802023-10-06 16:59:46 +020091 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);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010095}
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 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200103static void chacha20_block(const uint32_t initial_state[16],
104 unsigned char keystream[64])
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100105{
106 uint32_t working_state[16];
107 size_t i;
108
Jens Wiklander32b31802023-10-06 16:59:46 +0200109 memcpy(working_state,
110 initial_state,
111 CHACHA20_BLOCK_SIZE_BYTES);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100112
Jens Wiklander32b31802023-10-06 16:59:46 +0200113 for (i = 0U; i < 10U; i++) {
114 chacha20_inner_block(working_state);
115 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100116
Jens Wiklander32b31802023-10-06 16:59:46 +0200117 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];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100127 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
Jens Wiklander32b31802023-10-06 16:59:46 +0200134 for (i = 0U; i < 16; i++) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100135 size_t offset = i * 4U;
136
Jerome Forissier039e02d2022-08-09 17:10:15 +0200137 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100138 }
139
Jens Wiklander32b31802023-10-06 16:59:46 +0200140 mbedtls_platform_zeroize(working_state, sizeof(working_state));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100141}
142
Jens Wiklander32b31802023-10-06 16:59:46 +0200143void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100144{
Jens Wiklander32b31802023-10-06 16:59:46 +0200145 mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
146 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100147
148 /* Initially, there's no keystream bytes available */
149 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
150}
151
Jens Wiklander32b31802023-10-06 16:59:46 +0200152void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100153{
Jens Wiklander32b31802023-10-06 16:59:46 +0200154 if (ctx != NULL) {
155 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100156 }
157}
158
Jens Wiklander32b31802023-10-06 16:59:46 +0200159int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
160 const unsigned char key[32])
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100161{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100162 /* 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 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200169 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);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100177
Jens Wiklander32b31802023-10-06 16:59:46 +0200178 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100179}
180
Jens Wiklander32b31802023-10-06 16:59:46 +0200181int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
182 const unsigned char nonce[12],
183 uint32_t counter)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100184{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100185 /* Counter */
186 ctx->state[12] = counter;
187
188 /* Nonce */
Jens Wiklander32b31802023-10-06 16:59:46 +0200189 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);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100192
Jens Wiklander32b31802023-10-06 16:59:46 +0200193 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100194
195 /* Initially, there's no keystream bytes available */
196 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
197
Jens Wiklander32b31802023-10-06 16:59:46 +0200198 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100199}
200
Jens Wiklander32b31802023-10-06 16:59:46 +0200201int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
202 size_t size,
203 const unsigned char *input,
204 unsigned char *output)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100205{
206 size_t offset = 0U;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100207
208 /* Use leftover keystream bytes, if available */
Jens Wiklander32b31802023-10-06 16:59:46 +0200209 while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100210 output[offset] = input[offset]
Jens Wiklander32b31802023-10-06 16:59:46 +0200211 ^ ctx->keystream8[ctx->keystream_bytes_used];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100212
213 ctx->keystream_bytes_used++;
214 offset++;
215 size--;
216 }
217
218 /* Process full blocks */
Jens Wiklander32b31802023-10-06 16:59:46 +0200219 while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100220 /* Generate new keystream block and increment counter */
Jens Wiklander32b31802023-10-06 16:59:46 +0200221 chacha20_block(ctx->state, ctx->keystream8);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100222 ctx->state[CHACHA20_CTR_INDEX]++;
223
Jens Wiklander32b31802023-10-06 16:59:46 +0200224 mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100225
226 offset += CHACHA20_BLOCK_SIZE_BYTES;
227 size -= CHACHA20_BLOCK_SIZE_BYTES;
228 }
229
230 /* Last (partial) block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200231 if (size > 0U) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100232 /* Generate new keystream block and increment counter */
Jens Wiklander32b31802023-10-06 16:59:46 +0200233 chacha20_block(ctx->state, ctx->keystream8);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100234 ctx->state[CHACHA20_CTR_INDEX]++;
235
Jens Wiklander32b31802023-10-06 16:59:46 +0200236 mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100237
238 ctx->keystream_bytes_used = size;
239
240 }
241
Jens Wiklander32b31802023-10-06 16:59:46 +0200242 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100243}
244
Jens Wiklander32b31802023-10-06 16:59:46 +0200245int 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)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100251{
252 mbedtls_chacha20_context ctx;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200253 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100254
Jens Wiklander32b31802023-10-06 16:59:46 +0200255 mbedtls_chacha20_init(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100256
Jens Wiklander32b31802023-10-06 16:59:46 +0200257 ret = mbedtls_chacha20_setkey(&ctx, key);
258 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100259 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200260 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100261
Jens Wiklander32b31802023-10-06 16:59:46 +0200262 ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
263 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100264 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200265 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100266
Jens Wiklander32b31802023-10-06 16:59:46 +0200267 ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100268
269cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200270 mbedtls_chacha20_free(&ctx);
271 return ret;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100272}
273
274#endif /* !MBEDTLS_CHACHA20_ALT */
275
276#if defined(MBEDTLS_SELF_TEST)
277
278static 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
294static 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
306static const uint32_t test_counters[2] =
307{
308 0U,
309 1U
310};
311
312static 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
375static 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
438static const size_t test_lengths[2] =
439{
440 64U,
441 375U
442};
443
Jerome Forissier79013242021-07-28 10:24:04 +0200444/* Make sure no other definition is already present. */
445#undef ASSERT
446
Jens Wiklander32b31802023-10-06 16:59:46 +0200447#define ASSERT(cond, args) \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100448 do \
449 { \
Jens Wiklander32b31802023-10-06 16:59:46 +0200450 if (!(cond)) \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100451 { \
Jens Wiklander32b31802023-10-06 16:59:46 +0200452 if (verbose != 0) \
453 mbedtls_printf args; \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100454 \
Jens Wiklander32b31802023-10-06 16:59:46 +0200455 return -1; \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100456 } \
457 } \
Jens Wiklander32b31802023-10-06 16:59:46 +0200458 while (0)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100459
Jens Wiklander32b31802023-10-06 16:59:46 +0200460int mbedtls_chacha20_self_test(int verbose)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100461{
462 unsigned char output[381];
463 unsigned i;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200464 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100465
Jens Wiklander32b31802023-10-06 16:59:46 +0200466 for (i = 0U; i < 2U; i++) {
467 if (verbose != 0) {
468 mbedtls_printf(" ChaCha20 test %u ", i);
469 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100470
Jens Wiklander32b31802023-10-06 16:59:46 +0200471 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);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100477
Jens Wiklander32b31802023-10-06 16:59:46 +0200478 ASSERT(0 == ret, ("error code: %i\n", ret));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100479
Jens Wiklander32b31802023-10-06 16:59:46 +0200480 ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
481 ("failed (output)\n"));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100482
Jens Wiklander32b31802023-10-06 16:59:46 +0200483 if (verbose != 0) {
484 mbedtls_printf("passed\n");
485 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100486 }
487
Jens Wiklander32b31802023-10-06 16:59:46 +0200488 if (verbose != 0) {
489 mbedtls_printf("\n");
490 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100491
Jens Wiklander32b31802023-10-06 16:59:46 +0200492 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100493}
494
495#endif /* MBEDTLS_SELF_TEST */
496
497#endif /* !MBEDTLS_CHACHA20_C */