blob: 53f1d3916cee85b567553a6211bf57fbfb60e645 [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
Hanno Becker305e4e42018-12-11 15:03:16 +000039/* Parameter validation macros */
David Horstmannceeaeb92023-01-05 15:44:23 +000040#define CHACHA20_VALIDATE_RET(cond) \
41 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA)
42#define CHACHA20_VALIDATE(cond) \
43 MBEDTLS_INTERNAL_VALIDATE(cond)
Hanno Becker305e4e42018-12-11 15:03:16 +000044
David Horstmannceeaeb92023-01-05 15:44:23 +000045#define ROTL32(value, amount) \
46 ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
Daniel King34b822c2016-05-15 17:28:08 -030047
David Horstmannceeaeb92023-01-05 15:44:23 +000048#define CHACHA20_CTR_INDEX (12U)
Daniel King34b822c2016-05-15 17:28:08 -030049
David Horstmannceeaeb92023-01-05 15:44:23 +000050#define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
Daniel King34b822c2016-05-15 17:28:08 -030051
Daniel King34b822c2016-05-15 17:28:08 -030052/**
53 * \brief ChaCha20 quarter round operation.
54 *
55 * The quarter round is defined as follows (from RFC 7539):
56 * 1. a += b; d ^= a; d <<<= 16;
57 * 2. c += d; b ^= c; b <<<= 12;
58 * 3. a += b; d ^= a; d <<<= 8;
59 * 4. c += d; b ^= c; b <<<= 7;
60 *
61 * \param state ChaCha20 state to modify.
62 * \param a The index of 'a' in the state.
63 * \param b The index of 'b' in the state.
64 * \param c The index of 'c' in the state.
65 * \param d The index of 'd' in the state.
66 */
David Horstmannceeaeb92023-01-05 15:44:23 +000067static inline void chacha20_quarter_round(uint32_t state[16],
68 size_t a,
69 size_t b,
70 size_t c,
71 size_t d)
Daniel King34b822c2016-05-15 17:28:08 -030072{
73 /* a += b; d ^= a; d <<<= 16; */
74 state[a] += state[b];
75 state[d] ^= state[a];
David Horstmannceeaeb92023-01-05 15:44:23 +000076 state[d] = ROTL32(state[d], 16);
Daniel King34b822c2016-05-15 17:28:08 -030077
78 /* c += d; b ^= c; b <<<= 12 */
79 state[c] += state[d];
80 state[b] ^= state[c];
David Horstmannceeaeb92023-01-05 15:44:23 +000081 state[b] = ROTL32(state[b], 12);
Daniel King34b822c2016-05-15 17:28:08 -030082
83 /* a += b; d ^= a; d <<<= 8; */
84 state[a] += state[b];
85 state[d] ^= state[a];
David Horstmannceeaeb92023-01-05 15:44:23 +000086 state[d] = ROTL32(state[d], 8);
Daniel King34b822c2016-05-15 17:28:08 -030087
88 /* c += d; b ^= c; b <<<= 7; */
89 state[c] += state[d];
90 state[b] ^= state[c];
David Horstmannceeaeb92023-01-05 15:44:23 +000091 state[b] = ROTL32(state[b], 7);
Daniel King34b822c2016-05-15 17:28:08 -030092}
93
94/**
95 * \brief Perform the ChaCha20 inner block operation.
96 *
97 * This function performs two rounds: the column round and the
98 * diagonal round.
99 *
100 * \param state The ChaCha20 state to update.
101 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000102static void chacha20_inner_block(uint32_t state[16])
Daniel King34b822c2016-05-15 17:28:08 -0300103{
David Horstmannceeaeb92023-01-05 15:44:23 +0000104 chacha20_quarter_round(state, 0, 4, 8, 12);
105 chacha20_quarter_round(state, 1, 5, 9, 13);
106 chacha20_quarter_round(state, 2, 6, 10, 14);
107 chacha20_quarter_round(state, 3, 7, 11, 15);
Daniel King34b822c2016-05-15 17:28:08 -0300108
David Horstmannceeaeb92023-01-05 15:44:23 +0000109 chacha20_quarter_round(state, 0, 5, 10, 15);
110 chacha20_quarter_round(state, 1, 6, 11, 12);
111 chacha20_quarter_round(state, 2, 7, 8, 13);
112 chacha20_quarter_round(state, 3, 4, 9, 14);
Daniel King34b822c2016-05-15 17:28:08 -0300113}
114
115/**
116 * \brief Generates a keystream block.
117 *
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200118 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
Daniel King34b822c2016-05-15 17:28:08 -0300119 * \param keystream Generated keystream bytes are written to this buffer.
120 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000121static void chacha20_block(const uint32_t initial_state[16],
122 unsigned char keystream[64])
Daniel King34b822c2016-05-15 17:28:08 -0300123{
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200124 uint32_t working_state[16];
Daniel King34b822c2016-05-15 17:28:08 -0300125 size_t i;
Daniel King34b822c2016-05-15 17:28:08 -0300126
David Horstmannceeaeb92023-01-05 15:44:23 +0000127 memcpy(working_state,
128 initial_state,
129 CHACHA20_BLOCK_SIZE_BYTES);
Daniel King34b822c2016-05-15 17:28:08 -0300130
David Horstmannceeaeb92023-01-05 15:44:23 +0000131 for (i = 0U; i < 10U; i++) {
132 chacha20_inner_block(working_state);
133 }
Daniel King34b822c2016-05-15 17:28:08 -0300134
David Horstmannceeaeb92023-01-05 15:44:23 +0000135 working_state[0] += initial_state[0];
136 working_state[1] += initial_state[1];
137 working_state[2] += initial_state[2];
138 working_state[3] += initial_state[3];
139 working_state[4] += initial_state[4];
140 working_state[5] += initial_state[5];
141 working_state[6] += initial_state[6];
142 working_state[7] += initial_state[7];
143 working_state[8] += initial_state[8];
144 working_state[9] += initial_state[9];
Daniel Kingb8025c52016-05-17 14:43:01 -0300145 working_state[10] += initial_state[10];
146 working_state[11] += initial_state[11];
147 working_state[12] += initial_state[12];
148 working_state[13] += initial_state[13];
149 working_state[14] += initial_state[14];
150 working_state[15] += initial_state[15];
Daniel King34b822c2016-05-15 17:28:08 -0300151
David Horstmannceeaeb92023-01-05 15:44:23 +0000152 for (i = 0U; i < 16; i++) {
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200153 size_t offset = i * 4U;
Daniel King34b822c2016-05-15 17:28:08 -0300154
Joe Subbiani6627fb22021-07-16 15:02:55 +0100155 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
Daniel King34b822c2016-05-15 17:28:08 -0300156 }
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200157
David Horstmannceeaeb92023-01-05 15:44:23 +0000158 mbedtls_platform_zeroize(working_state, sizeof(working_state));
Daniel King34b822c2016-05-15 17:28:08 -0300159}
160
David Horstmannceeaeb92023-01-05 15:44:23 +0000161void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300162{
David Horstmannceeaeb92023-01-05 15:44:23 +0000163 CHACHA20_VALIDATE(ctx != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300164
David Horstmannceeaeb92023-01-05 15:44:23 +0000165 mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
166 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Hanno Becker305e4e42018-12-11 15:03:16 +0000167
168 /* Initially, there's no keystream bytes available */
169 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300170}
171
David Horstmannceeaeb92023-01-05 15:44:23 +0000172void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300173{
David Horstmannceeaeb92023-01-05 15:44:23 +0000174 if (ctx != NULL) {
175 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
Daniel King34b822c2016-05-15 17:28:08 -0300176 }
177}
178
David Horstmannceeaeb92023-01-05 15:44:23 +0000179int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
180 const unsigned char key[32])
Daniel King34b822c2016-05-15 17:28:08 -0300181{
David Horstmannceeaeb92023-01-05 15:44:23 +0000182 CHACHA20_VALIDATE_RET(ctx != NULL);
183 CHACHA20_VALIDATE_RET(key != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300184
185 /* ChaCha20 constants - the string "expand 32-byte k" */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200186 ctx->state[0] = 0x61707865;
187 ctx->state[1] = 0x3320646e;
188 ctx->state[2] = 0x79622d32;
189 ctx->state[3] = 0x6b206574;
Daniel King34b822c2016-05-15 17:28:08 -0300190
191 /* Set key */
David Horstmannceeaeb92023-01-05 15:44:23 +0000192 ctx->state[4] = MBEDTLS_GET_UINT32_LE(key, 0);
193 ctx->state[5] = MBEDTLS_GET_UINT32_LE(key, 4);
194 ctx->state[6] = MBEDTLS_GET_UINT32_LE(key, 8);
195 ctx->state[7] = MBEDTLS_GET_UINT32_LE(key, 12);
196 ctx->state[8] = MBEDTLS_GET_UINT32_LE(key, 16);
197 ctx->state[9] = MBEDTLS_GET_UINT32_LE(key, 20);
198 ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24);
199 ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28);
Daniel King34b822c2016-05-15 17:28:08 -0300200
David Horstmannceeaeb92023-01-05 15:44:23 +0000201 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300202}
203
David Horstmannceeaeb92023-01-05 15:44:23 +0000204int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
205 const unsigned char nonce[12],
206 uint32_t counter)
Daniel King34b822c2016-05-15 17:28:08 -0300207{
David Horstmannceeaeb92023-01-05 15:44:23 +0000208 CHACHA20_VALIDATE_RET(ctx != NULL);
209 CHACHA20_VALIDATE_RET(nonce != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300210
211 /* Counter */
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200212 ctx->state[12] = counter;
Daniel King34b822c2016-05-15 17:28:08 -0300213
214 /* Nonce */
David Horstmannceeaeb92023-01-05 15:44:23 +0000215 ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0);
216 ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4);
217 ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8);
Daniel King34b822c2016-05-15 17:28:08 -0300218
David Horstmannceeaeb92023-01-05 15:44:23 +0000219 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
Manuel Pégourié-Gonnard55c0d092018-05-09 12:37:58 +0200220
221 /* Initially, there's no keystream bytes available */
222 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
223
David Horstmannceeaeb92023-01-05 15:44:23 +0000224 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300225}
226
David Horstmannceeaeb92023-01-05 15:44:23 +0000227int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
228 size_t size,
229 const unsigned char *input,
230 unsigned char *output)
Daniel King34b822c2016-05-15 17:28:08 -0300231{
232 size_t offset = 0U;
233 size_t i;
234
David Horstmannceeaeb92023-01-05 15:44:23 +0000235 CHACHA20_VALIDATE_RET(ctx != NULL);
236 CHACHA20_VALIDATE_RET(size == 0 || input != NULL);
237 CHACHA20_VALIDATE_RET(size == 0 || output != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300238
239 /* Use leftover keystream bytes, if available */
David Horstmannceeaeb92023-01-05 15:44:23 +0000240 while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200241 output[offset] = input[offset]
David Horstmannceeaeb92023-01-05 15:44:23 +0000242 ^ ctx->keystream8[ctx->keystream_bytes_used];
Daniel King34b822c2016-05-15 17:28:08 -0300243
244 ctx->keystream_bytes_used++;
245 offset++;
246 size--;
247 }
248
249 /* Process full blocks */
David Horstmannceeaeb92023-01-05 15:44:23 +0000250 while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200251 /* Generate new keystream block and increment counter */
David Horstmannceeaeb92023-01-05 15:44:23 +0000252 chacha20_block(ctx->state, ctx->keystream8);
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200253 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300254
David Horstmannceeaeb92023-01-05 15:44:23 +0000255 for (i = 0U; i < 64U; i += 8U) {
256 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200257 output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
258 output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
259 output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
260 output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
261 output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
262 output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
263 output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
Daniel King34b822c2016-05-15 17:28:08 -0300264 }
265
Daniel Kingb8025c52016-05-17 14:43:01 -0300266 offset += CHACHA20_BLOCK_SIZE_BYTES;
267 size -= CHACHA20_BLOCK_SIZE_BYTES;
Daniel King34b822c2016-05-15 17:28:08 -0300268 }
269
270 /* Last (partial) block */
David Horstmannceeaeb92023-01-05 15:44:23 +0000271 if (size > 0U) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200272 /* Generate new keystream block and increment counter */
David Horstmannceeaeb92023-01-05 15:44:23 +0000273 chacha20_block(ctx->state, ctx->keystream8);
Manuel Pégourié-Gonnard98fae6d2018-05-24 17:23:41 +0200274 ctx->state[CHACHA20_CTR_INDEX]++;
Daniel King34b822c2016-05-15 17:28:08 -0300275
David Horstmannceeaeb92023-01-05 15:44:23 +0000276 for (i = 0U; i < size; i++) {
Daniel King34b822c2016-05-15 17:28:08 -0300277 output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
278 }
279
280 ctx->keystream_bytes_used = size;
281
Daniel King34b822c2016-05-15 17:28:08 -0300282 }
283
David Horstmannceeaeb92023-01-05 15:44:23 +0000284 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300285}
286
David Horstmannceeaeb92023-01-05 15:44:23 +0000287int mbedtls_chacha20_crypt(const unsigned char key[32],
288 const unsigned char nonce[12],
289 uint32_t counter,
290 size_t data_len,
291 const unsigned char *input,
292 unsigned char *output)
Daniel King34b822c2016-05-15 17:28:08 -0300293{
294 mbedtls_chacha20_context ctx;
Janos Follath24eed8d2019-11-22 13:21:35 +0000295 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300296
David Horstmannceeaeb92023-01-05 15:44:23 +0000297 CHACHA20_VALIDATE_RET(key != NULL);
298 CHACHA20_VALIDATE_RET(nonce != NULL);
299 CHACHA20_VALIDATE_RET(data_len == 0 || input != NULL);
300 CHACHA20_VALIDATE_RET(data_len == 0 || output != NULL);
Hanno Becker305e4e42018-12-11 15:03:16 +0000301
David Horstmannceeaeb92023-01-05 15:44:23 +0000302 mbedtls_chacha20_init(&ctx);
Daniel King34b822c2016-05-15 17:28:08 -0300303
David Horstmannceeaeb92023-01-05 15:44:23 +0000304 ret = mbedtls_chacha20_setkey(&ctx, key);
305 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300306 goto cleanup;
David Horstmannceeaeb92023-01-05 15:44:23 +0000307 }
Daniel King34b822c2016-05-15 17:28:08 -0300308
David Horstmannceeaeb92023-01-05 15:44:23 +0000309 ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
310 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300311 goto cleanup;
David Horstmannceeaeb92023-01-05 15:44:23 +0000312 }
Daniel King34b822c2016-05-15 17:28:08 -0300313
David Horstmannceeaeb92023-01-05 15:44:23 +0000314 ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
Daniel King34b822c2016-05-15 17:28:08 -0300315
316cleanup:
David Horstmannceeaeb92023-01-05 15:44:23 +0000317 mbedtls_chacha20_free(&ctx);
318 return ret;
Daniel King34b822c2016-05-15 17:28:08 -0300319}
320
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200321#endif /* !MBEDTLS_CHACHA20_ALT */
322
Daniel King34b822c2016-05-15 17:28:08 -0300323#if defined(MBEDTLS_SELF_TEST)
324
325static const unsigned char test_keys[2][32] =
326{
327 {
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 },
333 {
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
338 }
339};
340
341static const unsigned char test_nonces[2][12] =
342{
343 {
344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345 0x00, 0x00, 0x00, 0x00
346 },
347 {
348 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
349 0x00, 0x00, 0x00, 0x02
350 }
351};
352
353static const uint32_t test_counters[2] =
354{
355 0U,
356 1U
357};
358
359static const unsigned char test_input[2][375] =
360{
361 {
362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
370 },
371 {
372 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
373 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
374 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
375 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
376 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
377 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
378 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
379 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
380 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
381 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
382 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
383 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
384 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
385 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
386 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
387 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
388 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
389 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
390 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
391 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
392 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
393 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
394 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
395 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
396 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
397 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
398 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
399 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
400 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
401 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
402 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
403 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
404 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
405 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
406 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
407 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
408 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
409 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
410 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
411 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
412 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
413 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
414 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
415 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
416 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
417 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
418 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
419 }
420};
421
422static const unsigned char test_output[2][375] =
423{
424 {
425 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
426 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
427 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
428 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
429 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
430 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
431 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
432 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
433 },
434 {
435 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
436 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
437 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
438 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
439 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
440 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
441 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
442 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
443 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
444 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
445 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
446 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
447 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
448 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
449 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
450 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
451 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
452 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
453 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
454 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
455 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
456 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
457 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
458 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
459 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
460 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
461 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
462 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
463 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
464 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
465 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
466 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
467 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
468 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
469 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
470 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
471 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
472 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
473 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
474 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
475 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
476 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
477 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
478 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
479 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
480 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
481 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
482 }
483};
484
485static const size_t test_lengths[2] =
486{
487 64U,
488 375U
489};
490
Ouss4e0b26872020-08-11 16:07:09 +0100491/* Make sure no other definition is already present. */
492#undef ASSERT
493
David Horstmannceeaeb92023-01-05 15:44:23 +0000494#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200495 do \
496 { \
David Horstmannceeaeb92023-01-05 15:44:23 +0000497 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200498 { \
David Horstmannceeaeb92023-01-05 15:44:23 +0000499 if (verbose != 0) \
500 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200501 \
David Horstmannceeaeb92023-01-05 15:44:23 +0000502 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200503 } \
504 } \
David Horstmannceeaeb92023-01-05 15:44:23 +0000505 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200506
David Horstmannceeaeb92023-01-05 15:44:23 +0000507int mbedtls_chacha20_self_test(int verbose)
Daniel King34b822c2016-05-15 17:28:08 -0300508{
509 unsigned char output[381];
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200510 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000511 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel King34b822c2016-05-15 17:28:08 -0300512
David Horstmannceeaeb92023-01-05 15:44:23 +0000513 for (i = 0U; i < 2U; i++) {
514 if (verbose != 0) {
515 mbedtls_printf(" ChaCha20 test %u ", i);
516 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300517
David Horstmannceeaeb92023-01-05 15:44:23 +0000518 ret = mbedtls_chacha20_crypt(test_keys[i],
519 test_nonces[i],
520 test_counters[i],
521 test_lengths[i],
522 test_input[i],
523 output);
Daniel King34b822c2016-05-15 17:28:08 -0300524
David Horstmannceeaeb92023-01-05 15:44:23 +0000525 ASSERT(0 == ret, ("error code: %i\n", ret));
Daniel King34b822c2016-05-15 17:28:08 -0300526
David Horstmannceeaeb92023-01-05 15:44:23 +0000527 ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
528 ("failed (output)\n"));
Daniel King34b822c2016-05-15 17:28:08 -0300529
David Horstmannceeaeb92023-01-05 15:44:23 +0000530 if (verbose != 0) {
531 mbedtls_printf("passed\n");
532 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300533 }
534
David Horstmannceeaeb92023-01-05 15:44:23 +0000535 if (verbose != 0) {
536 mbedtls_printf("\n");
537 }
Daniel King34b822c2016-05-15 17:28:08 -0300538
David Horstmannceeaeb92023-01-05 15:44:23 +0000539 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300540}
541
542#endif /* MBEDTLS_SELF_TEST */
543
544#endif /* !MBEDTLS_CHACHA20_C */