blob: 3501837d3a1d5049b9f5eee2d5909687359bb505 [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
Gilles Peskine449bd832023-01-11 14:50:10 +010025#define ROTL32(value, amount) \
26 ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
Daniel King34b822c2016-05-15 17:28:08 -030027
Gilles Peskine449bd832023-01-11 14:50:10 +010028#define CHACHA20_CTR_INDEX (12U)
Daniel King34b822c2016-05-15 17:28:08 -030029
Gilles Peskine449bd832023-01-11 14:50:10 +010030#define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
Daniel King34b822c2016-05-15 17:28:08 -030031
Daniel King34b822c2016-05-15 17:28:08 -030032/**
33 * \brief ChaCha20 quarter round operation.
34 *
35 * The quarter round is defined as follows (from RFC 7539):
36 * 1. a += b; d ^= a; d <<<= 16;
37 * 2. c += d; b ^= c; b <<<= 12;
38 * 3. a += b; d ^= a; d <<<= 8;
39 * 4. c += d; b ^= c; b <<<= 7;
40 *
41 * \param state ChaCha20 state to modify.
42 * \param a The index of 'a' in the state.
43 * \param b The index of 'b' in the state.
44 * \param c The index of 'c' in the state.
45 * \param d The index of 'd' in the state.
46 */
Gilles Peskine449bd832023-01-11 14:50:10 +010047static inline void chacha20_quarter_round(uint32_t state[16],
48 size_t a,
49 size_t b,
50 size_t c,
51 size_t d)
Daniel King34b822c2016-05-15 17:28:08 -030052{
53 /* a += b; d ^= a; d <<<= 16; */
54 state[a] += state[b];
55 state[d] ^= state[a];
Gilles Peskine449bd832023-01-11 14:50:10 +010056 state[d] = ROTL32(state[d], 16);
Daniel King34b822c2016-05-15 17:28:08 -030057
58 /* c += d; b ^= c; b <<<= 12 */
59 state[c] += state[d];
60 state[b] ^= state[c];
Gilles Peskine449bd832023-01-11 14:50:10 +010061 state[b] = ROTL32(state[b], 12);
Daniel King34b822c2016-05-15 17:28:08 -030062
63 /* a += b; d ^= a; d <<<= 8; */
64 state[a] += state[b];
65 state[d] ^= state[a];
Gilles Peskine449bd832023-01-11 14:50:10 +010066 state[d] = ROTL32(state[d], 8);
Daniel King34b822c2016-05-15 17:28:08 -030067
68 /* c += d; b ^= c; b <<<= 7; */
69 state[c] += state[d];
70 state[b] ^= state[c];
Gilles Peskine449bd832023-01-11 14:50:10 +010071 state[b] = ROTL32(state[b], 7);
Daniel King34b822c2016-05-15 17:28:08 -030072}
73
74/**
75 * \brief Perform the ChaCha20 inner block operation.
76 *
77 * This function performs two rounds: the column round and the
78 * diagonal round.
79 *
80 * \param state The ChaCha20 state to update.
81 */
Gilles Peskine449bd832023-01-11 14:50:10 +010082static void chacha20_inner_block(uint32_t state[16])
Daniel King34b822c2016-05-15 17:28:08 -030083{
Gilles Peskine449bd832023-01-11 14:50:10 +010084 chacha20_quarter_round(state, 0, 4, 8, 12);
85 chacha20_quarter_round(state, 1, 5, 9, 13);
86 chacha20_quarter_round(state, 2, 6, 10, 14);
87 chacha20_quarter_round(state, 3, 7, 11, 15);
Daniel King34b822c2016-05-15 17:28:08 -030088
Gilles Peskine449bd832023-01-11 14:50:10 +010089 chacha20_quarter_round(state, 0, 5, 10, 15);
90 chacha20_quarter_round(state, 1, 6, 11, 12);
91 chacha20_quarter_round(state, 2, 7, 8, 13);
92 chacha20_quarter_round(state, 3, 4, 9, 14);
Daniel King34b822c2016-05-15 17:28:08 -030093}
94
95/**
96 * \brief Generates a keystream block.
97 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020098 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -030099 * \param keystream Generated keystream bytes are written to this buffer.
100 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100101static void chacha20_block(const uint32_t initial_state[16],
102 unsigned char keystream[64])
Daniel King34b822c2016-05-15 17:28:08 -0300103{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200104 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300105 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300106
Gilles Peskine449bd832023-01-11 14:50:10 +0100107 memcpy(working_state,
108 initial_state,
109 CHACHA20_BLOCK_SIZE_BYTES);
Daniel King34b822c2016-05-15 17:28:08 -0300110
Gilles Peskine449bd832023-01-11 14:50:10 +0100111 for (i = 0U; i < 10U; i++) {
112 chacha20_inner_block(working_state);
113 }
Daniel King34b822c2016-05-15 17:28:08 -0300114
Gilles Peskine449bd832023-01-11 14:50:10 +0100115 working_state[0] += initial_state[0];
116 working_state[1] += initial_state[1];
117 working_state[2] += initial_state[2];
118 working_state[3] += initial_state[3];
119 working_state[4] += initial_state[4];
120 working_state[5] += initial_state[5];
121 working_state[6] += initial_state[6];
122 working_state[7] += initial_state[7];
123 working_state[8] += initial_state[8];
124 working_state[9] += initial_state[9];
Daniel Kingb8025c52016-05-17 14:43:01 -0300125 working_state[10] += initial_state[10];
126 working_state[11] += initial_state[11];
127 working_state[12] += initial_state[12];
128 working_state[13] += initial_state[13];
129 working_state[14] += initial_state[14];
130 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300131
Gilles Peskine449bd832023-01-11 14:50:10 +0100132 for (i = 0U; i < 16; i++) {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200133 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300134
Joe Subbianib6511b02021-07-16 15:02:55 +0100135 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Daniel King34b822c2016-05-15 17:28:08 -0300136 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200137
Gilles Peskine449bd832023-01-11 14:50:10 +0100138 mbedtls_platform_zeroize(working_state, sizeof(working_state));
Daniel King34b822c2016-05-15 17:28:08 -0300139}
140
Gilles Peskine449bd832023-01-11 14:50:10 +0100141void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300142{
Gilles Peskine449bd832023-01-11 14:50:10 +0100143 mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
144 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Hanno Becker305e4e42018-12-11 15:03:16 +0000145
146 /* Initially, there's no keystream bytes available */
147 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300148}
149
Gilles Peskine449bd832023-01-11 14:50:10 +0100150void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300151{
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 if (ctx != NULL) {
153 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
Daniel King34b822c2016-05-15 17:28:08 -0300154 }
155}
156
Gilles Peskine449bd832023-01-11 14:50:10 +0100157int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
158 const unsigned char key[32])
Daniel King34b822c2016-05-15 17:28:08 -0300159{
Daniel King34b822c2016-05-15 17:28:08 -0300160 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200161 ctx->state[0] = 0x61707865;
162 ctx->state[1] = 0x3320646e;
163 ctx->state[2] = 0x79622d32;
164 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300165
166 /* Set key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100167 ctx->state[4] = MBEDTLS_GET_UINT32_LE(key, 0);
168 ctx->state[5] = MBEDTLS_GET_UINT32_LE(key, 4);
169 ctx->state[6] = MBEDTLS_GET_UINT32_LE(key, 8);
170 ctx->state[7] = MBEDTLS_GET_UINT32_LE(key, 12);
171 ctx->state[8] = MBEDTLS_GET_UINT32_LE(key, 16);
172 ctx->state[9] = MBEDTLS_GET_UINT32_LE(key, 20);
173 ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24);
174 ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28);
Daniel King34b822c2016-05-15 17:28:08 -0300175
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300177}
178
Gilles Peskine449bd832023-01-11 14:50:10 +0100179int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
180 const unsigned char nonce[12],
181 uint32_t counter)
Daniel King34b822c2016-05-15 17:28:08 -0300182{
Daniel King34b822c2016-05-15 17:28:08 -0300183 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200184 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300185
186 /* Nonce */
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0);
188 ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4);
189 ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8);
Daniel King34b822c2016-05-15 17:28:08 -0300190
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200192
193 /* Initially, there's no keystream bytes available */
194 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
195
Gilles Peskine449bd832023-01-11 14:50:10 +0100196 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300197}
198
Gilles Peskine449bd832023-01-11 14:50:10 +0100199int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
200 size_t size,
201 const unsigned char *input,
202 unsigned char *output)
Daniel King34b822c2016-05-15 17:28:08 -0300203{
204 size_t offset = 0U;
Daniel King34b822c2016-05-15 17:28:08 -0300205
Daniel King34b822c2016-05-15 17:28:08 -0300206 /* Use leftover keystream bytes, if available */
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200208 output[offset] = input[offset]
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300210
211 ctx->keystream_bytes_used++;
212 offset++;
213 size--;
214 }
215
216 /* Process full blocks */
Gilles Peskine449bd832023-01-11 14:50:10 +0100217 while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200218 /* Generate new keystream block and increment counter */
Gilles Peskine449bd832023-01-11 14:50:10 +0100219 chacha20_block(ctx->state, ctx->keystream8);
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200220 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300221
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U);
Daniel King34b822c2016-05-15 17:28:08 -0300223
Daniel Kingb8025c52016-05-17 14:43:01 -0300224 offset += CHACHA20_BLOCK_SIZE_BYTES;
225 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300226 }
227
228 /* Last (partial) block */
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 if (size > 0U) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200230 /* Generate new keystream block and increment counter */
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 chacha20_block(ctx->state, ctx->keystream8);
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200232 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300233
Gilles Peskine449bd832023-01-11 14:50:10 +0100234 mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);
Daniel King34b822c2016-05-15 17:28:08 -0300235
236 ctx->keystream_bytes_used = size;
237
Daniel King34b822c2016-05-15 17:28:08 -0300238 }
239
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300241}
242
Gilles Peskine449bd832023-01-11 14:50:10 +0100243int mbedtls_chacha20_crypt(const unsigned char key[32],
244 const unsigned char nonce[12],
245 uint32_t counter,
246 size_t data_len,
247 const unsigned char *input,
248 unsigned char *output)
Daniel King34b822c2016-05-15 17:28:08 -0300249{
250 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000251 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300252
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 mbedtls_chacha20_init(&ctx);
Daniel King34b822c2016-05-15 17:28:08 -0300254
Gilles Peskine449bd832023-01-11 14:50:10 +0100255 ret = mbedtls_chacha20_setkey(&ctx, key);
256 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300257 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100258 }
Daniel King34b822c2016-05-15 17:28:08 -0300259
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
261 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300262 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100263 }
Daniel King34b822c2016-05-15 17:28:08 -0300264
Gilles Peskine449bd832023-01-11 14:50:10 +0100265 ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
Daniel King34b822c2016-05-15 17:28:08 -0300266
267cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 mbedtls_chacha20_free(&ctx);
269 return ret;
Daniel King34b822c2016-05-15 17:28:08 -0300270}
271
272#if defined(MBEDTLS_SELF_TEST)
273
274static const unsigned char test_keys[2][32] =
275{
276 {
277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
281 },
282 {
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
287 }
288};
289
290static const unsigned char test_nonces[2][12] =
291{
292 {
293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x00
295 },
296 {
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x02
299 }
300};
301
302static const uint32_t test_counters[2] =
303{
304 0U,
305 1U
306};
307
308static const unsigned char test_input[2][375] =
309{
310 {
311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 },
320 {
321 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
322 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
323 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
324 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
325 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
326 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
327 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
328 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
329 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
330 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
331 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
332 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
333 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
334 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
335 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
336 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
337 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
338 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
339 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
340 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
341 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
342 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
343 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
344 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
345 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
346 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
347 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
348 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
349 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
350 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
351 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
352 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
353 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
354 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
355 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
356 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
357 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
358 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
359 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
360 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
361 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
362 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
363 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
364 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
365 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
366 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
367 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
368 }
369};
370
371static const unsigned char test_output[2][375] =
372{
373 {
374 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
375 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
376 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
377 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
378 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
379 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
380 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
381 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
382 },
383 {
384 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
385 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
386 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
387 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
388 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
389 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
390 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
391 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
392 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
393 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
394 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
395 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
396 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
397 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
398 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
399 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
400 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
401 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
402 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
403 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
404 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
405 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
406 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
407 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
408 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
409 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
410 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
411 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
412 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
413 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
414 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
415 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
416 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
417 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
418 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
419 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
420 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
421 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
422 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
423 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
424 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
425 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
426 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
427 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
428 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
429 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
430 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
431 }
432};
433
434static const size_t test_lengths[2] =
435{
436 64U,
437 375U
438};
439
Ouss4e0b26872020-08-11 16:07:09 +0100440/* Make sure no other definition is already present. */
441#undef ASSERT
442
Gilles Peskine449bd832023-01-11 14:50:10 +0100443#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200444 do \
445 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100446 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200447 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 if (verbose != 0) \
449 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200450 \
Gilles Peskine449bd832023-01-11 14:50:10 +0100451 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200452 } \
453 } \
Gilles Peskine449bd832023-01-11 14:50:10 +0100454 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200455
Gilles Peskine449bd832023-01-11 14:50:10 +0100456int mbedtls_chacha20_self_test(int verbose)
Daniel King34b822c2016-05-15 17:28:08 -0300457{
458 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200459 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000460 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300461
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 for (i = 0U; i < 2U; i++) {
463 if (verbose != 0) {
464 mbedtls_printf(" ChaCha20 test %u ", i);
465 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300466
Gilles Peskine449bd832023-01-11 14:50:10 +0100467 ret = mbedtls_chacha20_crypt(test_keys[i],
468 test_nonces[i],
469 test_counters[i],
470 test_lengths[i],
471 test_input[i],
472 output);
Daniel King34b822c2016-05-15 17:28:08 -0300473
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 ASSERT(0 == ret, ("error code: %i\n", ret));
Daniel King34b822c2016-05-15 17:28:08 -0300475
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
477 ("failed (output)\n"));
Daniel King34b822c2016-05-15 17:28:08 -0300478
Gilles Peskine449bd832023-01-11 14:50:10 +0100479 if (verbose != 0) {
480 mbedtls_printf("passed\n");
481 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300482 }
483
Gilles Peskine449bd832023-01-11 14:50:10 +0100484 if (verbose != 0) {
485 mbedtls_printf("\n");
486 }
Daniel King34b822c2016-05-15 17:28:08 -0300487
Gilles Peskine449bd832023-01-11 14:50:10 +0100488 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300489}
490
491#endif /* MBEDTLS_SELF_TEST */
492
493#endif /* !MBEDTLS_CHACHA20_C */