Coverage Report

Created: 2024-11-21 07:03

/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
28.1k
    ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
29
30
88
#define CHACHA20_CTR_INDEX (12U)
31
32
534
#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
7.04k
{
55
    /* a += b; d ^= a; d <<<= 16; */
56
7.04k
    state[a] += state[b];
57
7.04k
    state[d] ^= state[a];
58
7.04k
    state[d] = ROTL32(state[d], 16);
59
60
    /* c += d; b ^= c; b <<<= 12 */
61
7.04k
    state[c] += state[d];
62
7.04k
    state[b] ^= state[c];
63
7.04k
    state[b] = ROTL32(state[b], 12);
64
65
    /* a += b; d ^= a; d <<<= 8; */
66
7.04k
    state[a] += state[b];
67
7.04k
    state[d] ^= state[a];
68
7.04k
    state[d] = ROTL32(state[d], 8);
69
70
    /* c += d; b ^= c; b <<<= 7; */
71
7.04k
    state[c] += state[d];
72
7.04k
    state[b] ^= state[c];
73
7.04k
    state[b] = ROTL32(state[b], 7);
74
7.04k
}
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
880
{
86
880
    chacha20_quarter_round(state, 0, 4, 8,  12);
87
880
    chacha20_quarter_round(state, 1, 5, 9,  13);
88
880
    chacha20_quarter_round(state, 2, 6, 10, 14);
89
880
    chacha20_quarter_round(state, 3, 7, 11, 15);
90
91
880
    chacha20_quarter_round(state, 0, 5, 10, 15);
92
880
    chacha20_quarter_round(state, 1, 6, 11, 12);
93
880
    chacha20_quarter_round(state, 2, 7, 8,  13);
94
880
    chacha20_quarter_round(state, 3, 4, 9,  14);
95
880
}
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
88
{
106
88
    uint32_t working_state[16];
107
88
    size_t i;
108
109
88
    memcpy(working_state,
110
88
           initial_state,
111
88
           CHACHA20_BLOCK_SIZE_BYTES);
112
113
968
    for (i = 0U; i < 10U; i++) {
114
880
        chacha20_inner_block(working_state);
115
880
    }
116
117
88
    working_state[0] += initial_state[0];
118
88
    working_state[1] += initial_state[1];
119
88
    working_state[2] += initial_state[2];
120
88
    working_state[3] += initial_state[3];
121
88
    working_state[4] += initial_state[4];
122
88
    working_state[5] += initial_state[5];
123
88
    working_state[6] += initial_state[6];
124
88
    working_state[7] += initial_state[7];
125
88
    working_state[8] += initial_state[8];
126
88
    working_state[9] += initial_state[9];
127
88
    working_state[10] += initial_state[10];
128
88
    working_state[11] += initial_state[11];
129
88
    working_state[12] += initial_state[12];
130
88
    working_state[13] += initial_state[13];
131
88
    working_state[14] += initial_state[14];
132
88
    working_state[15] += initial_state[15];
133
134
1.49k
    for (i = 0U; i < 16; i++) {
135
1.40k
        size_t offset = i * 4U;
136
137
1.40k
        MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
138
1.40k
    }
139
140
88
    mbedtls_platform_zeroize(working_state, sizeof(working_state));
141
88
}
142
143
void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
144
94
{
145
94
    mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
146
94
    mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
147
148
    /* Initially, there's no keystream bytes available */
149
94
    ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
150
94
}
151
152
void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
153
94
{
154
94
    if (ctx != NULL) {
155
94
        mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
156
94
    }
157
94
}
158
159
int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
160
                            const unsigned char key[32])
161
71
{
162
    /* ChaCha20 constants - the string "expand 32-byte k" */
163
71
    ctx->state[0] = 0x61707865;
164
71
    ctx->state[1] = 0x3320646e;
165
71
    ctx->state[2] = 0x79622d32;
166
71
    ctx->state[3] = 0x6b206574;
167
168
    /* Set key */
169
71
    ctx->state[4]  = MBEDTLS_GET_UINT32_LE(key, 0);
170
71
    ctx->state[5]  = MBEDTLS_GET_UINT32_LE(key, 4);
171
71
    ctx->state[6]  = MBEDTLS_GET_UINT32_LE(key, 8);
172
71
    ctx->state[7]  = MBEDTLS_GET_UINT32_LE(key, 12);
173
71
    ctx->state[8]  = MBEDTLS_GET_UINT32_LE(key, 16);
174
71
    ctx->state[9]  = MBEDTLS_GET_UINT32_LE(key, 20);
175
71
    ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24);
176
71
    ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28);
177
178
71
    return 0;
179
71
}
180
181
int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
182
                            const unsigned char nonce[12],
183
                            uint32_t counter)
184
44
{
185
    /* Counter */
186
44
    ctx->state[12] = counter;
187
188
    /* Nonce */
189
44
    ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0);
190
44
    ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4);
191
44
    ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8);
192
193
44
    mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
194
195
    /* Initially, there's no keystream bytes available */
196
44
    ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
197
198
44
    return 0;
199
44
}
200
201
int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
202
                            size_t size,
203
                            const unsigned char *input,
204
                            unsigned char *output)
205
88
{
206
88
    size_t offset = 0U;
207
208
    /* Use leftover keystream bytes, if available */
209
88
    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
132
    while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
220
        /* Generate new keystream block and increment counter */
221
44
        chacha20_block(ctx->state, ctx->keystream8);
222
44
        ctx->state[CHACHA20_CTR_INDEX]++;
223
224
44
        mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U);
225
226
44
        offset += CHACHA20_BLOCK_SIZE_BYTES;
227
44
        size   -= CHACHA20_BLOCK_SIZE_BYTES;
228
44
    }
229
230
    /* Last (partial) block */
231
88
    if (size > 0U) {
232
        /* Generate new keystream block and increment counter */
233
44
        chacha20_block(ctx->state, ctx->keystream8);
234
44
        ctx->state[CHACHA20_CTR_INDEX]++;
235
236
44
        mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);
237
238
44
        ctx->keystream_bytes_used = size;
239
240
44
    }
241
242
88
    return 0;
243
88
}
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 */