blob: cbb01f4adf733e409f6ea97006ef434766d4041e [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
9 * SPDX-License-Identifier: Apache-2.0
Jens Wiklander3d3b0592019-03-20 15:30:29 +010010 *
11 * Licensed under the Apache License, Version 2.0 (the "License"); you may
12 * not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
19 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
Jens Wiklander3d3b0592019-03-20 15:30:29 +010022 */
23
Jerome Forissier79013242021-07-28 10:24:04 +020024#include "common.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010025
26#if defined(MBEDTLS_CHACHA20_C)
27
28#include "mbedtls/chacha20.h"
29#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020030#include "mbedtls/error.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010031
32#include <stddef.h>
33#include <string.h>
34
Jens Wiklander3d3b0592019-03-20 15:30:29 +010035#include "mbedtls/platform.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010036
37#if !defined(MBEDTLS_CHACHA20_ALT)
38
Jens Wiklander32b31802023-10-06 16:59:46 +020039#define ROTL32(value, amount) \
40 ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
Jens Wiklander3d3b0592019-03-20 15:30:29 +010041
Jens Wiklander32b31802023-10-06 16:59:46 +020042#define CHACHA20_CTR_INDEX (12U)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010043
Jens Wiklander32b31802023-10-06 16:59:46 +020044#define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010045
46/**
47 * \brief ChaCha20 quarter round operation.
48 *
49 * The quarter round is defined as follows (from RFC 7539):
50 * 1. a += b; d ^= a; d <<<= 16;
51 * 2. c += d; b ^= c; b <<<= 12;
52 * 3. a += b; d ^= a; d <<<= 8;
53 * 4. c += d; b ^= c; b <<<= 7;
54 *
55 * \param state ChaCha20 state to modify.
56 * \param a The index of 'a' in the state.
57 * \param b The index of 'b' in the state.
58 * \param c The index of 'c' in the state.
59 * \param d The index of 'd' in the state.
60 */
Jens Wiklander32b31802023-10-06 16:59:46 +020061static inline void chacha20_quarter_round(uint32_t state[16],
62 size_t a,
63 size_t b,
64 size_t c,
65 size_t d)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010066{
67 /* a += b; d ^= a; d <<<= 16; */
68 state[a] += state[b];
69 state[d] ^= state[a];
Jens Wiklander32b31802023-10-06 16:59:46 +020070 state[d] = ROTL32(state[d], 16);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010071
72 /* c += d; b ^= c; b <<<= 12 */
73 state[c] += state[d];
74 state[b] ^= state[c];
Jens Wiklander32b31802023-10-06 16:59:46 +020075 state[b] = ROTL32(state[b], 12);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010076
77 /* a += b; d ^= a; d <<<= 8; */
78 state[a] += state[b];
79 state[d] ^= state[a];
Jens Wiklander32b31802023-10-06 16:59:46 +020080 state[d] = ROTL32(state[d], 8);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010081
82 /* c += d; b ^= c; b <<<= 7; */
83 state[c] += state[d];
84 state[b] ^= state[c];
Jens Wiklander32b31802023-10-06 16:59:46 +020085 state[b] = ROTL32(state[b], 7);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010086}
87
88/**
89 * \brief Perform the ChaCha20 inner block operation.
90 *
91 * This function performs two rounds: the column round and the
92 * diagonal round.
93 *
94 * \param state The ChaCha20 state to update.
95 */
Jens Wiklander32b31802023-10-06 16:59:46 +020096static void chacha20_inner_block(uint32_t state[16])
Jens Wiklander3d3b0592019-03-20 15:30:29 +010097{
Jens Wiklander32b31802023-10-06 16:59:46 +020098 chacha20_quarter_round(state, 0, 4, 8, 12);
99 chacha20_quarter_round(state, 1, 5, 9, 13);
100 chacha20_quarter_round(state, 2, 6, 10, 14);
101 chacha20_quarter_round(state, 3, 7, 11, 15);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100102
Jens Wiklander32b31802023-10-06 16:59:46 +0200103 chacha20_quarter_round(state, 0, 5, 10, 15);
104 chacha20_quarter_round(state, 1, 6, 11, 12);
105 chacha20_quarter_round(state, 2, 7, 8, 13);
106 chacha20_quarter_round(state, 3, 4, 9, 14);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100107}
108
109/**
110 * \brief Generates a keystream block.
111 *
112 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
113 * \param keystream Generated keystream bytes are written to this buffer.
114 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200115static void chacha20_block(const uint32_t initial_state[16],
116 unsigned char keystream[64])
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100117{
118 uint32_t working_state[16];
119 size_t i;
120
Jens Wiklander32b31802023-10-06 16:59:46 +0200121 memcpy(working_state,
122 initial_state,
123 CHACHA20_BLOCK_SIZE_BYTES);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100124
Jens Wiklander32b31802023-10-06 16:59:46 +0200125 for (i = 0U; i < 10U; i++) {
126 chacha20_inner_block(working_state);
127 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100128
Jens Wiklander32b31802023-10-06 16:59:46 +0200129 working_state[0] += initial_state[0];
130 working_state[1] += initial_state[1];
131 working_state[2] += initial_state[2];
132 working_state[3] += initial_state[3];
133 working_state[4] += initial_state[4];
134 working_state[5] += initial_state[5];
135 working_state[6] += initial_state[6];
136 working_state[7] += initial_state[7];
137 working_state[8] += initial_state[8];
138 working_state[9] += initial_state[9];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100139 working_state[10] += initial_state[10];
140 working_state[11] += initial_state[11];
141 working_state[12] += initial_state[12];
142 working_state[13] += initial_state[13];
143 working_state[14] += initial_state[14];
144 working_state[15] += initial_state[15];
145
Jens Wiklander32b31802023-10-06 16:59:46 +0200146 for (i = 0U; i < 16; i++) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100147 size_t offset = i * 4U;
148
Jerome Forissier039e02d2022-08-09 17:10:15 +0200149 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100150 }
151
Jens Wiklander32b31802023-10-06 16:59:46 +0200152 mbedtls_platform_zeroize(working_state, sizeof(working_state));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100153}
154
Jens Wiklander32b31802023-10-06 16:59:46 +0200155void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100156{
Jens Wiklander32b31802023-10-06 16:59:46 +0200157 mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
158 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100159
160 /* Initially, there's no keystream bytes available */
161 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
162}
163
Jens Wiklander32b31802023-10-06 16:59:46 +0200164void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100165{
Jens Wiklander32b31802023-10-06 16:59:46 +0200166 if (ctx != NULL) {
167 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100168 }
169}
170
Jens Wiklander32b31802023-10-06 16:59:46 +0200171int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
172 const unsigned char key[32])
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100173{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100174 /* ChaCha20 constants - the string "expand 32-byte k" */
175 ctx->state[0] = 0x61707865;
176 ctx->state[1] = 0x3320646e;
177 ctx->state[2] = 0x79622d32;
178 ctx->state[3] = 0x6b206574;
179
180 /* Set key */
Jens Wiklander32b31802023-10-06 16:59:46 +0200181 ctx->state[4] = MBEDTLS_GET_UINT32_LE(key, 0);
182 ctx->state[5] = MBEDTLS_GET_UINT32_LE(key, 4);
183 ctx->state[6] = MBEDTLS_GET_UINT32_LE(key, 8);
184 ctx->state[7] = MBEDTLS_GET_UINT32_LE(key, 12);
185 ctx->state[8] = MBEDTLS_GET_UINT32_LE(key, 16);
186 ctx->state[9] = MBEDTLS_GET_UINT32_LE(key, 20);
187 ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24);
188 ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100189
Jens Wiklander32b31802023-10-06 16:59:46 +0200190 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100191}
192
Jens Wiklander32b31802023-10-06 16:59:46 +0200193int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
194 const unsigned char nonce[12],
195 uint32_t counter)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100196{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100197 /* Counter */
198 ctx->state[12] = counter;
199
200 /* Nonce */
Jens Wiklander32b31802023-10-06 16:59:46 +0200201 ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0);
202 ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4);
203 ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100204
Jens Wiklander32b31802023-10-06 16:59:46 +0200205 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100206
207 /* Initially, there's no keystream bytes available */
208 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
209
Jens Wiklander32b31802023-10-06 16:59:46 +0200210 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100211}
212
Jens Wiklander32b31802023-10-06 16:59:46 +0200213int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
214 size_t size,
215 const unsigned char *input,
216 unsigned char *output)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100217{
218 size_t offset = 0U;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100219
220 /* Use leftover keystream bytes, if available */
Jens Wiklander32b31802023-10-06 16:59:46 +0200221 while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100222 output[offset] = input[offset]
Jens Wiklander32b31802023-10-06 16:59:46 +0200223 ^ ctx->keystream8[ctx->keystream_bytes_used];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100224
225 ctx->keystream_bytes_used++;
226 offset++;
227 size--;
228 }
229
230 /* Process full blocks */
Jens Wiklander32b31802023-10-06 16:59:46 +0200231 while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
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, 64U);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100237
238 offset += CHACHA20_BLOCK_SIZE_BYTES;
239 size -= CHACHA20_BLOCK_SIZE_BYTES;
240 }
241
242 /* Last (partial) block */
Jens Wiklander32b31802023-10-06 16:59:46 +0200243 if (size > 0U) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100244 /* Generate new keystream block and increment counter */
Jens Wiklander32b31802023-10-06 16:59:46 +0200245 chacha20_block(ctx->state, ctx->keystream8);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100246 ctx->state[CHACHA20_CTR_INDEX]++;
247
Jens Wiklander32b31802023-10-06 16:59:46 +0200248 mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100249
250 ctx->keystream_bytes_used = size;
251
252 }
253
Jens Wiklander32b31802023-10-06 16:59:46 +0200254 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100255}
256
Jens Wiklander32b31802023-10-06 16:59:46 +0200257int mbedtls_chacha20_crypt(const unsigned char key[32],
258 const unsigned char nonce[12],
259 uint32_t counter,
260 size_t data_len,
261 const unsigned char *input,
262 unsigned char *output)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100263{
264 mbedtls_chacha20_context ctx;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200265 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100266
Jens Wiklander32b31802023-10-06 16:59:46 +0200267 mbedtls_chacha20_init(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100268
Jens Wiklander32b31802023-10-06 16:59:46 +0200269 ret = mbedtls_chacha20_setkey(&ctx, key);
270 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100271 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200272 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100273
Jens Wiklander32b31802023-10-06 16:59:46 +0200274 ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
275 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100276 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200277 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100278
Jens Wiklander32b31802023-10-06 16:59:46 +0200279 ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100280
281cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200282 mbedtls_chacha20_free(&ctx);
283 return ret;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100284}
285
286#endif /* !MBEDTLS_CHACHA20_ALT */
287
288#if defined(MBEDTLS_SELF_TEST)
289
290static const unsigned char test_keys[2][32] =
291{
292 {
293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
297 },
298 {
299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
303 }
304};
305
306static const unsigned char test_nonces[2][12] =
307{
308 {
309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310 0x00, 0x00, 0x00, 0x00
311 },
312 {
313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0x00, 0x02
315 }
316};
317
318static const uint32_t test_counters[2] =
319{
320 0U,
321 1U
322};
323
324static const unsigned char test_input[2][375] =
325{
326 {
327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
328 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
335 },
336 {
337 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
338 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
339 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
340 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
341 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
342 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
343 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
344 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
345 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
346 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
347 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
348 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
349 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
350 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
351 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
352 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
353 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
354 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
355 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
356 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
357 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
358 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
359 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
360 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
361 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
362 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
363 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
364 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
365 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
366 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
367 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
368 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
369 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
370 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
371 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
372 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
373 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
374 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
375 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
376 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
377 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
378 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
379 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
380 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
381 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
382 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
383 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
384 }
385};
386
387static const unsigned char test_output[2][375] =
388{
389 {
390 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
391 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
392 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
393 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
394 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
395 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
396 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
397 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
398 },
399 {
400 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
401 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
402 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
403 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
404 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
405 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
406 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
407 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
408 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
409 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
410 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
411 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
412 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
413 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
414 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
415 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
416 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
417 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
418 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
419 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
420 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
421 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
422 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
423 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
424 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
425 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
426 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
427 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
428 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
429 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
430 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
431 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
432 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
433 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
434 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
435 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
436 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
437 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
438 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
439 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
440 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
441 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
442 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
443 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
444 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
445 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
446 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
447 }
448};
449
450static const size_t test_lengths[2] =
451{
452 64U,
453 375U
454};
455
Jerome Forissier79013242021-07-28 10:24:04 +0200456/* Make sure no other definition is already present. */
457#undef ASSERT
458
Jens Wiklander32b31802023-10-06 16:59:46 +0200459#define ASSERT(cond, args) \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100460 do \
461 { \
Jens Wiklander32b31802023-10-06 16:59:46 +0200462 if (!(cond)) \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100463 { \
Jens Wiklander32b31802023-10-06 16:59:46 +0200464 if (verbose != 0) \
465 mbedtls_printf args; \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100466 \
Jens Wiklander32b31802023-10-06 16:59:46 +0200467 return -1; \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100468 } \
469 } \
Jens Wiklander32b31802023-10-06 16:59:46 +0200470 while (0)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100471
Jens Wiklander32b31802023-10-06 16:59:46 +0200472int mbedtls_chacha20_self_test(int verbose)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100473{
474 unsigned char output[381];
475 unsigned i;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200476 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100477
Jens Wiklander32b31802023-10-06 16:59:46 +0200478 for (i = 0U; i < 2U; i++) {
479 if (verbose != 0) {
480 mbedtls_printf(" ChaCha20 test %u ", i);
481 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100482
Jens Wiklander32b31802023-10-06 16:59:46 +0200483 ret = mbedtls_chacha20_crypt(test_keys[i],
484 test_nonces[i],
485 test_counters[i],
486 test_lengths[i],
487 test_input[i],
488 output);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100489
Jens Wiklander32b31802023-10-06 16:59:46 +0200490 ASSERT(0 == ret, ("error code: %i\n", ret));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100491
Jens Wiklander32b31802023-10-06 16:59:46 +0200492 ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
493 ("failed (output)\n"));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100494
Jens Wiklander32b31802023-10-06 16:59:46 +0200495 if (verbose != 0) {
496 mbedtls_printf("passed\n");
497 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100498 }
499
Jens Wiklander32b31802023-10-06 16:59:46 +0200500 if (verbose != 0) {
501 mbedtls_printf("\n");
502 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100503
Jens Wiklander32b31802023-10-06 16:59:46 +0200504 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100505}
506
507#endif /* MBEDTLS_SELF_TEST */
508
509#endif /* !MBEDTLS_CHACHA20_C */