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