blob: acaae5b2e98d279c18cdedcd62a31efe8172584a [file] [log] [blame]
Daniel King34b822c2016-05-15 17:28:08 -03001/**
2 * \file chacha20.c
3 *
4 * \brief ChaCha20 cipher.
5 *
6 * \author Daniel King <damaki.gh@gmail.com>
7 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02008 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00009 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Daniel King34b822c2016-05-15 17:28:08 -030010 */
Daniel King34b822c2016-05-15 17:28:08 -030011
Gilles Peskinedb09ef62020-06-03 01:43:33 +020012#include "common.h"
Daniel King34b822c2016-05-15 17:28:08 -030013
14#if defined(MBEDTLS_CHACHA20_C)
15
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020016#include "mbedtls/chacha20.h"
17#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000018#include "mbedtls/error.h"
Daniel King34b822c2016-05-15 17:28:08 -030019
20#include <stddef.h>
21#include <string.h>
22
Daniel King34b822c2016-05-15 17:28:08 -030023#include "mbedtls/platform.h"
Daniel King34b822c2016-05-15 17:28:08 -030024
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020025#if !defined(MBEDTLS_CHACHA20_ALT)
26
Gilles Peskine449bd832023-01-11 14:50:10 +010027#define ROTL32(value, amount) \
28 ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
Daniel King34b822c2016-05-15 17:28:08 -030029
Gilles Peskine449bd832023-01-11 14:50:10 +010030#define CHACHA20_CTR_INDEX (12U)
Daniel King34b822c2016-05-15 17:28:08 -030031
Gilles Peskine449bd832023-01-11 14:50:10 +010032#define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
Daniel King34b822c2016-05-15 17:28:08 -030033
Daniel King34b822c2016-05-15 17:28:08 -030034/**
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 */
Gilles Peskine449bd832023-01-11 14:50:10 +010049static 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)
Daniel King34b822c2016-05-15 17:28:08 -030054{
55 /* a += b; d ^= a; d <<<= 16; */
56 state[a] += state[b];
57 state[d] ^= state[a];
Gilles Peskine449bd832023-01-11 14:50:10 +010058 state[d] = ROTL32(state[d], 16);
Daniel King34b822c2016-05-15 17:28:08 -030059
60 /* c += d; b ^= c; b <<<= 12 */
61 state[c] += state[d];
62 state[b] ^= state[c];
Gilles Peskine449bd832023-01-11 14:50:10 +010063 state[b] = ROTL32(state[b], 12);
Daniel King34b822c2016-05-15 17:28:08 -030064
65 /* a += b; d ^= a; d <<<= 8; */
66 state[a] += state[b];
67 state[d] ^= state[a];
Gilles Peskine449bd832023-01-11 14:50:10 +010068 state[d] = ROTL32(state[d], 8);
Daniel King34b822c2016-05-15 17:28:08 -030069
70 /* c += d; b ^= c; b <<<= 7; */
71 state[c] += state[d];
72 state[b] ^= state[c];
Gilles Peskine449bd832023-01-11 14:50:10 +010073 state[b] = ROTL32(state[b], 7);
Daniel King34b822c2016-05-15 17:28:08 -030074}
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 */
Gilles Peskine449bd832023-01-11 14:50:10 +010084static void chacha20_inner_block(uint32_t state[16])
Daniel King34b822c2016-05-15 17:28:08 -030085{
Gilles Peskine449bd832023-01-11 14:50:10 +010086 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);
Daniel King34b822c2016-05-15 17:28:08 -030090
Gilles Peskine449bd832023-01-11 14:50:10 +010091 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);
Daniel King34b822c2016-05-15 17:28:08 -030095}
96
97/**
98 * \brief Generates a keystream block.
99 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200100 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300101 * \param keystream Generated keystream bytes are written to this buffer.
102 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100103static void chacha20_block(const uint32_t initial_state[16],
104 unsigned char keystream[64])
Daniel King34b822c2016-05-15 17:28:08 -0300105{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200106 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300107 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300108
Gilles Peskine449bd832023-01-11 14:50:10 +0100109 memcpy(working_state,
110 initial_state,
111 CHACHA20_BLOCK_SIZE_BYTES);
Daniel King34b822c2016-05-15 17:28:08 -0300112
Gilles Peskine449bd832023-01-11 14:50:10 +0100113 for (i = 0U; i < 10U; i++) {
114 chacha20_inner_block(working_state);
115 }
Daniel King34b822c2016-05-15 17:28:08 -0300116
Gilles Peskine449bd832023-01-11 14:50:10 +0100117 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];
Daniel Kingb8025c52016-05-17 14:43:01 -0300127 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];
Daniel King34b822c2016-05-15 17:28:08 -0300133
Gilles Peskine449bd832023-01-11 14:50:10 +0100134 for (i = 0U; i < 16; i++) {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200135 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300136
Joe Subbianib6511b02021-07-16 15:02:55 +0100137 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Daniel King34b822c2016-05-15 17:28:08 -0300138 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200139
Gilles Peskine449bd832023-01-11 14:50:10 +0100140 mbedtls_platform_zeroize(working_state, sizeof(working_state));
Daniel King34b822c2016-05-15 17:28:08 -0300141}
142
Gilles Peskine449bd832023-01-11 14:50:10 +0100143void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300144{
Gilles Peskine449bd832023-01-11 14:50:10 +0100145 mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
146 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Hanno Becker305e4e42018-12-11 15:03:16 +0000147
148 /* Initially, there's no keystream bytes available */
149 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300150}
151
Gilles Peskine449bd832023-01-11 14:50:10 +0100152void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300153{
Gilles Peskine449bd832023-01-11 14:50:10 +0100154 if (ctx != NULL) {
155 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
Daniel King34b822c2016-05-15 17:28:08 -0300156 }
157}
158
Gilles Peskine449bd832023-01-11 14:50:10 +0100159int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
160 const unsigned char key[32])
Daniel King34b822c2016-05-15 17:28:08 -0300161{
Daniel King34b822c2016-05-15 17:28:08 -0300162 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200163 ctx->state[0] = 0x61707865;
164 ctx->state[1] = 0x3320646e;
165 ctx->state[2] = 0x79622d32;
166 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300167
168 /* Set key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100169 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);
Daniel King34b822c2016-05-15 17:28:08 -0300177
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300179}
180
Gilles Peskine449bd832023-01-11 14:50:10 +0100181int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
182 const unsigned char nonce[12],
183 uint32_t counter)
Daniel King34b822c2016-05-15 17:28:08 -0300184{
Daniel King34b822c2016-05-15 17:28:08 -0300185 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200186 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300187
188 /* Nonce */
Gilles Peskine449bd832023-01-11 14:50:10 +0100189 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);
Daniel King34b822c2016-05-15 17:28:08 -0300192
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200194
195 /* Initially, there's no keystream bytes available */
196 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
197
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300199}
200
Gilles Peskine449bd832023-01-11 14:50:10 +0100201int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
202 size_t size,
203 const unsigned char *input,
204 unsigned char *output)
Daniel King34b822c2016-05-15 17:28:08 -0300205{
206 size_t offset = 0U;
Daniel King34b822c2016-05-15 17:28:08 -0300207
Daniel King34b822c2016-05-15 17:28:08 -0300208 /* Use leftover keystream bytes, if available */
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200210 output[offset] = input[offset]
Gilles Peskine449bd832023-01-11 14:50:10 +0100211 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300212
213 ctx->keystream_bytes_used++;
214 offset++;
215 size--;
216 }
217
218 /* Process full blocks */
Gilles Peskine449bd832023-01-11 14:50:10 +0100219 while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200220 /* Generate new keystream block and increment counter */
Gilles Peskine449bd832023-01-11 14:50:10 +0100221 chacha20_block(ctx->state, ctx->keystream8);
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200222 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300223
Gilles Peskine449bd832023-01-11 14:50:10 +0100224 mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U);
Daniel King34b822c2016-05-15 17:28:08 -0300225
Daniel Kingb8025c52016-05-17 14:43:01 -0300226 offset += CHACHA20_BLOCK_SIZE_BYTES;
227 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300228 }
229
230 /* Last (partial) block */
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 if (size > 0U) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200232 /* Generate new keystream block and increment counter */
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 chacha20_block(ctx->state, ctx->keystream8);
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200234 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300235
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);
Daniel King34b822c2016-05-15 17:28:08 -0300237
238 ctx->keystream_bytes_used = size;
239
Daniel King34b822c2016-05-15 17:28:08 -0300240 }
241
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300243}
244
Gilles Peskine449bd832023-01-11 14:50:10 +0100245int 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)
Daniel King34b822c2016-05-15 17:28:08 -0300251{
252 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000253 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300254
Gilles Peskine449bd832023-01-11 14:50:10 +0100255 mbedtls_chacha20_init(&ctx);
Daniel King34b822c2016-05-15 17:28:08 -0300256
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 ret = mbedtls_chacha20_setkey(&ctx, key);
258 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300259 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 }
Daniel King34b822c2016-05-15 17:28:08 -0300261
Gilles Peskine449bd832023-01-11 14:50:10 +0100262 ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
263 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300264 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100265 }
Daniel King34b822c2016-05-15 17:28:08 -0300266
Gilles Peskine449bd832023-01-11 14:50:10 +0100267 ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
Daniel King34b822c2016-05-15 17:28:08 -0300268
269cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 mbedtls_chacha20_free(&ctx);
271 return ret;
Daniel King34b822c2016-05-15 17:28:08 -0300272}
273
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200274#endif /* !MBEDTLS_CHACHA20_ALT */
275
Daniel King34b822c2016-05-15 17:28:08 -0300276#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
Ouss4e0b26872020-08-11 16:07:09 +0100444/* Make sure no other definition is already present. */
445#undef ASSERT
446
Gilles Peskine449bd832023-01-11 14:50:10 +0100447#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200448 do \
449 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200451 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 if (verbose != 0) \
453 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200454 \
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200456 } \
457 } \
Gilles Peskine449bd832023-01-11 14:50:10 +0100458 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200459
Gilles Peskine449bd832023-01-11 14:50:10 +0100460int mbedtls_chacha20_self_test(int verbose)
Daniel King34b822c2016-05-15 17:28:08 -0300461{
462 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200463 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000464 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300465
Gilles Peskine449bd832023-01-11 14:50:10 +0100466 for (i = 0U; i < 2U; i++) {
467 if (verbose != 0) {
468 mbedtls_printf(" ChaCha20 test %u ", i);
469 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300470
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 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);
Daniel King34b822c2016-05-15 17:28:08 -0300477
Gilles Peskine449bd832023-01-11 14:50:10 +0100478 ASSERT(0 == ret, ("error code: %i\n", ret));
Daniel King34b822c2016-05-15 17:28:08 -0300479
Gilles Peskine449bd832023-01-11 14:50:10 +0100480 ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
481 ("failed (output)\n"));
Daniel King34b822c2016-05-15 17:28:08 -0300482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 if (verbose != 0) {
484 mbedtls_printf("passed\n");
485 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300486 }
487
Gilles Peskine449bd832023-01-11 14:50:10 +0100488 if (verbose != 0) {
489 mbedtls_printf("\n");
490 }
Daniel King34b822c2016-05-15 17:28:08 -0300491
Gilles Peskine449bd832023-01-11 14:50:10 +0100492 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300493}
494
495#endif /* MBEDTLS_SELF_TEST */
496
497#endif /* !MBEDTLS_CHACHA20_C */