Coverage Report

Created: 2025-03-01 06:26

/src/mbedtls/library/chacha20.c
Line
Count
Source (jump to first uncovered line)
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 OR GPL-2.0-or-later
10
 */
11
12
#include "common.h"
13
14
#if defined(MBEDTLS_CHACHA20_C)
15
16
#include "mbedtls/chacha20.h"
17
#include "mbedtls/platform_util.h"
18
#include "mbedtls/error.h"
19
20
#include <stddef.h>
21
#include <string.h>
22
23
#include "mbedtls/platform.h"
24
25
#if !defined(MBEDTLS_CHACHA20_ALT)
26
27
#define ROTL32(value, amount) \
28
0
    ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
29
30
0
#define CHACHA20_CTR_INDEX (12U)
31
32
0
#define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
33
34
/**
35
 * \brief           ChaCha20 quarter round operation.
36
 *
37
 *                  The quarter round is defined as follows (from RFC 7539):
38
 *                      1.  a += b; d ^= a; d <<<= 16;
39
 *                      2.  c += d; b ^= c; b <<<= 12;
40
 *                      3.  a += b; d ^= a; d <<<= 8;
41
 *                      4.  c += d; b ^= c; b <<<= 7;
42
 *
43
 * \param state     ChaCha20 state to modify.
44
 * \param a         The index of 'a' in the state.
45
 * \param b         The index of 'b' in the state.
46
 * \param c         The index of 'c' in the state.
47
 * \param d         The index of 'd' in the state.
48
 */
49
static inline void chacha20_quarter_round(uint32_t state[16],
50
                                          size_t a,
51
                                          size_t b,
52
                                          size_t c,
53
                                          size_t d)
54
0
{
55
    /* a += b; d ^= a; d <<<= 16; */
56
0
    state[a] += state[b];
57
0
    state[d] ^= state[a];
58
0
    state[d] = ROTL32(state[d], 16);
59
60
    /* c += d; b ^= c; b <<<= 12 */
61
0
    state[c] += state[d];
62
0
    state[b] ^= state[c];
63
0
    state[b] = ROTL32(state[b], 12);
64
65
    /* a += b; d ^= a; d <<<= 8; */
66
0
    state[a] += state[b];
67
0
    state[d] ^= state[a];
68
0
    state[d] = ROTL32(state[d], 8);
69
70
    /* c += d; b ^= c; b <<<= 7; */
71
0
    state[c] += state[d];
72
0
    state[b] ^= state[c];
73
0
    state[b] = ROTL32(state[b], 7);
74
0
}
75
76
/**
77
 * \brief           Perform the ChaCha20 inner block operation.
78
 *
79
 *                  This function performs two rounds: the column round and the
80
 *                  diagonal round.
81
 *
82
 * \param state     The ChaCha20 state to update.
83
 */
84
static void chacha20_inner_block(uint32_t state[16])
85
0
{
86
0
    chacha20_quarter_round(state, 0, 4, 8,  12);
87
0
    chacha20_quarter_round(state, 1, 5, 9,  13);
88
0
    chacha20_quarter_round(state, 2, 6, 10, 14);
89
0
    chacha20_quarter_round(state, 3, 7, 11, 15);
90
91
0
    chacha20_quarter_round(state, 0, 5, 10, 15);
92
0
    chacha20_quarter_round(state, 1, 6, 11, 12);
93
0
    chacha20_quarter_round(state, 2, 7, 8,  13);
94
0
    chacha20_quarter_round(state, 3, 4, 9,  14);
95
0
}
96
97
/**
98
 * \brief               Generates a keystream block.
99
 *
100
 * \param initial_state The initial ChaCha20 state (key, nonce, counter).
101
 * \param keystream     Generated keystream bytes are written to this buffer.
102
 */
103
static void chacha20_block(const uint32_t initial_state[16],
104
                           unsigned char keystream[64])
105
0
{
106
0
    uint32_t working_state[16];
107
0
    size_t i;
108
109
0
    memcpy(working_state,
110
0
           initial_state,
111
0
           CHACHA20_BLOCK_SIZE_BYTES);
112
113
0
    for (i = 0U; i < 10U; i++) {
114
0
        chacha20_inner_block(working_state);
115
0
    }
116
117
0
    working_state[0] += initial_state[0];
118
0
    working_state[1] += initial_state[1];
119
0
    working_state[2] += initial_state[2];
120
0
    working_state[3] += initial_state[3];
121
0
    working_state[4] += initial_state[4];
122
0
    working_state[5] += initial_state[5];
123
0
    working_state[6] += initial_state[6];
124
0
    working_state[7] += initial_state[7];
125
0
    working_state[8] += initial_state[8];
126
0
    working_state[9] += initial_state[9];
127
0
    working_state[10] += initial_state[10];
128
0
    working_state[11] += initial_state[11];
129
0
    working_state[12] += initial_state[12];
130
0
    working_state[13] += initial_state[13];
131
0
    working_state[14] += initial_state[14];
132
0
    working_state[15] += initial_state[15];
133
134
0
    for (i = 0U; i < 16; i++) {
135
0
        size_t offset = i * 4U;
136
137
0
        MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
138
0
    }
139
140
0
    mbedtls_platform_zeroize(working_state, sizeof(working_state));
141
0
}
142
143
void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
144
0
{
145
0
    mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
146
0
    mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
147
148
    /* Initially, there's no keystream bytes available */
149
0
    ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
150
0
}
151
152
void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
153
0
{
154
0
    if (ctx != NULL) {
155
0
        mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
156
0
    }
157
0
}
158
159
int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
160
                            const unsigned char key[32])
161
0
{
162
    /* ChaCha20 constants - the string "expand 32-byte k" */
163
0
    ctx->state[0] = 0x61707865;
164
0
    ctx->state[1] = 0x3320646e;
165
0
    ctx->state[2] = 0x79622d32;
166
0
    ctx->state[3] = 0x6b206574;
167
168
    /* Set key */
169
0
    ctx->state[4]  = MBEDTLS_GET_UINT32_LE(key, 0);
170
0
    ctx->state[5]  = MBEDTLS_GET_UINT32_LE(key, 4);
171
0
    ctx->state[6]  = MBEDTLS_GET_UINT32_LE(key, 8);
172
0
    ctx->state[7]  = MBEDTLS_GET_UINT32_LE(key, 12);
173
0
    ctx->state[8]  = MBEDTLS_GET_UINT32_LE(key, 16);
174
0
    ctx->state[9]  = MBEDTLS_GET_UINT32_LE(key, 20);
175
0
    ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24);
176
0
    ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28);
177
178
0
    return 0;
179
0
}
180
181
int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
182
                            const unsigned char nonce[12],
183
                            uint32_t counter)
184
0
{
185
    /* Counter */
186
0
    ctx->state[12] = counter;
187
188
    /* Nonce */
189
0
    ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0);
190
0
    ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4);
191
0
    ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8);
192
193
0
    mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
194
195
    /* Initially, there's no keystream bytes available */
196
0
    ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
197
198
0
    return 0;
199
0
}
200
201
int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
202
                            size_t size,
203
                            const unsigned char *input,
204
                            unsigned char *output)
205
0
{
206
0
    size_t offset = 0U;
207
208
    /* Use leftover keystream bytes, if available */
209
0
    while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
210
0
        output[offset] = input[offset]
211
0
                         ^ ctx->keystream8[ctx->keystream_bytes_used];
212
213
0
        ctx->keystream_bytes_used++;
214
0
        offset++;
215
0
        size--;
216
0
    }
217
218
    /* Process full blocks */
219
0
    while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
220
        /* Generate new keystream block and increment counter */
221
0
        chacha20_block(ctx->state, ctx->keystream8);
222
0
        ctx->state[CHACHA20_CTR_INDEX]++;
223
224
0
        mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U);
225
226
0
        offset += CHACHA20_BLOCK_SIZE_BYTES;
227
0
        size   -= CHACHA20_BLOCK_SIZE_BYTES;
228
0
    }
229
230
    /* Last (partial) block */
231
0
    if (size > 0U) {
232
        /* Generate new keystream block and increment counter */
233
0
        chacha20_block(ctx->state, ctx->keystream8);
234
0
        ctx->state[CHACHA20_CTR_INDEX]++;
235
236
0
        mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);
237
238
0
        ctx->keystream_bytes_used = size;
239
240
0
    }
241
242
0
    return 0;
243
0
}
244
245
int mbedtls_chacha20_crypt(const unsigned char key[32],
246
                           const unsigned char nonce[12],
247
                           uint32_t counter,
248
                           size_t data_len,
249
                           const unsigned char *input,
250
                           unsigned char *output)
251
0
{
252
0
    mbedtls_chacha20_context ctx;
253
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
254
255
0
    mbedtls_chacha20_init(&ctx);
256
257
0
    ret = mbedtls_chacha20_setkey(&ctx, key);
258
0
    if (ret != 0) {
259
0
        goto cleanup;
260
0
    }
261
262
0
    ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
263
0
    if (ret != 0) {
264
0
        goto cleanup;
265
0
    }
266
267
0
    ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
268
269
0
cleanup:
270
0
    mbedtls_chacha20_free(&ctx);
271
0
    return ret;
272
0
}
273
274
#endif /* !MBEDTLS_CHACHA20_ALT */
275
276
#if defined(MBEDTLS_SELF_TEST)
277
278
static const unsigned char test_keys[2][32] =
279
{
280
    {
281
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
282
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
285
    },
286
    {
287
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
288
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
291
    }
292
};
293
294
static const unsigned char test_nonces[2][12] =
295
{
296
    {
297
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298
        0x00, 0x00, 0x00, 0x00
299
    },
300
    {
301
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302
        0x00, 0x00, 0x00, 0x02
303
    }
304
};
305
306
static const uint32_t test_counters[2] =
307
{
308
    0U,
309
    1U
310
};
311
312
static const unsigned char test_input[2][375] =
313
{
314
    {
315
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
323
    },
324
    {
325
        0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
326
        0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
327
        0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
328
        0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
329
        0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
330
        0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
331
        0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
332
        0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
333
        0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
334
        0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
335
        0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
336
        0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
337
        0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
338
        0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
339
        0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
340
        0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
341
        0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
342
        0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
343
        0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
344
        0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
345
        0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
346
        0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
347
        0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
348
        0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
349
        0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
350
        0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
351
        0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
352
        0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
353
        0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
354
        0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
355
        0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
356
        0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
357
        0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
358
        0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
359
        0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
360
        0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
361
        0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
362
        0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
363
        0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
364
        0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
365
        0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
366
        0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
367
        0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
368
        0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
369
        0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
370
        0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
371
        0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
372
    }
373
};
374
375
static const unsigned char test_output[2][375] =
376
{
377
    {
378
        0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
379
        0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
380
        0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
381
        0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
382
        0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
383
        0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
384
        0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
385
        0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
386
    },
387
    {
388
        0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
389
        0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
390
        0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
391
        0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
392
        0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
393
        0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
394
        0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
395
        0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
396
        0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
397
        0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
398
        0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
399
        0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
400
        0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
401
        0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
402
        0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
403
        0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
404
        0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
405
        0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
406
        0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
407
        0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
408
        0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
409
        0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
410
        0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
411
        0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
412
        0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
413
        0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
414
        0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
415
        0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
416
        0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
417
        0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
418
        0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
419
        0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
420
        0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
421
        0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
422
        0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
423
        0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
424
        0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
425
        0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
426
        0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
427
        0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
428
        0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
429
        0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
430
        0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
431
        0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
432
        0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
433
        0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
434
        0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
435
    }
436
};
437
438
static const size_t test_lengths[2] =
439
{
440
    64U,
441
    375U
442
};
443
444
/* Make sure no other definition is already present. */
445
#undef ASSERT
446
447
#define ASSERT(cond, args)            \
448
0
    do                                  \
449
0
    {                                   \
450
0
        if (!(cond))                \
451
0
        {                               \
452
0
            if (verbose != 0)          \
453
0
            mbedtls_printf args;    \
454
0
                                        \
455
0
            return -1;               \
456
0
        }                               \
457
0
    }                                   \
458
0
    while (0)
459
460
int mbedtls_chacha20_self_test(int verbose)
461
0
{
462
0
    unsigned char output[381];
463
0
    unsigned i;
464
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
465
466
0
    for (i = 0U; i < 2U; i++) {
467
0
        if (verbose != 0) {
468
0
            mbedtls_printf("  ChaCha20 test %u ", i);
469
0
        }
470
471
0
        ret = mbedtls_chacha20_crypt(test_keys[i],
472
0
                                     test_nonces[i],
473
0
                                     test_counters[i],
474
0
                                     test_lengths[i],
475
0
                                     test_input[i],
476
0
                                     output);
477
478
0
        ASSERT(0 == ret, ("error code: %i\n", ret));
479
480
0
        ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
481
0
               ("failed (output)\n"));
482
483
0
        if (verbose != 0) {
484
0
            mbedtls_printf("passed\n");
485
0
        }
486
0
    }
487
488
0
    if (verbose != 0) {
489
0
        mbedtls_printf("\n");
490
0
    }
491
492
0
    return 0;
493
0
}
494
495
#endif /* MBEDTLS_SELF_TEST */
496
497
#endif /* !MBEDTLS_CHACHA20_C */