1 /**
2 * \file chacha20.c
3 *
4 * \brief ChaCha20 cipher.
5 *
6 * \author Daniel King <damaki.gh@gmail.com>
7 *
8 * Copyright The Mbed TLS Contributors
9 * 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.
22 */
23
24 #include "common.h"
25
26 #if defined(MBEDTLS_CHACHA20_C)
27
28 #include "mbedtls/chacha20.h"
29 #include "mbedtls/platform_util.h"
30 #include "mbedtls/error.h"
31
32 #include <stddef.h>
33 #include <string.h>
34
35 #include "mbedtls/platform.h"
36
37 #if !defined(MBEDTLS_CHACHA20_ALT)
38
39 #define ROTL32(value, amount) \
40 ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
41
42 #define CHACHA20_CTR_INDEX (12U)
43
44 #define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
45
46 /**
47 * \brief ChaCha20 quarter round operation.
48 *
49 * The quarter round is defined as follows (from RFC 7539):
50 * 1. a += b; d ^= a; d <<<= 16;
51 * 2. c += d; b ^= c; b <<<= 12;
52 * 3. a += b; d ^= a; d <<<= 8;
53 * 4. c += d; b ^= c; b <<<= 7;
54 *
55 * \param state ChaCha20 state to modify.
56 * \param a The index of 'a' in the state.
57 * \param b The index of 'b' in the state.
58 * \param c The index of 'c' in the state.
59 * \param d The index of 'd' in the state.
60 */
chacha20_quarter_round(uint32_t state[16],size_t a,size_t b,size_t c,size_t d)61 static 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)
66 {
67 /* a += b; d ^= a; d <<<= 16; */
68 state[a] += state[b];
69 state[d] ^= state[a];
70 state[d] = ROTL32(state[d], 16);
71
72 /* c += d; b ^= c; b <<<= 12 */
73 state[c] += state[d];
74 state[b] ^= state[c];
75 state[b] = ROTL32(state[b], 12);
76
77 /* a += b; d ^= a; d <<<= 8; */
78 state[a] += state[b];
79 state[d] ^= state[a];
80 state[d] = ROTL32(state[d], 8);
81
82 /* c += d; b ^= c; b <<<= 7; */
83 state[c] += state[d];
84 state[b] ^= state[c];
85 state[b] = ROTL32(state[b], 7);
86 }
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 */
chacha20_inner_block(uint32_t state[16])96 static void chacha20_inner_block(uint32_t state[16])
97 {
98 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);
102
103 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);
107 }
108
109 /**
110 * \brief Generates a keystream block.
111 *
112 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
113 * \param keystream Generated keystream bytes are written to this buffer.
114 */
chacha20_block(const uint32_t initial_state[16],unsigned char keystream[64])115 static void chacha20_block(const uint32_t initial_state[16],
116 unsigned char keystream[64])
117 {
118 uint32_t working_state[16];
119 size_t i;
120
121 memcpy(working_state,
122 initial_state,
123 CHACHA20_BLOCK_SIZE_BYTES);
124
125 for (i = 0U; i < 10U; i++) {
126 chacha20_inner_block(working_state);
127 }
128
129 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];
139 working_state[10] += initial_state[10];
140 working_state[11] += initial_state[11];
141 working_state[12] += initial_state[12];
142 working_state[13] += initial_state[13];
143 working_state[14] += initial_state[14];
144 working_state[15] += initial_state[15];
145
146 for (i = 0U; i < 16; i++) {
147 size_t offset = i * 4U;
148
149 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
150 }
151
152 mbedtls_platform_zeroize(working_state, sizeof(working_state));
153 }
154
mbedtls_chacha20_init(mbedtls_chacha20_context * ctx)155 void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
156 {
157 mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
158 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
159
160 /* Initially, there's no keystream bytes available */
161 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
162 }
163
mbedtls_chacha20_free(mbedtls_chacha20_context * ctx)164 void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
165 {
166 if (ctx != NULL) {
167 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
168 }
169 }
170
mbedtls_chacha20_setkey(mbedtls_chacha20_context * ctx,const unsigned char key[32])171 int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
172 const unsigned char key[32])
173 {
174 /* ChaCha20 constants - the string "expand 32-byte k" */
175 ctx->state[0] = 0x61707865;
176 ctx->state[1] = 0x3320646e;
177 ctx->state[2] = 0x79622d32;
178 ctx->state[3] = 0x6b206574;
179
180 /* Set key */
181 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);
189
190 return 0;
191 }
192
mbedtls_chacha20_starts(mbedtls_chacha20_context * ctx,const unsigned char nonce[12],uint32_t counter)193 int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
194 const unsigned char nonce[12],
195 uint32_t counter)
196 {
197 /* Counter */
198 ctx->state[12] = counter;
199
200 /* Nonce */
201 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);
204
205 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
206
207 /* Initially, there's no keystream bytes available */
208 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
209
210 return 0;
211 }
212
mbedtls_chacha20_update(mbedtls_chacha20_context * ctx,size_t size,const unsigned char * input,unsigned char * output)213 int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
214 size_t size,
215 const unsigned char *input,
216 unsigned char *output)
217 {
218 size_t offset = 0U;
219
220 /* Use leftover keystream bytes, if available */
221 while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
222 output[offset] = input[offset]
223 ^ ctx->keystream8[ctx->keystream_bytes_used];
224
225 ctx->keystream_bytes_used++;
226 offset++;
227 size--;
228 }
229
230 /* Process full blocks */
231 while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
232 /* Generate new keystream block and increment counter */
233 chacha20_block(ctx->state, ctx->keystream8);
234 ctx->state[CHACHA20_CTR_INDEX]++;
235
236 mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U);
237
238 offset += CHACHA20_BLOCK_SIZE_BYTES;
239 size -= CHACHA20_BLOCK_SIZE_BYTES;
240 }
241
242 /* Last (partial) block */
243 if (size > 0U) {
244 /* Generate new keystream block and increment counter */
245 chacha20_block(ctx->state, ctx->keystream8);
246 ctx->state[CHACHA20_CTR_INDEX]++;
247
248 mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);
249
250 ctx->keystream_bytes_used = size;
251
252 }
253
254 return 0;
255 }
256
mbedtls_chacha20_crypt(const unsigned char key[32],const unsigned char nonce[12],uint32_t counter,size_t data_len,const unsigned char * input,unsigned char * output)257 int 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)
263 {
264 mbedtls_chacha20_context ctx;
265 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
266
267 mbedtls_chacha20_init(&ctx);
268
269 ret = mbedtls_chacha20_setkey(&ctx, key);
270 if (ret != 0) {
271 goto cleanup;
272 }
273
274 ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
275 if (ret != 0) {
276 goto cleanup;
277 }
278
279 ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
280
281 cleanup:
282 mbedtls_chacha20_free(&ctx);
283 return ret;
284 }
285
286 #endif /* !MBEDTLS_CHACHA20_ALT */
287
288 #if defined(MBEDTLS_SELF_TEST)
289
290 static 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
306 static 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
318 static const uint32_t test_counters[2] =
319 {
320 0U,
321 1U
322 };
323
324 static 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
387 static 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
450 static const size_t test_lengths[2] =
451 {
452 64U,
453 375U
454 };
455
456 /* Make sure no other definition is already present. */
457 #undef ASSERT
458
459 #define ASSERT(cond, args) \
460 do \
461 { \
462 if (!(cond)) \
463 { \
464 if (verbose != 0) \
465 mbedtls_printf args; \
466 \
467 return -1; \
468 } \
469 } \
470 while (0)
471
mbedtls_chacha20_self_test(int verbose)472 int mbedtls_chacha20_self_test(int verbose)
473 {
474 unsigned char output[381];
475 unsigned i;
476 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
477
478 for (i = 0U; i < 2U; i++) {
479 if (verbose != 0) {
480 mbedtls_printf(" ChaCha20 test %u ", i);
481 }
482
483 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);
489
490 ASSERT(0 == ret, ("error code: %i\n", ret));
491
492 ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
493 ("failed (output)\n"));
494
495 if (verbose != 0) {
496 mbedtls_printf("passed\n");
497 }
498 }
499
500 if (verbose != 0) {
501 mbedtls_printf("\n");
502 }
503
504 return 0;
505 }
506
507 #endif /* MBEDTLS_SELF_TEST */
508
509 #endif /* !MBEDTLS_CHACHA20_C */
510