blob: 82b7b1d89f46becb9b6f162ba9eedc0554b8afba [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 Rodgman7ff79652023-11-03 12:04:52 +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
Hanno Becker305e4e42018-12-11 15:03:16 +000027/* Parameter validation macros */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010028#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)
Hanno Becker305e4e42018-12-11 15:03:16 +000032
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010033#define ROTL32(value, amount) \
34 ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
Daniel King34b822c2016-05-15 17:28:08 -030035
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010036#define CHACHA20_CTR_INDEX (12U)
Daniel King34b822c2016-05-15 17:28:08 -030037
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010038#define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
Daniel King34b822c2016-05-15 17:28:08 -030039
Daniel King34b822c2016-05-15 17:28:08 -030040/**
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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010055static 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)
Daniel King34b822c2016-05-15 17:28:08 -030060{
61 /* a += b; d ^= a; d <<<= 16; */
62 state[a] += state[b];
63 state[d] ^= state[a];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010064 state[d] = ROTL32(state[d], 16);
Daniel King34b822c2016-05-15 17:28:08 -030065
66 /* c += d; b ^= c; b <<<= 12 */
67 state[c] += state[d];
68 state[b] ^= state[c];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010069 state[b] = ROTL32(state[b], 12);
Daniel King34b822c2016-05-15 17:28:08 -030070
71 /* a += b; d ^= a; d <<<= 8; */
72 state[a] += state[b];
73 state[d] ^= state[a];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010074 state[d] = ROTL32(state[d], 8);
Daniel King34b822c2016-05-15 17:28:08 -030075
76 /* c += d; b ^= c; b <<<= 7; */
77 state[c] += state[d];
78 state[b] ^= state[c];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010079 state[b] = ROTL32(state[b], 7);
Daniel King34b822c2016-05-15 17:28:08 -030080}
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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010090static void chacha20_inner_block(uint32_t state[16])
Daniel King34b822c2016-05-15 17:28:08 -030091{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010092 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);
Daniel King34b822c2016-05-15 17:28:08 -030096
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010097 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);
Daniel King34b822c2016-05-15 17:28:08 -0300101}
102
103/**
104 * \brief Generates a keystream block.
105 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200106 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300107 * \param keystream Generated keystream bytes are written to this buffer.
108 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100109static void chacha20_block(const uint32_t initial_state[16],
110 unsigned char keystream[64])
Daniel King34b822c2016-05-15 17:28:08 -0300111{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200112 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300113 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300114
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100115 memcpy(working_state,
116 initial_state,
117 CHACHA20_BLOCK_SIZE_BYTES);
Daniel King34b822c2016-05-15 17:28:08 -0300118
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100119 for (i = 0U; i < 10U; i++) {
120 chacha20_inner_block(working_state);
121 }
Daniel King34b822c2016-05-15 17:28:08 -0300122
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100123 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];
Daniel Kingb8025c52016-05-17 14:43:01 -0300133 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];
Daniel King34b822c2016-05-15 17:28:08 -0300139
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100140 for (i = 0U; i < 16; i++) {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200141 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300142
Joe Subbiani6627fb22021-07-16 15:02:55 +0100143 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Daniel King34b822c2016-05-15 17:28:08 -0300144 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200145
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100146 mbedtls_platform_zeroize(working_state, sizeof(working_state));
Daniel King34b822c2016-05-15 17:28:08 -0300147}
148
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100149void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300150{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151 CHACHA20_VALIDATE(ctx != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300152
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100153 mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
154 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Hanno Becker305e4e42018-12-11 15:03:16 +0000155
156 /* Initially, there's no keystream bytes available */
157 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300158}
159
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100160void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300161{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100162 if (ctx != NULL) {
163 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
Daniel King34b822c2016-05-15 17:28:08 -0300164 }
165}
166
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100167int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
168 const unsigned char key[32])
Daniel King34b822c2016-05-15 17:28:08 -0300169{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100170 CHACHA20_VALIDATE_RET(ctx != NULL);
171 CHACHA20_VALIDATE_RET(key != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300172
173 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200174 ctx->state[0] = 0x61707865;
175 ctx->state[1] = 0x3320646e;
176 ctx->state[2] = 0x79622d32;
177 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300178
179 /* Set key */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100180 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);
Daniel King34b822c2016-05-15 17:28:08 -0300188
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100189 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300190}
191
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100192int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
193 const unsigned char nonce[12],
194 uint32_t counter)
Daniel King34b822c2016-05-15 17:28:08 -0300195{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100196 CHACHA20_VALIDATE_RET(ctx != NULL);
197 CHACHA20_VALIDATE_RET(nonce != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300198
199 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200200 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300201
202 /* Nonce */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100203 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);
Daniel King34b822c2016-05-15 17:28:08 -0300206
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100207 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200208
209 /* Initially, there's no keystream bytes available */
210 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
211
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100212 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300213}
214
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100215int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
216 size_t size,
217 const unsigned char *input,
218 unsigned char *output)
Daniel King34b822c2016-05-15 17:28:08 -0300219{
220 size_t offset = 0U;
221 size_t i;
222
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100223 CHACHA20_VALIDATE_RET(ctx != NULL);
224 CHACHA20_VALIDATE_RET(size == 0 || input != NULL);
225 CHACHA20_VALIDATE_RET(size == 0 || output != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300226
227 /* Use leftover keystream bytes, if available */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100228 while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200229 output[offset] = input[offset]
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100230 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300231
232 ctx->keystream_bytes_used++;
233 offset++;
234 size--;
235 }
236
237 /* Process full blocks */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100238 while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200239 /* Generate new keystream block and increment counter */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100240 chacha20_block(ctx->state, ctx->keystream8);
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200241 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300242
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100243 for (i = 0U; i < 64U; i += 8U) {
244 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200245 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];
Daniel King34b822c2016-05-15 17:28:08 -0300252 }
253
Daniel Kingb8025c52016-05-17 14:43:01 -0300254 offset += CHACHA20_BLOCK_SIZE_BYTES;
255 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300256 }
257
258 /* Last (partial) block */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100259 if (size > 0U) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200260 /* Generate new keystream block and increment counter */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100261 chacha20_block(ctx->state, ctx->keystream8);
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200262 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300263
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100264 for (i = 0U; i < size; i++) {
Daniel King34b822c2016-05-15 17:28:08 -0300265 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
266 }
267
268 ctx->keystream_bytes_used = size;
269
Daniel King34b822c2016-05-15 17:28:08 -0300270 }
271
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100272 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300273}
274
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100275int 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)
Daniel King34b822c2016-05-15 17:28:08 -0300281{
282 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000283 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300284
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100285 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);
Hanno Becker305e4e42018-12-11 15:03:16 +0000289
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100290 mbedtls_chacha20_init(&ctx);
Daniel King34b822c2016-05-15 17:28:08 -0300291
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100292 ret = mbedtls_chacha20_setkey(&ctx, key);
293 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300294 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100295 }
Daniel King34b822c2016-05-15 17:28:08 -0300296
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100297 ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
298 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300299 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100300 }
Daniel King34b822c2016-05-15 17:28:08 -0300301
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100302 ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
Daniel King34b822c2016-05-15 17:28:08 -0300303
304cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100305 mbedtls_chacha20_free(&ctx);
306 return ret;
Daniel King34b822c2016-05-15 17:28:08 -0300307}
308
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200309#endif /* !MBEDTLS_CHACHA20_ALT */
310
Daniel King34b822c2016-05-15 17:28:08 -0300311#if defined(MBEDTLS_SELF_TEST)
312
313static 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
329static 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
341static const uint32_t test_counters[2] =
342{
343 0U,
344 1U
345};
346
347static 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
410static 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
473static const size_t test_lengths[2] =
474{
475 64U,
476 375U
477};
478
Ouss4e0b26872020-08-11 16:07:09 +0100479/* Make sure no other definition is already present. */
480#undef ASSERT
481
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100482#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200483 do \
484 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100485 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200486 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100487 if (verbose != 0) \
488 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200489 \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100490 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200491 } \
492 } \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100493 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200494
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100495int mbedtls_chacha20_self_test(int verbose)
Daniel King34b822c2016-05-15 17:28:08 -0300496{
497 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200498 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000499 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300500
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100501 for (i = 0U; i < 2U; i++) {
502 if (verbose != 0) {
503 mbedtls_printf(" ChaCha20 test %u ", i);
504 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300505
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100506 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);
Daniel King34b822c2016-05-15 17:28:08 -0300512
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100513 ASSERT(0 == ret, ("error code: %i\n", ret));
Daniel King34b822c2016-05-15 17:28:08 -0300514
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100515 ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
516 ("failed (output)\n"));
Daniel King34b822c2016-05-15 17:28:08 -0300517
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100518 if (verbose != 0) {
519 mbedtls_printf("passed\n");
520 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300521 }
522
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100523 if (verbose != 0) {
524 mbedtls_printf("\n");
525 }
Daniel King34b822c2016-05-15 17:28:08 -0300526
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100527 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300528}
529
530#endif /* MBEDTLS_SELF_TEST */
531
532#endif /* !MBEDTLS_CHACHA20_C */