blob: cbb01f4adf733e409f6ea97006ef434766d4041e [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
Daniel King34b822c2016-05-15 17:28:08 -03009 * SPDX-License-Identifier: Apache-2.0
10 *
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.
Daniel King34b822c2016-05-15 17:28:08 -030022 */
Daniel King34b822c2016-05-15 17:28:08 -030023
Gilles Peskinedb09ef62020-06-03 01:43:33 +020024#include "common.h"
Daniel King34b822c2016-05-15 17:28:08 -030025
26#if defined(MBEDTLS_CHACHA20_C)
27
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020028#include "mbedtls/chacha20.h"
29#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000030#include "mbedtls/error.h"
Daniel King34b822c2016-05-15 17:28:08 -030031
32#include <stddef.h>
33#include <string.h>
34
Daniel King34b822c2016-05-15 17:28:08 -030035#include "mbedtls/platform.h"
Daniel King34b822c2016-05-15 17:28:08 -030036
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020037#if !defined(MBEDTLS_CHACHA20_ALT)
38
Gilles Peskine449bd832023-01-11 14:50:10 +010039#define ROTL32(value, amount) \
40 ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
Daniel King34b822c2016-05-15 17:28:08 -030041
Gilles Peskine449bd832023-01-11 14:50:10 +010042#define CHACHA20_CTR_INDEX (12U)
Daniel King34b822c2016-05-15 17:28:08 -030043
Gilles Peskine449bd832023-01-11 14:50:10 +010044#define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
Daniel King34b822c2016-05-15 17:28:08 -030045
Daniel King34b822c2016-05-15 17:28:08 -030046/**
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 */
Gilles Peskine449bd832023-01-11 14:50:10 +010061static 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)
Daniel King34b822c2016-05-15 17:28:08 -030066{
67 /* a += b; d ^= a; d <<<= 16; */
68 state[a] += state[b];
69 state[d] ^= state[a];
Gilles Peskine449bd832023-01-11 14:50:10 +010070 state[d] = ROTL32(state[d], 16);
Daniel King34b822c2016-05-15 17:28:08 -030071
72 /* c += d; b ^= c; b <<<= 12 */
73 state[c] += state[d];
74 state[b] ^= state[c];
Gilles Peskine449bd832023-01-11 14:50:10 +010075 state[b] = ROTL32(state[b], 12);
Daniel King34b822c2016-05-15 17:28:08 -030076
77 /* a += b; d ^= a; d <<<= 8; */
78 state[a] += state[b];
79 state[d] ^= state[a];
Gilles Peskine449bd832023-01-11 14:50:10 +010080 state[d] = ROTL32(state[d], 8);
Daniel King34b822c2016-05-15 17:28:08 -030081
82 /* c += d; b ^= c; b <<<= 7; */
83 state[c] += state[d];
84 state[b] ^= state[c];
Gilles Peskine449bd832023-01-11 14:50:10 +010085 state[b] = ROTL32(state[b], 7);
Daniel King34b822c2016-05-15 17:28:08 -030086}
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 */
Gilles Peskine449bd832023-01-11 14:50:10 +010096static void chacha20_inner_block(uint32_t state[16])
Daniel King34b822c2016-05-15 17:28:08 -030097{
Gilles Peskine449bd832023-01-11 14:50:10 +010098 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);
Daniel King34b822c2016-05-15 17:28:08 -0300102
Gilles Peskine449bd832023-01-11 14:50:10 +0100103 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);
Daniel King34b822c2016-05-15 17:28:08 -0300107}
108
109/**
110 * \brief Generates a keystream block.
111 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200112 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300113 * \param keystream Generated keystream bytes are written to this buffer.
114 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100115static void chacha20_block(const uint32_t initial_state[16],
116 unsigned char keystream[64])
Daniel King34b822c2016-05-15 17:28:08 -0300117{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200118 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300119 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300120
Gilles Peskine449bd832023-01-11 14:50:10 +0100121 memcpy(working_state,
122 initial_state,
123 CHACHA20_BLOCK_SIZE_BYTES);
Daniel King34b822c2016-05-15 17:28:08 -0300124
Gilles Peskine449bd832023-01-11 14:50:10 +0100125 for (i = 0U; i < 10U; i++) {
126 chacha20_inner_block(working_state);
127 }
Daniel King34b822c2016-05-15 17:28:08 -0300128
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 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];
Daniel Kingb8025c52016-05-17 14:43:01 -0300139 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];
Daniel King34b822c2016-05-15 17:28:08 -0300145
Gilles Peskine449bd832023-01-11 14:50:10 +0100146 for (i = 0U; i < 16; i++) {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200147 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300148
Joe Subbianib6511b02021-07-16 15:02:55 +0100149 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Daniel King34b822c2016-05-15 17:28:08 -0300150 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200151
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 mbedtls_platform_zeroize(working_state, sizeof(working_state));
Daniel King34b822c2016-05-15 17:28:08 -0300153}
154
Gilles Peskine449bd832023-01-11 14:50:10 +0100155void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300156{
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
158 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Hanno Becker305e4e42018-12-11 15:03:16 +0000159
160 /* Initially, there's no keystream bytes available */
161 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300162}
163
Gilles Peskine449bd832023-01-11 14:50:10 +0100164void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300165{
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 if (ctx != NULL) {
167 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
Daniel King34b822c2016-05-15 17:28:08 -0300168 }
169}
170
Gilles Peskine449bd832023-01-11 14:50:10 +0100171int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
172 const unsigned char key[32])
Daniel King34b822c2016-05-15 17:28:08 -0300173{
Daniel King34b822c2016-05-15 17:28:08 -0300174 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200175 ctx->state[0] = 0x61707865;
176 ctx->state[1] = 0x3320646e;
177 ctx->state[2] = 0x79622d32;
178 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300179
180 /* Set key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100181 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);
Daniel King34b822c2016-05-15 17:28:08 -0300189
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300191}
192
Gilles Peskine449bd832023-01-11 14:50:10 +0100193int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
194 const unsigned char nonce[12],
195 uint32_t counter)
Daniel King34b822c2016-05-15 17:28:08 -0300196{
Daniel King34b822c2016-05-15 17:28:08 -0300197 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200198 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300199
200 /* Nonce */
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 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);
Daniel King34b822c2016-05-15 17:28:08 -0300204
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200206
207 /* Initially, there's no keystream bytes available */
208 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
209
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300211}
212
Gilles Peskine449bd832023-01-11 14:50:10 +0100213int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
214 size_t size,
215 const unsigned char *input,
216 unsigned char *output)
Daniel King34b822c2016-05-15 17:28:08 -0300217{
218 size_t offset = 0U;
Daniel King34b822c2016-05-15 17:28:08 -0300219
Daniel King34b822c2016-05-15 17:28:08 -0300220 /* Use leftover keystream bytes, if available */
Gilles Peskine449bd832023-01-11 14:50:10 +0100221 while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200222 output[offset] = input[offset]
Gilles Peskine449bd832023-01-11 14:50:10 +0100223 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300224
225 ctx->keystream_bytes_used++;
226 offset++;
227 size--;
228 }
229
230 /* Process full blocks */
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
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, 64U);
Daniel King34b822c2016-05-15 17:28:08 -0300237
Daniel Kingb8025c52016-05-17 14:43:01 -0300238 offset += CHACHA20_BLOCK_SIZE_BYTES;
239 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300240 }
241
242 /* Last (partial) block */
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 if (size > 0U) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200244 /* Generate new keystream block and increment counter */
Gilles Peskine449bd832023-01-11 14:50:10 +0100245 chacha20_block(ctx->state, ctx->keystream8);
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200246 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300247
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);
Daniel King34b822c2016-05-15 17:28:08 -0300249
250 ctx->keystream_bytes_used = size;
251
Daniel King34b822c2016-05-15 17:28:08 -0300252 }
253
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300255}
256
Gilles Peskine449bd832023-01-11 14:50:10 +0100257int 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)
Daniel King34b822c2016-05-15 17:28:08 -0300263{
264 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000265 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300266
Gilles Peskine449bd832023-01-11 14:50:10 +0100267 mbedtls_chacha20_init(&ctx);
Daniel King34b822c2016-05-15 17:28:08 -0300268
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 ret = mbedtls_chacha20_setkey(&ctx, key);
270 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300271 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 }
Daniel King34b822c2016-05-15 17:28:08 -0300273
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
275 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300276 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100277 }
Daniel King34b822c2016-05-15 17:28:08 -0300278
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
Daniel King34b822c2016-05-15 17:28:08 -0300280
281cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 mbedtls_chacha20_free(&ctx);
283 return ret;
Daniel King34b822c2016-05-15 17:28:08 -0300284}
285
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200286#endif /* !MBEDTLS_CHACHA20_ALT */
287
Daniel King34b822c2016-05-15 17:28:08 -0300288#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
Ouss4e0b26872020-08-11 16:07:09 +0100456/* Make sure no other definition is already present. */
457#undef ASSERT
458
Gilles Peskine449bd832023-01-11 14:50:10 +0100459#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200460 do \
461 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200463 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 if (verbose != 0) \
465 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200466 \
Gilles Peskine449bd832023-01-11 14:50:10 +0100467 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200468 } \
469 } \
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200471
Gilles Peskine449bd832023-01-11 14:50:10 +0100472int mbedtls_chacha20_self_test(int verbose)
Daniel King34b822c2016-05-15 17:28:08 -0300473{
474 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200475 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000476 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300477
Gilles Peskine449bd832023-01-11 14:50:10 +0100478 for (i = 0U; i < 2U; i++) {
479 if (verbose != 0) {
480 mbedtls_printf(" ChaCha20 test %u ", i);
481 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 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);
Daniel King34b822c2016-05-15 17:28:08 -0300489
Gilles Peskine449bd832023-01-11 14:50:10 +0100490 ASSERT(0 == ret, ("error code: %i\n", ret));
Daniel King34b822c2016-05-15 17:28:08 -0300491
Gilles Peskine449bd832023-01-11 14:50:10 +0100492 ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
493 ("failed (output)\n"));
Daniel King34b822c2016-05-15 17:28:08 -0300494
Gilles Peskine449bd832023-01-11 14:50:10 +0100495 if (verbose != 0) {
496 mbedtls_printf("passed\n");
497 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300498 }
499
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 if (verbose != 0) {
501 mbedtls_printf("\n");
502 }
Daniel King34b822c2016-05-15 17:28:08 -0300503
Gilles Peskine449bd832023-01-11 14:50:10 +0100504 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300505}
506
507#endif /* MBEDTLS_SELF_TEST */
508
509#endif /* !MBEDTLS_CHACHA20_C */