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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010040#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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010045#define ROTL32(value, amount) \
46 ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
Daniel King34b822c2016-05-15 17:28:08 -030047
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010048#define CHACHA20_CTR_INDEX (12U)
Daniel King34b822c2016-05-15 17:28:08 -030049
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010050#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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010067static 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];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010076 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];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010081 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];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010086 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];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010091 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100102static void chacha20_inner_block(uint32_t state[16])
Daniel King34b822c2016-05-15 17:28:08 -0300103{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100104 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100109 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100121static 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100127 memcpy(working_state,
128 initial_state,
129 CHACHA20_BLOCK_SIZE_BYTES);
Daniel King34b822c2016-05-15 17:28:08 -0300130
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100131 for (i = 0U; i < 10U; i++) {
132 chacha20_inner_block(working_state);
133 }
Daniel King34b822c2016-05-15 17:28:08 -0300134
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100135 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100152 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100158 mbedtls_platform_zeroize(working_state, sizeof(working_state));
Daniel King34b822c2016-05-15 17:28:08 -0300159}
160
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100161void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300162{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100163 CHACHA20_VALIDATE(ctx != NULL);
Daniel King34b822c2016-05-15 17:28:08 -0300164
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100165 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100172void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
Daniel King34b822c2016-05-15 17:28:08 -0300173{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100174 if (ctx != NULL) {
175 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
Daniel King34b822c2016-05-15 17:28:08 -0300176 }
177}
178
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100179int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
180 const unsigned char key[32])
Daniel King34b822c2016-05-15 17:28:08 -0300181{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100182 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100192 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100201 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300202}
203
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100204int 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{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100208 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100215 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100224 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300225}
226
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100227int 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100235 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100240 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]
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100242 ^ 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100250 while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200251 /* Generate new keystream block and increment counter */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100252 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100255 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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100271 if (size > 0U) {
Manuel Pégourié-Gonnard502f1892018-05-07 11:57:05 +0200272 /* Generate new keystream block and increment counter */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100273 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100276 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100284 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300285}
286
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100287int 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100297 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100302 mbedtls_chacha20_init(&ctx);
Daniel King34b822c2016-05-15 17:28:08 -0300303
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100304 ret = mbedtls_chacha20_setkey(&ctx, key);
305 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300306 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100307 }
Daniel King34b822c2016-05-15 17:28:08 -0300308
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100309 ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
310 if (ret != 0) {
Daniel King34b822c2016-05-15 17:28:08 -0300311 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100312 }
Daniel King34b822c2016-05-15 17:28:08 -0300313
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100314 ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
Daniel King34b822c2016-05-15 17:28:08 -0300315
316cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100317 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100494#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200495 do \
496 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100497 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200498 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100499 if (verbose != 0) \
500 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200501 \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100502 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200503 } \
504 } \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100505 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200506
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100507int 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100513 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100518 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
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100525 ASSERT(0 == ret, ("error code: %i\n", ret));
Daniel King34b822c2016-05-15 17:28:08 -0300526
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100527 ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
528 ("failed (output)\n"));
Daniel King34b822c2016-05-15 17:28:08 -0300529
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100530 if (verbose != 0) {
531 mbedtls_printf("passed\n");
532 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300533 }
534
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100535 if (verbose != 0) {
536 mbedtls_printf("\n");
537 }
Daniel King34b822c2016-05-15 17:28:08 -0300538
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100539 return 0;
Daniel King34b822c2016-05-15 17:28:08 -0300540}
541
542#endif /* MBEDTLS_SELF_TEST */
543
544#endif /* !MBEDTLS_CHACHA20_C */