1*62c56f98SSadaf Ebrahimi /**
2*62c56f98SSadaf Ebrahimi * \file chachapoly.c
3*62c56f98SSadaf Ebrahimi *
4*62c56f98SSadaf Ebrahimi * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
5*62c56f98SSadaf Ebrahimi *
6*62c56f98SSadaf Ebrahimi * Copyright The Mbed TLS Contributors
7*62c56f98SSadaf Ebrahimi * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
8*62c56f98SSadaf Ebrahimi */
9*62c56f98SSadaf Ebrahimi #include "common.h"
10*62c56f98SSadaf Ebrahimi
11*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_CHACHAPOLY_C)
12*62c56f98SSadaf Ebrahimi
13*62c56f98SSadaf Ebrahimi #include "mbedtls/chachapoly.h"
14*62c56f98SSadaf Ebrahimi #include "mbedtls/platform_util.h"
15*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
16*62c56f98SSadaf Ebrahimi #include "mbedtls/constant_time.h"
17*62c56f98SSadaf Ebrahimi
18*62c56f98SSadaf Ebrahimi #include <string.h>
19*62c56f98SSadaf Ebrahimi
20*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
21*62c56f98SSadaf Ebrahimi
22*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_CHACHAPOLY_ALT)
23*62c56f98SSadaf Ebrahimi
24*62c56f98SSadaf Ebrahimi #define CHACHAPOLY_STATE_INIT (0)
25*62c56f98SSadaf Ebrahimi #define CHACHAPOLY_STATE_AAD (1)
26*62c56f98SSadaf Ebrahimi #define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
27*62c56f98SSadaf Ebrahimi #define CHACHAPOLY_STATE_FINISHED (3)
28*62c56f98SSadaf Ebrahimi
29*62c56f98SSadaf Ebrahimi /**
30*62c56f98SSadaf Ebrahimi * \brief Adds nul bytes to pad the AAD for Poly1305.
31*62c56f98SSadaf Ebrahimi *
32*62c56f98SSadaf Ebrahimi * \param ctx The ChaCha20-Poly1305 context.
33*62c56f98SSadaf Ebrahimi */
chachapoly_pad_aad(mbedtls_chachapoly_context * ctx)34*62c56f98SSadaf Ebrahimi static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
35*62c56f98SSadaf Ebrahimi {
36*62c56f98SSadaf Ebrahimi uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
37*62c56f98SSadaf Ebrahimi unsigned char zeroes[15];
38*62c56f98SSadaf Ebrahimi
39*62c56f98SSadaf Ebrahimi if (partial_block_len == 0U) {
40*62c56f98SSadaf Ebrahimi return 0;
41*62c56f98SSadaf Ebrahimi }
42*62c56f98SSadaf Ebrahimi
43*62c56f98SSadaf Ebrahimi memset(zeroes, 0, sizeof(zeroes));
44*62c56f98SSadaf Ebrahimi
45*62c56f98SSadaf Ebrahimi return mbedtls_poly1305_update(&ctx->poly1305_ctx,
46*62c56f98SSadaf Ebrahimi zeroes,
47*62c56f98SSadaf Ebrahimi 16U - partial_block_len);
48*62c56f98SSadaf Ebrahimi }
49*62c56f98SSadaf Ebrahimi
50*62c56f98SSadaf Ebrahimi /**
51*62c56f98SSadaf Ebrahimi * \brief Adds nul bytes to pad the ciphertext for Poly1305.
52*62c56f98SSadaf Ebrahimi *
53*62c56f98SSadaf Ebrahimi * \param ctx The ChaCha20-Poly1305 context.
54*62c56f98SSadaf Ebrahimi */
chachapoly_pad_ciphertext(mbedtls_chachapoly_context * ctx)55*62c56f98SSadaf Ebrahimi static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
56*62c56f98SSadaf Ebrahimi {
57*62c56f98SSadaf Ebrahimi uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
58*62c56f98SSadaf Ebrahimi unsigned char zeroes[15];
59*62c56f98SSadaf Ebrahimi
60*62c56f98SSadaf Ebrahimi if (partial_block_len == 0U) {
61*62c56f98SSadaf Ebrahimi return 0;
62*62c56f98SSadaf Ebrahimi }
63*62c56f98SSadaf Ebrahimi
64*62c56f98SSadaf Ebrahimi memset(zeroes, 0, sizeof(zeroes));
65*62c56f98SSadaf Ebrahimi return mbedtls_poly1305_update(&ctx->poly1305_ctx,
66*62c56f98SSadaf Ebrahimi zeroes,
67*62c56f98SSadaf Ebrahimi 16U - partial_block_len);
68*62c56f98SSadaf Ebrahimi }
69*62c56f98SSadaf Ebrahimi
mbedtls_chachapoly_init(mbedtls_chachapoly_context * ctx)70*62c56f98SSadaf Ebrahimi void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
71*62c56f98SSadaf Ebrahimi {
72*62c56f98SSadaf Ebrahimi mbedtls_chacha20_init(&ctx->chacha20_ctx);
73*62c56f98SSadaf Ebrahimi mbedtls_poly1305_init(&ctx->poly1305_ctx);
74*62c56f98SSadaf Ebrahimi ctx->aad_len = 0U;
75*62c56f98SSadaf Ebrahimi ctx->ciphertext_len = 0U;
76*62c56f98SSadaf Ebrahimi ctx->state = CHACHAPOLY_STATE_INIT;
77*62c56f98SSadaf Ebrahimi ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
78*62c56f98SSadaf Ebrahimi }
79*62c56f98SSadaf Ebrahimi
mbedtls_chachapoly_free(mbedtls_chachapoly_context * ctx)80*62c56f98SSadaf Ebrahimi void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
81*62c56f98SSadaf Ebrahimi {
82*62c56f98SSadaf Ebrahimi if (ctx == NULL) {
83*62c56f98SSadaf Ebrahimi return;
84*62c56f98SSadaf Ebrahimi }
85*62c56f98SSadaf Ebrahimi
86*62c56f98SSadaf Ebrahimi mbedtls_chacha20_free(&ctx->chacha20_ctx);
87*62c56f98SSadaf Ebrahimi mbedtls_poly1305_free(&ctx->poly1305_ctx);
88*62c56f98SSadaf Ebrahimi ctx->aad_len = 0U;
89*62c56f98SSadaf Ebrahimi ctx->ciphertext_len = 0U;
90*62c56f98SSadaf Ebrahimi ctx->state = CHACHAPOLY_STATE_INIT;
91*62c56f98SSadaf Ebrahimi ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
92*62c56f98SSadaf Ebrahimi }
93*62c56f98SSadaf Ebrahimi
mbedtls_chachapoly_setkey(mbedtls_chachapoly_context * ctx,const unsigned char key[32])94*62c56f98SSadaf Ebrahimi int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
95*62c56f98SSadaf Ebrahimi const unsigned char key[32])
96*62c56f98SSadaf Ebrahimi {
97*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
98*62c56f98SSadaf Ebrahimi
99*62c56f98SSadaf Ebrahimi ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
100*62c56f98SSadaf Ebrahimi
101*62c56f98SSadaf Ebrahimi return ret;
102*62c56f98SSadaf Ebrahimi }
103*62c56f98SSadaf Ebrahimi
mbedtls_chachapoly_starts(mbedtls_chachapoly_context * ctx,const unsigned char nonce[12],mbedtls_chachapoly_mode_t mode)104*62c56f98SSadaf Ebrahimi int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
105*62c56f98SSadaf Ebrahimi const unsigned char nonce[12],
106*62c56f98SSadaf Ebrahimi mbedtls_chachapoly_mode_t mode)
107*62c56f98SSadaf Ebrahimi {
108*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
109*62c56f98SSadaf Ebrahimi unsigned char poly1305_key[64];
110*62c56f98SSadaf Ebrahimi
111*62c56f98SSadaf Ebrahimi /* Set counter = 0, will be update to 1 when generating Poly1305 key */
112*62c56f98SSadaf Ebrahimi ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
113*62c56f98SSadaf Ebrahimi if (ret != 0) {
114*62c56f98SSadaf Ebrahimi goto cleanup;
115*62c56f98SSadaf Ebrahimi }
116*62c56f98SSadaf Ebrahimi
117*62c56f98SSadaf Ebrahimi /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
118*62c56f98SSadaf Ebrahimi * counter = 0. This is the same as encrypting a buffer of zeroes.
119*62c56f98SSadaf Ebrahimi * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
120*62c56f98SSadaf Ebrahimi * The other 256 bits are discarded.
121*62c56f98SSadaf Ebrahimi */
122*62c56f98SSadaf Ebrahimi memset(poly1305_key, 0, sizeof(poly1305_key));
123*62c56f98SSadaf Ebrahimi ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
124*62c56f98SSadaf Ebrahimi poly1305_key, poly1305_key);
125*62c56f98SSadaf Ebrahimi if (ret != 0) {
126*62c56f98SSadaf Ebrahimi goto cleanup;
127*62c56f98SSadaf Ebrahimi }
128*62c56f98SSadaf Ebrahimi
129*62c56f98SSadaf Ebrahimi ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
130*62c56f98SSadaf Ebrahimi
131*62c56f98SSadaf Ebrahimi if (ret == 0) {
132*62c56f98SSadaf Ebrahimi ctx->aad_len = 0U;
133*62c56f98SSadaf Ebrahimi ctx->ciphertext_len = 0U;
134*62c56f98SSadaf Ebrahimi ctx->state = CHACHAPOLY_STATE_AAD;
135*62c56f98SSadaf Ebrahimi ctx->mode = mode;
136*62c56f98SSadaf Ebrahimi }
137*62c56f98SSadaf Ebrahimi
138*62c56f98SSadaf Ebrahimi cleanup:
139*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(poly1305_key, 64U);
140*62c56f98SSadaf Ebrahimi return ret;
141*62c56f98SSadaf Ebrahimi }
142*62c56f98SSadaf Ebrahimi
mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context * ctx,const unsigned char * aad,size_t aad_len)143*62c56f98SSadaf Ebrahimi int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
144*62c56f98SSadaf Ebrahimi const unsigned char *aad,
145*62c56f98SSadaf Ebrahimi size_t aad_len)
146*62c56f98SSadaf Ebrahimi {
147*62c56f98SSadaf Ebrahimi if (ctx->state != CHACHAPOLY_STATE_AAD) {
148*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
149*62c56f98SSadaf Ebrahimi }
150*62c56f98SSadaf Ebrahimi
151*62c56f98SSadaf Ebrahimi ctx->aad_len += aad_len;
152*62c56f98SSadaf Ebrahimi
153*62c56f98SSadaf Ebrahimi return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
154*62c56f98SSadaf Ebrahimi }
155*62c56f98SSadaf Ebrahimi
mbedtls_chachapoly_update(mbedtls_chachapoly_context * ctx,size_t len,const unsigned char * input,unsigned char * output)156*62c56f98SSadaf Ebrahimi int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
157*62c56f98SSadaf Ebrahimi size_t len,
158*62c56f98SSadaf Ebrahimi const unsigned char *input,
159*62c56f98SSadaf Ebrahimi unsigned char *output)
160*62c56f98SSadaf Ebrahimi {
161*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
162*62c56f98SSadaf Ebrahimi
163*62c56f98SSadaf Ebrahimi if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
164*62c56f98SSadaf Ebrahimi (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
165*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
166*62c56f98SSadaf Ebrahimi }
167*62c56f98SSadaf Ebrahimi
168*62c56f98SSadaf Ebrahimi if (ctx->state == CHACHAPOLY_STATE_AAD) {
169*62c56f98SSadaf Ebrahimi ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
170*62c56f98SSadaf Ebrahimi
171*62c56f98SSadaf Ebrahimi ret = chachapoly_pad_aad(ctx);
172*62c56f98SSadaf Ebrahimi if (ret != 0) {
173*62c56f98SSadaf Ebrahimi return ret;
174*62c56f98SSadaf Ebrahimi }
175*62c56f98SSadaf Ebrahimi }
176*62c56f98SSadaf Ebrahimi
177*62c56f98SSadaf Ebrahimi ctx->ciphertext_len += len;
178*62c56f98SSadaf Ebrahimi
179*62c56f98SSadaf Ebrahimi if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
180*62c56f98SSadaf Ebrahimi ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
181*62c56f98SSadaf Ebrahimi if (ret != 0) {
182*62c56f98SSadaf Ebrahimi return ret;
183*62c56f98SSadaf Ebrahimi }
184*62c56f98SSadaf Ebrahimi
185*62c56f98SSadaf Ebrahimi ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
186*62c56f98SSadaf Ebrahimi if (ret != 0) {
187*62c56f98SSadaf Ebrahimi return ret;
188*62c56f98SSadaf Ebrahimi }
189*62c56f98SSadaf Ebrahimi } else { /* DECRYPT */
190*62c56f98SSadaf Ebrahimi ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
191*62c56f98SSadaf Ebrahimi if (ret != 0) {
192*62c56f98SSadaf Ebrahimi return ret;
193*62c56f98SSadaf Ebrahimi }
194*62c56f98SSadaf Ebrahimi
195*62c56f98SSadaf Ebrahimi ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
196*62c56f98SSadaf Ebrahimi if (ret != 0) {
197*62c56f98SSadaf Ebrahimi return ret;
198*62c56f98SSadaf Ebrahimi }
199*62c56f98SSadaf Ebrahimi }
200*62c56f98SSadaf Ebrahimi
201*62c56f98SSadaf Ebrahimi return 0;
202*62c56f98SSadaf Ebrahimi }
203*62c56f98SSadaf Ebrahimi
mbedtls_chachapoly_finish(mbedtls_chachapoly_context * ctx,unsigned char mac[16])204*62c56f98SSadaf Ebrahimi int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
205*62c56f98SSadaf Ebrahimi unsigned char mac[16])
206*62c56f98SSadaf Ebrahimi {
207*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
208*62c56f98SSadaf Ebrahimi unsigned char len_block[16];
209*62c56f98SSadaf Ebrahimi
210*62c56f98SSadaf Ebrahimi if (ctx->state == CHACHAPOLY_STATE_INIT) {
211*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
212*62c56f98SSadaf Ebrahimi }
213*62c56f98SSadaf Ebrahimi
214*62c56f98SSadaf Ebrahimi if (ctx->state == CHACHAPOLY_STATE_AAD) {
215*62c56f98SSadaf Ebrahimi ret = chachapoly_pad_aad(ctx);
216*62c56f98SSadaf Ebrahimi if (ret != 0) {
217*62c56f98SSadaf Ebrahimi return ret;
218*62c56f98SSadaf Ebrahimi }
219*62c56f98SSadaf Ebrahimi } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
220*62c56f98SSadaf Ebrahimi ret = chachapoly_pad_ciphertext(ctx);
221*62c56f98SSadaf Ebrahimi if (ret != 0) {
222*62c56f98SSadaf Ebrahimi return ret;
223*62c56f98SSadaf Ebrahimi }
224*62c56f98SSadaf Ebrahimi }
225*62c56f98SSadaf Ebrahimi
226*62c56f98SSadaf Ebrahimi ctx->state = CHACHAPOLY_STATE_FINISHED;
227*62c56f98SSadaf Ebrahimi
228*62c56f98SSadaf Ebrahimi /* The lengths of the AAD and ciphertext are processed by
229*62c56f98SSadaf Ebrahimi * Poly1305 as the final 128-bit block, encoded as little-endian integers.
230*62c56f98SSadaf Ebrahimi */
231*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
232*62c56f98SSadaf Ebrahimi MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
233*62c56f98SSadaf Ebrahimi
234*62c56f98SSadaf Ebrahimi ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
235*62c56f98SSadaf Ebrahimi if (ret != 0) {
236*62c56f98SSadaf Ebrahimi return ret;
237*62c56f98SSadaf Ebrahimi }
238*62c56f98SSadaf Ebrahimi
239*62c56f98SSadaf Ebrahimi ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
240*62c56f98SSadaf Ebrahimi
241*62c56f98SSadaf Ebrahimi return ret;
242*62c56f98SSadaf Ebrahimi }
243*62c56f98SSadaf Ebrahimi
chachapoly_crypt_and_tag(mbedtls_chachapoly_context * ctx,mbedtls_chachapoly_mode_t mode,size_t length,const unsigned char nonce[12],const unsigned char * aad,size_t aad_len,const unsigned char * input,unsigned char * output,unsigned char tag[16])244*62c56f98SSadaf Ebrahimi static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
245*62c56f98SSadaf Ebrahimi mbedtls_chachapoly_mode_t mode,
246*62c56f98SSadaf Ebrahimi size_t length,
247*62c56f98SSadaf Ebrahimi const unsigned char nonce[12],
248*62c56f98SSadaf Ebrahimi const unsigned char *aad,
249*62c56f98SSadaf Ebrahimi size_t aad_len,
250*62c56f98SSadaf Ebrahimi const unsigned char *input,
251*62c56f98SSadaf Ebrahimi unsigned char *output,
252*62c56f98SSadaf Ebrahimi unsigned char tag[16])
253*62c56f98SSadaf Ebrahimi {
254*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
255*62c56f98SSadaf Ebrahimi
256*62c56f98SSadaf Ebrahimi ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
257*62c56f98SSadaf Ebrahimi if (ret != 0) {
258*62c56f98SSadaf Ebrahimi goto cleanup;
259*62c56f98SSadaf Ebrahimi }
260*62c56f98SSadaf Ebrahimi
261*62c56f98SSadaf Ebrahimi ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
262*62c56f98SSadaf Ebrahimi if (ret != 0) {
263*62c56f98SSadaf Ebrahimi goto cleanup;
264*62c56f98SSadaf Ebrahimi }
265*62c56f98SSadaf Ebrahimi
266*62c56f98SSadaf Ebrahimi ret = mbedtls_chachapoly_update(ctx, length, input, output);
267*62c56f98SSadaf Ebrahimi if (ret != 0) {
268*62c56f98SSadaf Ebrahimi goto cleanup;
269*62c56f98SSadaf Ebrahimi }
270*62c56f98SSadaf Ebrahimi
271*62c56f98SSadaf Ebrahimi ret = mbedtls_chachapoly_finish(ctx, tag);
272*62c56f98SSadaf Ebrahimi
273*62c56f98SSadaf Ebrahimi cleanup:
274*62c56f98SSadaf Ebrahimi return ret;
275*62c56f98SSadaf Ebrahimi }
276*62c56f98SSadaf Ebrahimi
mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context * ctx,size_t length,const unsigned char nonce[12],const unsigned char * aad,size_t aad_len,const unsigned char * input,unsigned char * output,unsigned char tag[16])277*62c56f98SSadaf Ebrahimi int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
278*62c56f98SSadaf Ebrahimi size_t length,
279*62c56f98SSadaf Ebrahimi const unsigned char nonce[12],
280*62c56f98SSadaf Ebrahimi const unsigned char *aad,
281*62c56f98SSadaf Ebrahimi size_t aad_len,
282*62c56f98SSadaf Ebrahimi const unsigned char *input,
283*62c56f98SSadaf Ebrahimi unsigned char *output,
284*62c56f98SSadaf Ebrahimi unsigned char tag[16])
285*62c56f98SSadaf Ebrahimi {
286*62c56f98SSadaf Ebrahimi return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
287*62c56f98SSadaf Ebrahimi length, nonce, aad, aad_len,
288*62c56f98SSadaf Ebrahimi input, output, tag);
289*62c56f98SSadaf Ebrahimi }
290*62c56f98SSadaf Ebrahimi
mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context * ctx,size_t length,const unsigned char nonce[12],const unsigned char * aad,size_t aad_len,const unsigned char tag[16],const unsigned char * input,unsigned char * output)291*62c56f98SSadaf Ebrahimi int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
292*62c56f98SSadaf Ebrahimi size_t length,
293*62c56f98SSadaf Ebrahimi const unsigned char nonce[12],
294*62c56f98SSadaf Ebrahimi const unsigned char *aad,
295*62c56f98SSadaf Ebrahimi size_t aad_len,
296*62c56f98SSadaf Ebrahimi const unsigned char tag[16],
297*62c56f98SSadaf Ebrahimi const unsigned char *input,
298*62c56f98SSadaf Ebrahimi unsigned char *output)
299*62c56f98SSadaf Ebrahimi {
300*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
301*62c56f98SSadaf Ebrahimi unsigned char check_tag[16];
302*62c56f98SSadaf Ebrahimi int diff;
303*62c56f98SSadaf Ebrahimi
304*62c56f98SSadaf Ebrahimi if ((ret = chachapoly_crypt_and_tag(ctx,
305*62c56f98SSadaf Ebrahimi MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
306*62c56f98SSadaf Ebrahimi aad, aad_len, input, output, check_tag)) != 0) {
307*62c56f98SSadaf Ebrahimi return ret;
308*62c56f98SSadaf Ebrahimi }
309*62c56f98SSadaf Ebrahimi
310*62c56f98SSadaf Ebrahimi /* Check tag in "constant-time" */
311*62c56f98SSadaf Ebrahimi diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));
312*62c56f98SSadaf Ebrahimi
313*62c56f98SSadaf Ebrahimi if (diff != 0) {
314*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(output, length);
315*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
316*62c56f98SSadaf Ebrahimi }
317*62c56f98SSadaf Ebrahimi
318*62c56f98SSadaf Ebrahimi return 0;
319*62c56f98SSadaf Ebrahimi }
320*62c56f98SSadaf Ebrahimi
321*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_CHACHAPOLY_ALT */
322*62c56f98SSadaf Ebrahimi
323*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_SELF_TEST)
324*62c56f98SSadaf Ebrahimi
325*62c56f98SSadaf Ebrahimi static const unsigned char test_key[1][32] =
326*62c56f98SSadaf Ebrahimi {
327*62c56f98SSadaf Ebrahimi {
328*62c56f98SSadaf Ebrahimi 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
329*62c56f98SSadaf Ebrahimi 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
330*62c56f98SSadaf Ebrahimi 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
331*62c56f98SSadaf Ebrahimi 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
332*62c56f98SSadaf Ebrahimi }
333*62c56f98SSadaf Ebrahimi };
334*62c56f98SSadaf Ebrahimi
335*62c56f98SSadaf Ebrahimi static const unsigned char test_nonce[1][12] =
336*62c56f98SSadaf Ebrahimi {
337*62c56f98SSadaf Ebrahimi {
338*62c56f98SSadaf Ebrahimi 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
339*62c56f98SSadaf Ebrahimi 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
340*62c56f98SSadaf Ebrahimi }
341*62c56f98SSadaf Ebrahimi };
342*62c56f98SSadaf Ebrahimi
343*62c56f98SSadaf Ebrahimi static const unsigned char test_aad[1][12] =
344*62c56f98SSadaf Ebrahimi {
345*62c56f98SSadaf Ebrahimi {
346*62c56f98SSadaf Ebrahimi 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
347*62c56f98SSadaf Ebrahimi 0xc4, 0xc5, 0xc6, 0xc7
348*62c56f98SSadaf Ebrahimi }
349*62c56f98SSadaf Ebrahimi };
350*62c56f98SSadaf Ebrahimi
351*62c56f98SSadaf Ebrahimi static const size_t test_aad_len[1] =
352*62c56f98SSadaf Ebrahimi {
353*62c56f98SSadaf Ebrahimi 12U
354*62c56f98SSadaf Ebrahimi };
355*62c56f98SSadaf Ebrahimi
356*62c56f98SSadaf Ebrahimi static const unsigned char test_input[1][114] =
357*62c56f98SSadaf Ebrahimi {
358*62c56f98SSadaf Ebrahimi {
359*62c56f98SSadaf Ebrahimi 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
360*62c56f98SSadaf Ebrahimi 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
361*62c56f98SSadaf Ebrahimi 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
362*62c56f98SSadaf Ebrahimi 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
363*62c56f98SSadaf Ebrahimi 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
364*62c56f98SSadaf Ebrahimi 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
365*62c56f98SSadaf Ebrahimi 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
366*62c56f98SSadaf Ebrahimi 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
367*62c56f98SSadaf Ebrahimi 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
368*62c56f98SSadaf Ebrahimi 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
369*62c56f98SSadaf Ebrahimi 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
370*62c56f98SSadaf Ebrahimi 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
371*62c56f98SSadaf Ebrahimi 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
372*62c56f98SSadaf Ebrahimi 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
373*62c56f98SSadaf Ebrahimi 0x74, 0x2e
374*62c56f98SSadaf Ebrahimi }
375*62c56f98SSadaf Ebrahimi };
376*62c56f98SSadaf Ebrahimi
377*62c56f98SSadaf Ebrahimi static const unsigned char test_output[1][114] =
378*62c56f98SSadaf Ebrahimi {
379*62c56f98SSadaf Ebrahimi {
380*62c56f98SSadaf Ebrahimi 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
381*62c56f98SSadaf Ebrahimi 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
382*62c56f98SSadaf Ebrahimi 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
383*62c56f98SSadaf Ebrahimi 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
384*62c56f98SSadaf Ebrahimi 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
385*62c56f98SSadaf Ebrahimi 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
386*62c56f98SSadaf Ebrahimi 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
387*62c56f98SSadaf Ebrahimi 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
388*62c56f98SSadaf Ebrahimi 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
389*62c56f98SSadaf Ebrahimi 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
390*62c56f98SSadaf Ebrahimi 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
391*62c56f98SSadaf Ebrahimi 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
392*62c56f98SSadaf Ebrahimi 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
393*62c56f98SSadaf Ebrahimi 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
394*62c56f98SSadaf Ebrahimi 0x61, 0x16
395*62c56f98SSadaf Ebrahimi }
396*62c56f98SSadaf Ebrahimi };
397*62c56f98SSadaf Ebrahimi
398*62c56f98SSadaf Ebrahimi static const size_t test_input_len[1] =
399*62c56f98SSadaf Ebrahimi {
400*62c56f98SSadaf Ebrahimi 114U
401*62c56f98SSadaf Ebrahimi };
402*62c56f98SSadaf Ebrahimi
403*62c56f98SSadaf Ebrahimi static const unsigned char test_mac[1][16] =
404*62c56f98SSadaf Ebrahimi {
405*62c56f98SSadaf Ebrahimi {
406*62c56f98SSadaf Ebrahimi 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
407*62c56f98SSadaf Ebrahimi 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
408*62c56f98SSadaf Ebrahimi }
409*62c56f98SSadaf Ebrahimi };
410*62c56f98SSadaf Ebrahimi
411*62c56f98SSadaf Ebrahimi /* Make sure no other definition is already present. */
412*62c56f98SSadaf Ebrahimi #undef ASSERT
413*62c56f98SSadaf Ebrahimi
414*62c56f98SSadaf Ebrahimi #define ASSERT(cond, args) \
415*62c56f98SSadaf Ebrahimi do \
416*62c56f98SSadaf Ebrahimi { \
417*62c56f98SSadaf Ebrahimi if (!(cond)) \
418*62c56f98SSadaf Ebrahimi { \
419*62c56f98SSadaf Ebrahimi if (verbose != 0) \
420*62c56f98SSadaf Ebrahimi mbedtls_printf args; \
421*62c56f98SSadaf Ebrahimi \
422*62c56f98SSadaf Ebrahimi return -1; \
423*62c56f98SSadaf Ebrahimi } \
424*62c56f98SSadaf Ebrahimi } \
425*62c56f98SSadaf Ebrahimi while (0)
426*62c56f98SSadaf Ebrahimi
mbedtls_chachapoly_self_test(int verbose)427*62c56f98SSadaf Ebrahimi int mbedtls_chachapoly_self_test(int verbose)
428*62c56f98SSadaf Ebrahimi {
429*62c56f98SSadaf Ebrahimi mbedtls_chachapoly_context ctx;
430*62c56f98SSadaf Ebrahimi unsigned i;
431*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
432*62c56f98SSadaf Ebrahimi unsigned char output[200];
433*62c56f98SSadaf Ebrahimi unsigned char mac[16];
434*62c56f98SSadaf Ebrahimi
435*62c56f98SSadaf Ebrahimi for (i = 0U; i < 1U; i++) {
436*62c56f98SSadaf Ebrahimi if (verbose != 0) {
437*62c56f98SSadaf Ebrahimi mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
438*62c56f98SSadaf Ebrahimi }
439*62c56f98SSadaf Ebrahimi
440*62c56f98SSadaf Ebrahimi mbedtls_chachapoly_init(&ctx);
441*62c56f98SSadaf Ebrahimi
442*62c56f98SSadaf Ebrahimi ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
443*62c56f98SSadaf Ebrahimi ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
444*62c56f98SSadaf Ebrahimi
445*62c56f98SSadaf Ebrahimi ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
446*62c56f98SSadaf Ebrahimi test_input_len[i],
447*62c56f98SSadaf Ebrahimi test_nonce[i],
448*62c56f98SSadaf Ebrahimi test_aad[i],
449*62c56f98SSadaf Ebrahimi test_aad_len[i],
450*62c56f98SSadaf Ebrahimi test_input[i],
451*62c56f98SSadaf Ebrahimi output,
452*62c56f98SSadaf Ebrahimi mac);
453*62c56f98SSadaf Ebrahimi
454*62c56f98SSadaf Ebrahimi ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
455*62c56f98SSadaf Ebrahimi
456*62c56f98SSadaf Ebrahimi ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
457*62c56f98SSadaf Ebrahimi ("failure (wrong output)\n"));
458*62c56f98SSadaf Ebrahimi
459*62c56f98SSadaf Ebrahimi ASSERT(0 == memcmp(mac, test_mac[i], 16U),
460*62c56f98SSadaf Ebrahimi ("failure (wrong MAC)\n"));
461*62c56f98SSadaf Ebrahimi
462*62c56f98SSadaf Ebrahimi mbedtls_chachapoly_free(&ctx);
463*62c56f98SSadaf Ebrahimi
464*62c56f98SSadaf Ebrahimi if (verbose != 0) {
465*62c56f98SSadaf Ebrahimi mbedtls_printf("passed\n");
466*62c56f98SSadaf Ebrahimi }
467*62c56f98SSadaf Ebrahimi }
468*62c56f98SSadaf Ebrahimi
469*62c56f98SSadaf Ebrahimi if (verbose != 0) {
470*62c56f98SSadaf Ebrahimi mbedtls_printf("\n");
471*62c56f98SSadaf Ebrahimi }
472*62c56f98SSadaf Ebrahimi
473*62c56f98SSadaf Ebrahimi return 0;
474*62c56f98SSadaf Ebrahimi }
475*62c56f98SSadaf Ebrahimi
476*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_SELF_TEST */
477*62c56f98SSadaf Ebrahimi
478*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_CHACHAPOLY_C */
479