blob: a95d5e9b83349aeb3e94ed26a250872b12139a41 [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
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020028# include "mbedtls/chacha20.h"
29# include "mbedtls/platform_util.h"
30# include "mbedtls/error.h"
Daniel King34b822c2016-05-15 17:28:08 -030031
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020032# include <stddef.h>
33# include <string.h>
Daniel King34b822c2016-05-15 17:28:08 -030034
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020035# if defined(MBEDTLS_SELF_TEST)
36# if defined(MBEDTLS_PLATFORM_C)
37# include "mbedtls/platform.h"
38# else
39# include <stdio.h>
40# define mbedtls_printf printf
41# endif /* MBEDTLS_PLATFORM_C */
42# endif /* MBEDTLS_SELF_TEST */
Daniel King34b822c2016-05-15 17:28:08 -030043
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020044# if !defined(MBEDTLS_CHACHA20_ALT)
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020045
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020046# if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \
47 !defined(inline) && !defined(__cplusplus)
48# define inline __inline
49# endif
Manuel Pégourié-Gonnard21a65e02018-06-07 11:54:17 +020050
Hanno Becker305e4e42018-12-11 15:03:16 +000051/* Parameter validation macros */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020052# define CHACHA20_VALIDATE_RET(cond) \
53 MBEDTLS_INTERNAL_VALIDATE_RET(cond, \
54 MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA)
55# define CHACHA20_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond)
Hanno Becker305e4e42018-12-11 15:03:16 +000056
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020057# define BYTES_TO_U32_LE(data, offset) \
58 ((uint32_t)(data)[offset] | \
59 (uint32_t)((uint32_t)(data)[(offset) + 1] << 8) | \
60 (uint32_t)((uint32_t)(data)[(offset) + 2] << 16) | \
61 (uint32_t)((uint32_t)(data)[(offset) + 3] << 24))
Daniel King34b822c2016-05-15 17:28:08 -030062
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020063# define ROTL32(value, amount) \
64 ((uint32_t)((value) << (amount)) | ((value) >> (32 - (amount))))
Daniel King34b822c2016-05-15 17:28:08 -030065
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020066# define CHACHA20_CTR_INDEX (12U)
Daniel King34b822c2016-05-15 17:28:08 -030067
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020068# define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
Daniel King34b822c2016-05-15 17:28:08 -030069
Daniel King34b822c2016-05-15 17:28:08 -030070/**
71 * \brief ChaCha20 quarter round operation.
72 *
73 * The quarter round is defined as follows (from RFC 7539):
74 * 1. a += b; d ^= a; d <<<= 16;
75 * 2. c += d; b ^= c; b <<<= 12;
76 * 3. a += b; d ^= a; d <<<= 8;
77 * 4. c += d; b ^= c; b <<<= 7;
78 *
79 * \param state ChaCha20 state to modify.
80 * \param a The index of 'a' in the state.
81 * \param b The index of 'b' in the state.
82 * \param c The index of 'c' in the state.
83 * \param d The index of 'd' in the state.
84 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020085static inline void chacha20_quarter_round(uint32_t state[16],
86 size_t a,
87 size_t b,
88 size_t c,
89 size_t d)
Daniel King34b822c2016-05-15 17:28:08 -030090{
91 /* a += b; d ^= a; d <<<= 16; */
92 state[a] += state[b];
93 state[d] ^= state[a];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020094 state[d] = ROTL32(state[d], 16);
Daniel King34b822c2016-05-15 17:28:08 -030095
96 /* c += d; b ^= c; b <<<= 12 */
97 state[c] += state[d];
98 state[b] ^= state[c];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020099 state[b] = ROTL32(state[b], 12);
Daniel King34b822c2016-05-15 17:28:08 -0300100
101 /* a += b; d ^= a; d <<<= 8; */
102 state[a] += state[b];
103 state[d] ^= state[a];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200104 state[d] = ROTL32(state[d], 8);
Daniel King34b822c2016-05-15 17:28:08 -0300105
106 /* c += d; b ^= c; b <<<= 7; */
107 state[c] += state[d];
108 state[b] ^= state[c];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200109 state[b] = ROTL32(state[b], 7);
Daniel King34b822c2016-05-15 17:28:08 -0300110}
111
112/**
113 * \brief Perform the ChaCha20 inner block operation.
114 *
115 * This function performs two rounds: the column round and the
116 * diagonal round.
117 *
118 * \param state The ChaCha20 state to update.
119 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200120static void chacha20_inner_block(uint32_t state[16])
Daniel King34b822c2016-05-15 17:28:08 -0300121{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200122 chacha20_quarter_round(state, 0, 4, 8, 12);
123 chacha20_quarter_round(state, 1, 5, 9, 13);
124 chacha20_quarter_round(state, 2, 6, 10, 14);
125 chacha20_quarter_round(state, 3, 7, 11, 15);
Daniel King34b822c2016-05-15 17:28:08 -0300126
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200127 chacha20_quarter_round(state, 0, 5, 10, 15);
128 chacha20_quarter_round(state, 1, 6, 11, 12);
129 chacha20_quarter_round(state, 2, 7, 8, 13);
130 chacha20_quarter_round(state, 3, 4, 9, 14);
Daniel King34b822c2016-05-15 17:28:08 -0300131}
132
133/**
134 * \brief Generates a keystream block.
135 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200136 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300137 * \param keystream Generated keystream bytes are written to this buffer.
138 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200139static void chacha20_block(const uint32_t initial_state[16],
140 unsigned char keystream[64])
Daniel King34b822c2016-05-15 17:28:08 -0300141{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200142 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300143 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300144
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200145 memcpy(working_state, initial_state, CHACHA20_BLOCK_SIZE_BYTES);
Daniel King34b822c2016-05-15 17:28:08 -0300146
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200147 for (i = 0U; i < 10U; i++)
148 chacha20_inner_block(working_state);
Daniel King34b822c2016-05-15 17:28:08 -0300149
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200150 working_state[0] += initial_state[0];
151 working_state[1] += initial_state[1];
152 working_state[2] += initial_state[2];
153 working_state[3] += initial_state[3];
154 working_state[4] += initial_state[4];
155 working_state[5] += initial_state[5];
156 working_state[6] += initial_state[6];
157 working_state[7] += initial_state[7];
158 working_state[8] += initial_state[8];
159 working_state[9] += initial_state[9];
Daniel Kingb8025c52016-05-17 14:43:01 -0300160 working_state[10] += initial_state[10];
161 working_state[11] += initial_state[11];
162 working_state[12] += initial_state[12];
163 working_state[13] += initial_state[13];
164 working_state[14] += initial_state[14];
165 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300166
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200167 for (i = 0U; i < 16; i++) {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200168 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300169
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200170 keystream[offset] = (unsigned char)(working_state[i]);
171 keystream[offset + 1U] = (unsigned char)(working_state[i] >> 8);
172 keystream[offset + 2U] = (unsigned char)(working_state[i] >> 16);
173 keystream[offset + 3U] = (unsigned char)(working_state[i] >> 24);
Daniel King34b822c2016-05-15 17:28:08 -0300174 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200175
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200176 mbedtls_platform_zeroize(working_state, sizeof(working_state));
Daniel King34b822c2016-05-15 17:28:08 -0300177}
178
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200179void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300180{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200181 CHACHA20_VALIDATE(ctx != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300182
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200183 mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
184 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Hanno Becker305e4e42018-12-11 15:03:16 +0000185
186 /* Initially, there's no keystream bytes available */
187 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300188}
189
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200190void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300191{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200192 if (ctx != NULL) {
193 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
Daniel King34b822c2016-05-15 17:28:08 -0300194 }
195}
196
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200197int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
198 const unsigned char key[32])
Daniel King34b822c2016-05-15 17:28:08 -0300199{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200200 CHACHA20_VALIDATE_RET(ctx != NULL);
201 CHACHA20_VALIDATE_RET(key != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300202
203 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200204 ctx->state[0] = 0x61707865;
205 ctx->state[1] = 0x3320646e;
206 ctx->state[2] = 0x79622d32;
207 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300208
209 /* Set key */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200210 ctx->state[4] = BYTES_TO_U32_LE(key, 0);
211 ctx->state[5] = BYTES_TO_U32_LE(key, 4);
212 ctx->state[6] = BYTES_TO_U32_LE(key, 8);
213 ctx->state[7] = BYTES_TO_U32_LE(key, 12);
214 ctx->state[8] = BYTES_TO_U32_LE(key, 16);
215 ctx->state[9] = BYTES_TO_U32_LE(key, 20);
216 ctx->state[10] = BYTES_TO_U32_LE(key, 24);
217 ctx->state[11] = BYTES_TO_U32_LE(key, 28);
Daniel King34b822c2016-05-15 17:28:08 -0300218
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200219 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300220}
221
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200222int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
223 const unsigned char nonce[12],
224 uint32_t counter)
Daniel King34b822c2016-05-15 17:28:08 -0300225{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200226 CHACHA20_VALIDATE_RET(ctx != NULL);
227 CHACHA20_VALIDATE_RET(nonce != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300228
229 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200230 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300231
232 /* Nonce */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200233 ctx->state[13] = BYTES_TO_U32_LE(nonce, 0);
234 ctx->state[14] = BYTES_TO_U32_LE(nonce, 4);
235 ctx->state[15] = BYTES_TO_U32_LE(nonce, 8);
Daniel King34b822c2016-05-15 17:28:08 -0300236
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200237 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200238
239 /* Initially, there's no keystream bytes available */
240 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
241
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200242 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300243}
244
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200245int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
246 size_t size,
247 const unsigned char *input,
248 unsigned char *output)
Daniel King34b822c2016-05-15 17:28:08 -0300249{
250 size_t offset = 0U;
251 size_t i;
252
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200253 CHACHA20_VALIDATE_RET(ctx != NULL);
254 CHACHA20_VALIDATE_RET(size == 0 || input != NULL);
255 CHACHA20_VALIDATE_RET(size == 0 || output != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300256
257 /* Use leftover keystream bytes, if available */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200258 while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
259 output[offset] = input[offset] ^
260 ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300261
262 ctx->keystream_bytes_used++;
263 offset++;
264 size--;
265 }
266
267 /* Process full blocks */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200268 while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200269 /* Generate new keystream block and increment counter */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200270 chacha20_block(ctx->state, ctx->keystream8);
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200271 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300272
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200273 for (i = 0U; i < 64U; i += 8U) {
274 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
275 output[offset + i + 1] = input[offset + i + 1] ^
276 ctx->keystream8[i + 1];
277 output[offset + i + 2] = input[offset + i + 2] ^
278 ctx->keystream8[i + 2];
279 output[offset + i + 3] = input[offset + i + 3] ^
280 ctx->keystream8[i + 3];
281 output[offset + i + 4] = input[offset + i + 4] ^
282 ctx->keystream8[i + 4];
283 output[offset + i + 5] = input[offset + i + 5] ^
284 ctx->keystream8[i + 5];
285 output[offset + i + 6] = input[offset + i + 6] ^
286 ctx->keystream8[i + 6];
287 output[offset + i + 7] = input[offset + i + 7] ^
288 ctx->keystream8[i + 7];
Daniel King34b822c2016-05-15 17:28:08 -0300289 }
290
Daniel Kingb8025c52016-05-17 14:43:01 -0300291 offset += CHACHA20_BLOCK_SIZE_BYTES;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200292 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300293 }
294
295 /* Last (partial) block */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200296 if (size > 0U) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200297 /* Generate new keystream block and increment counter */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200298 chacha20_block(ctx->state, ctx->keystream8);
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200299 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300300
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200301 for (i = 0U; i < size; i++) {
Daniel King34b822c2016-05-15 17:28:08 -0300302 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
303 }
304
305 ctx->keystream_bytes_used = size;
Daniel King34b822c2016-05-15 17:28:08 -0300306 }
307
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200308 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300309}
310
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200311int mbedtls_chacha20_crypt(const unsigned char key[32],
312 const unsigned char nonce[12],
313 uint32_t counter,
314 size_t data_len,
315 const unsigned char *input,
316 unsigned char *output)
Daniel King34b822c2016-05-15 17:28:08 -0300317{
318 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000319 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300320
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200321 CHACHA20_VALIDATE_RET(key != NULL);
322 CHACHA20_VALIDATE_RET(nonce != NULL);
323 CHACHA20_VALIDATE_RET(data_len == 0 || input != NULL);
324 CHACHA20_VALIDATE_RET(data_len == 0 || output != NULL);
Hanno Becker305e4e42018-12-11 15:03:16 +0000325
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200326 mbedtls_chacha20_init(&ctx);
Daniel King34b822c2016-05-15 17:28:08 -0300327
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200328 ret = mbedtls_chacha20_setkey(&ctx, key);
329 if (ret != 0)
Daniel King34b822c2016-05-15 17:28:08 -0300330 goto cleanup;
331
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200332 ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
333 if (ret != 0)
Daniel King34b822c2016-05-15 17:28:08 -0300334 goto cleanup;
335
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200336 ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
Daniel King34b822c2016-05-15 17:28:08 -0300337
338cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200339 mbedtls_chacha20_free(&ctx);
340 return ret;
Daniel King34b822c2016-05-15 17:28:08 -0300341}
342
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200343# endif /* !MBEDTLS_CHACHA20_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200344
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200345# if defined(MBEDTLS_SELF_TEST)
Daniel King34b822c2016-05-15 17:28:08 -0300346
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200347static const unsigned char test_keys[2][32] = {
348 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
351 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
352 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
Daniel King34b822c2016-05-15 17:28:08 -0300354};
355
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200356static const unsigned char test_nonces[2][12] = {
357 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
358 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }
Daniel King34b822c2016-05-15 17:28:08 -0300359};
360
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200361static const uint32_t test_counters[2] = { 0U, 1U };
362
363static const unsigned char test_input[2][375] = {
364 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
370 { 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69,
371 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
372 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20,
373 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
374 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70,
375 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
376 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x72,
377 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
378 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2d, 0x44, 0x72,
379 0x61, 0x66, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
380 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65,
381 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
382 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e,
383 0x74, 0x65, 0x78, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
384 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79,
385 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
386 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, 0x45, 0x54, 0x46, 0x20,
387 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
388 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, 0x73, 0x74, 0x61, 0x74,
389 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
390 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, 0x73, 0x74, 0x61, 0x74,
391 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
392 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2c,
393 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
394 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20,
395 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
396 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
397 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
398 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x6c,
399 0x61, 0x63, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
400 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64,
401 0x20, 0x74, 0x6f }
Daniel King34b822c2016-05-15 17:28:08 -0300402};
403
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200404static const unsigned char test_output[2][375] = {
405 { 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 0x40, 0x5d, 0x6a,
406 0xe5, 0x53, 0x86, 0xbd, 0x28, 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d,
407 0xed, 0x1a, 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, 0xda,
408 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, 0x77, 0x24, 0xe0, 0x3f,
409 0xb8, 0xd8, 0x4a, 0x37, 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1,
410 0x1c, 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 },
411 { 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, 0x4f, 0x37, 0x6c, 0xa2,
412 0x3e, 0x82, 0x73, 0x70, 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
413 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, 0x2a, 0x97, 0x94, 0x8b,
414 0xd3, 0x72, 0x29, 0x15, 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
415 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, 0x56, 0xe0, 0x31, 0xca,
416 0x5e, 0xb6, 0x25, 0x0d, 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
417 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, 0x20, 0xb6, 0xe8, 0xdb,
418 0x09, 0xd8, 0x81, 0xa7, 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
419 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, 0x14, 0x47, 0xb3, 0x29,
420 0x1c, 0xe1, 0x41, 0x1c, 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
421 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, 0xd0, 0x0f, 0x84, 0x49,
422 0xed, 0x8f, 0x72, 0xd0, 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
423 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, 0x1f, 0x43, 0xab, 0xf9,
424 0x37, 0xd3, 0x25, 0x9d, 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
425 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, 0xe6, 0x35, 0x55, 0x3b,
426 0xa7, 0x6c, 0x5c, 0x87, 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
427 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, 0x5e, 0x8a, 0x1e, 0x0e,
428 0xf9, 0xd5, 0x28, 0x0f, 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
429 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, 0xcc, 0x3a, 0xaf, 0x9f,
430 0x39, 0x79, 0xc9, 0x2b, 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
431 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, 0xa2, 0x36, 0xe7, 0xe8,
432 0x18, 0xb0, 0x4b, 0x0b, 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
433 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, 0x8a, 0xaa, 0x9b, 0x63,
434 0xd1, 0xa1, 0x6f, 0x80, 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
435 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, 0x6f, 0xf2, 0x16, 0xb9,
436 0xc1, 0xd3, 0x00, 0x62, 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
437 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, 0x98, 0xce, 0xd7, 0x59,
438 0xc3, 0xff, 0x9b, 0x64, 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
439 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, 0xb2, 0x38, 0x4d, 0xd9,
440 0x02, 0xf3, 0xd1, 0xab, 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
441 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, 0xc4, 0xfd, 0x80, 0x6c,
442 0x22, 0xf2, 0x21 }
Daniel King34b822c2016-05-15 17:28:08 -0300443};
444
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200445static const size_t test_lengths[2] = { 64U, 375U };
Daniel King34b822c2016-05-15 17:28:08 -0300446
Ouss4e0b26872020-08-11 16:07:09 +0100447/* Make sure no other definition is already present. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200448# undef ASSERT
Ouss4e0b26872020-08-11 16:07:09 +0100449
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200450# define ASSERT(cond, args) \
451 do { \
452 if (!(cond)) { \
453 if (verbose != 0) \
454 mbedtls_printf args; \
455 \
456 return -1; \
457 } \
458 } while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200459
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200460int mbedtls_chacha20_self_test(int verbose)
Daniel King34b822c2016-05-15 17:28:08 -0300461{
462 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200463 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000464 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300465
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200466 for (i = 0U; i < 2U; i++) {
467 if (verbose != 0)
468 mbedtls_printf(" ChaCha20 test %u ", i);
Daniel Kingdedf4a32016-05-18 10:07:53 -0300469
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200470 ret = mbedtls_chacha20_crypt(test_keys[i], test_nonces[i],
471 test_counters[i], test_lengths[i],
472 test_input[i], output);
Daniel King34b822c2016-05-15 17:28:08 -0300473
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200474 ASSERT(0 == ret, ("error code: %i\n", ret));
Daniel King34b822c2016-05-15 17:28:08 -0300475
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200476 ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
477 ("failed (output)\n"));
Daniel King34b822c2016-05-15 17:28:08 -0300478
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200479 if (verbose != 0)
480 mbedtls_printf("passed\n");
Daniel Kingdedf4a32016-05-18 10:07:53 -0300481 }
482
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200483 if (verbose != 0)
484 mbedtls_printf("\n");
Daniel King34b822c2016-05-15 17:28:08 -0300485
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200486 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300487}
488
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200489# endif /* MBEDTLS_SELF_TEST */
Daniel King34b822c2016-05-15 17:28:08 -0300490
491#endif /* !MBEDTLS_CHACHA20_C */