blob: 0124d757016bbf83c20ea0ad14c743ff017088c6 [file] [log] [blame]
Jens Wiklander3d3b0592019-03-20 15:30:29 +01001/**
2 * \file chachapoly.c
3 *
4 * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
5 *
Jerome Forissier79013242021-07-28 10:24:04 +02006 * Copyright The Mbed TLS Contributors
7 * SPDX-License-Identifier: Apache-2.0
Jens Wiklander3d3b0592019-03-20 15:30:29 +01008 *
9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
10 * not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
Jens Wiklander3d3b0592019-03-20 15:30:29 +010020 */
Jerome Forissier79013242021-07-28 10:24:04 +020021#include "common.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010022
23#if defined(MBEDTLS_CHACHAPOLY_C)
24
25#include "mbedtls/chachapoly.h"
26#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020027#include "mbedtls/error.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010028
29#include <string.h>
30
Jens Wiklander3d3b0592019-03-20 15:30:29 +010031#include "mbedtls/platform.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010032
33#if !defined(MBEDTLS_CHACHAPOLY_ALT)
34
Jens Wiklander32b31802023-10-06 16:59:46 +020035#define CHACHAPOLY_STATE_INIT (0)
36#define CHACHAPOLY_STATE_AAD (1)
37#define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
38#define CHACHAPOLY_STATE_FINISHED (3)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010039
40/**
41 * \brief Adds nul bytes to pad the AAD for Poly1305.
42 *
43 * \param ctx The ChaCha20-Poly1305 context.
44 */
Jens Wiklander32b31802023-10-06 16:59:46 +020045static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010046{
Jens Wiklander32b31802023-10-06 16:59:46 +020047 uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010048 unsigned char zeroes[15];
49
Jens Wiklander32b31802023-10-06 16:59:46 +020050 if (partial_block_len == 0U) {
51 return 0;
52 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +010053
Jens Wiklander32b31802023-10-06 16:59:46 +020054 memset(zeroes, 0, sizeof(zeroes));
Jens Wiklander3d3b0592019-03-20 15:30:29 +010055
Jens Wiklander32b31802023-10-06 16:59:46 +020056 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
57 zeroes,
58 16U - partial_block_len);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010059}
60
61/**
62 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
63 *
64 * \param ctx The ChaCha20-Poly1305 context.
65 */
Jens Wiklander32b31802023-10-06 16:59:46 +020066static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010067{
Jens Wiklander32b31802023-10-06 16:59:46 +020068 uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010069 unsigned char zeroes[15];
70
Jens Wiklander32b31802023-10-06 16:59:46 +020071 if (partial_block_len == 0U) {
72 return 0;
73 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +010074
Jens Wiklander32b31802023-10-06 16:59:46 +020075 memset(zeroes, 0, sizeof(zeroes));
76 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
77 zeroes,
78 16U - partial_block_len);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010079}
80
Jens Wiklander32b31802023-10-06 16:59:46 +020081void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010082{
Jens Wiklander32b31802023-10-06 16:59:46 +020083 mbedtls_chacha20_init(&ctx->chacha20_ctx);
84 mbedtls_poly1305_init(&ctx->poly1305_ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010085 ctx->aad_len = 0U;
86 ctx->ciphertext_len = 0U;
87 ctx->state = CHACHAPOLY_STATE_INIT;
88 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
89}
90
Jens Wiklander32b31802023-10-06 16:59:46 +020091void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010092{
Jens Wiklander32b31802023-10-06 16:59:46 +020093 if (ctx == NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010094 return;
Jens Wiklander32b31802023-10-06 16:59:46 +020095 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +010096
Jens Wiklander32b31802023-10-06 16:59:46 +020097 mbedtls_chacha20_free(&ctx->chacha20_ctx);
98 mbedtls_poly1305_free(&ctx->poly1305_ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010099 ctx->aad_len = 0U;
100 ctx->ciphertext_len = 0U;
101 ctx->state = CHACHAPOLY_STATE_INIT;
102 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
103}
104
Jens Wiklander32b31802023-10-06 16:59:46 +0200105int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
106 const unsigned char key[32])
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100107{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200108 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100109
Jens Wiklander32b31802023-10-06 16:59:46 +0200110 ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100111
Jens Wiklander32b31802023-10-06 16:59:46 +0200112 return ret;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100113}
114
Jens Wiklander32b31802023-10-06 16:59:46 +0200115int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
116 const unsigned char nonce[12],
117 mbedtls_chachapoly_mode_t mode)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100118{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200119 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100120 unsigned char poly1305_key[64];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100121
122 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Jens Wiklander32b31802023-10-06 16:59:46 +0200123 ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
124 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100125 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200126 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100127
128 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
129 * counter = 0. This is the same as encrypting a buffer of zeroes.
130 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
131 * The other 256 bits are discarded.
132 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200133 memset(poly1305_key, 0, sizeof(poly1305_key));
134 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
135 poly1305_key, poly1305_key);
136 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100137 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200138 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100139
Jens Wiklander32b31802023-10-06 16:59:46 +0200140 ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100141
Jens Wiklander32b31802023-10-06 16:59:46 +0200142 if (ret == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100143 ctx->aad_len = 0U;
144 ctx->ciphertext_len = 0U;
145 ctx->state = CHACHAPOLY_STATE_AAD;
146 ctx->mode = mode;
147 }
148
149cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200150 mbedtls_platform_zeroize(poly1305_key, 64U);
151 return ret;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100152}
153
Jens Wiklander32b31802023-10-06 16:59:46 +0200154int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
155 const unsigned char *aad,
156 size_t aad_len)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100157{
Jens Wiklander32b31802023-10-06 16:59:46 +0200158 if (ctx->state != CHACHAPOLY_STATE_AAD) {
159 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
160 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100161
162 ctx->aad_len += aad_len;
163
Jens Wiklander32b31802023-10-06 16:59:46 +0200164 return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100165}
166
Jens Wiklander32b31802023-10-06 16:59:46 +0200167int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
168 size_t len,
169 const unsigned char *input,
170 unsigned char *output)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100171{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200172 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100173
Jens Wiklander32b31802023-10-06 16:59:46 +0200174 if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
175 (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
176 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100177 }
178
Jens Wiklander32b31802023-10-06 16:59:46 +0200179 if (ctx->state == CHACHAPOLY_STATE_AAD) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100180 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
181
Jens Wiklander32b31802023-10-06 16:59:46 +0200182 ret = chachapoly_pad_aad(ctx);
183 if (ret != 0) {
184 return ret;
185 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100186 }
187
188 ctx->ciphertext_len += len;
189
Jens Wiklander32b31802023-10-06 16:59:46 +0200190 if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
191 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
192 if (ret != 0) {
193 return ret;
194 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100195
Jens Wiklander32b31802023-10-06 16:59:46 +0200196 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
197 if (ret != 0) {
198 return ret;
199 }
200 } else { /* DECRYPT */
201 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
202 if (ret != 0) {
203 return ret;
204 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100205
Jens Wiklander32b31802023-10-06 16:59:46 +0200206 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
207 if (ret != 0) {
208 return ret;
209 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100210 }
211
Jens Wiklander32b31802023-10-06 16:59:46 +0200212 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100213}
214
Jens Wiklander32b31802023-10-06 16:59:46 +0200215int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
216 unsigned char mac[16])
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100217{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200218 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100219 unsigned char len_block[16];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100220
Jens Wiklander32b31802023-10-06 16:59:46 +0200221 if (ctx->state == CHACHAPOLY_STATE_INIT) {
222 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100223 }
224
Jens Wiklander32b31802023-10-06 16:59:46 +0200225 if (ctx->state == CHACHAPOLY_STATE_AAD) {
226 ret = chachapoly_pad_aad(ctx);
227 if (ret != 0) {
228 return ret;
229 }
230 } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
231 ret = chachapoly_pad_ciphertext(ctx);
232 if (ret != 0) {
233 return ret;
234 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100235 }
236
237 ctx->state = CHACHAPOLY_STATE_FINISHED;
238
239 /* The lengths of the AAD and ciphertext are processed by
240 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
241 */
Jerome Forissier039e02d2022-08-09 17:10:15 +0200242 MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
243 MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100244
Jens Wiklander32b31802023-10-06 16:59:46 +0200245 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
246 if (ret != 0) {
247 return ret;
248 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100249
Jens Wiklander32b31802023-10-06 16:59:46 +0200250 ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100251
Jens Wiklander32b31802023-10-06 16:59:46 +0200252 return ret;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100253}
254
Jens Wiklander32b31802023-10-06 16:59:46 +0200255static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
256 mbedtls_chachapoly_mode_t mode,
257 size_t length,
258 const unsigned char nonce[12],
259 const unsigned char *aad,
260 size_t aad_len,
261 const unsigned char *input,
262 unsigned char *output,
263 unsigned char tag[16])
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100264{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200265 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100266
Jens Wiklander32b31802023-10-06 16:59:46 +0200267 ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
268 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100269 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200270 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100271
Jens Wiklander32b31802023-10-06 16:59:46 +0200272 ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
273 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100274 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200275 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100276
Jens Wiklander32b31802023-10-06 16:59:46 +0200277 ret = mbedtls_chachapoly_update(ctx, length, input, output);
278 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100279 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200280 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100281
Jens Wiklander32b31802023-10-06 16:59:46 +0200282 ret = mbedtls_chachapoly_finish(ctx, tag);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100283
284cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200285 return ret;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100286}
287
Jens Wiklander32b31802023-10-06 16:59:46 +0200288int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
289 size_t length,
290 const unsigned char nonce[12],
291 const unsigned char *aad,
292 size_t aad_len,
293 const unsigned char *input,
294 unsigned char *output,
295 unsigned char tag[16])
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100296{
Jens Wiklander32b31802023-10-06 16:59:46 +0200297 return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
298 length, nonce, aad, aad_len,
299 input, output, tag);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100300}
301
Jens Wiklander32b31802023-10-06 16:59:46 +0200302int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
303 size_t length,
304 const unsigned char nonce[12],
305 const unsigned char *aad,
306 size_t aad_len,
307 const unsigned char tag[16],
308 const unsigned char *input,
309 unsigned char *output)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100310{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200311 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100312 unsigned char check_tag[16];
313 size_t i;
314 int diff;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100315
Jens Wiklander32b31802023-10-06 16:59:46 +0200316 if ((ret = chachapoly_crypt_and_tag(ctx,
317 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
318 aad, aad_len, input, output, check_tag)) != 0) {
319 return ret;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100320 }
321
322 /* Check tag in "constant-time" */
Jens Wiklander32b31802023-10-06 16:59:46 +0200323 for (diff = 0, i = 0; i < sizeof(check_tag); i++) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100324 diff |= tag[i] ^ check_tag[i];
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100325 }
326
Jens Wiklander32b31802023-10-06 16:59:46 +0200327 if (diff != 0) {
328 mbedtls_platform_zeroize(output, length);
329 return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
330 }
331
332 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100333}
334
335#endif /* MBEDTLS_CHACHAPOLY_ALT */
336
337#if defined(MBEDTLS_SELF_TEST)
338
339static const unsigned char test_key[1][32] =
340{
341 {
342 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
343 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
344 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
345 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
346 }
347};
348
349static const unsigned char test_nonce[1][12] =
350{
351 {
352 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
353 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
354 }
355};
356
357static const unsigned char test_aad[1][12] =
358{
359 {
360 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
361 0xc4, 0xc5, 0xc6, 0xc7
362 }
363};
364
365static const size_t test_aad_len[1] =
366{
367 12U
368};
369
370static const unsigned char test_input[1][114] =
371{
372 {
373 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
374 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
375 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
376 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
377 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
378 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
379 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
380 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
381 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
382 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
383 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
384 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
385 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
386 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
387 0x74, 0x2e
388 }
389};
390
391static const unsigned char test_output[1][114] =
392{
393 {
394 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
395 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
396 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
397 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
398 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
399 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
400 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
401 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
402 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
403 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
404 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
405 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
406 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
407 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
408 0x61, 0x16
409 }
410};
411
412static const size_t test_input_len[1] =
413{
414 114U
415};
416
417static const unsigned char test_mac[1][16] =
418{
419 {
420 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
421 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
422 }
423};
424
Jerome Forissier79013242021-07-28 10:24:04 +0200425/* Make sure no other definition is already present. */
426#undef ASSERT
427
Jens Wiklander32b31802023-10-06 16:59:46 +0200428#define ASSERT(cond, args) \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100429 do \
430 { \
Jens Wiklander32b31802023-10-06 16:59:46 +0200431 if (!(cond)) \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100432 { \
Jens Wiklander32b31802023-10-06 16:59:46 +0200433 if (verbose != 0) \
434 mbedtls_printf args; \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100435 \
Jens Wiklander32b31802023-10-06 16:59:46 +0200436 return -1; \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100437 } \
438 } \
Jens Wiklander32b31802023-10-06 16:59:46 +0200439 while (0)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100440
Jens Wiklander32b31802023-10-06 16:59:46 +0200441int mbedtls_chachapoly_self_test(int verbose)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100442{
443 mbedtls_chachapoly_context ctx;
444 unsigned i;
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200445 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100446 unsigned char output[200];
447 unsigned char mac[16];
448
Jens Wiklander32b31802023-10-06 16:59:46 +0200449 for (i = 0U; i < 1U; i++) {
450 if (verbose != 0) {
451 mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
452 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100453
Jens Wiklander32b31802023-10-06 16:59:46 +0200454 mbedtls_chachapoly_init(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100455
Jens Wiklander32b31802023-10-06 16:59:46 +0200456 ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
457 ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100458
Jens Wiklander32b31802023-10-06 16:59:46 +0200459 ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
460 test_input_len[i],
461 test_nonce[i],
462 test_aad[i],
463 test_aad_len[i],
464 test_input[i],
465 output,
466 mac);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100467
Jens Wiklander32b31802023-10-06 16:59:46 +0200468 ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100469
Jens Wiklander32b31802023-10-06 16:59:46 +0200470 ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
471 ("failure (wrong output)\n"));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100472
Jens Wiklander32b31802023-10-06 16:59:46 +0200473 ASSERT(0 == memcmp(mac, test_mac[i], 16U),
474 ("failure (wrong MAC)\n"));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100475
Jens Wiklander32b31802023-10-06 16:59:46 +0200476 mbedtls_chachapoly_free(&ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100477
Jens Wiklander32b31802023-10-06 16:59:46 +0200478 if (verbose != 0) {
479 mbedtls_printf("passed\n");
480 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100481 }
482
Jens Wiklander32b31802023-10-06 16:59:46 +0200483 if (verbose != 0) {
484 mbedtls_printf("\n");
485 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100486
Jens Wiklander32b31802023-10-06 16:59:46 +0200487 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100488}
489
490#endif /* MBEDTLS_SELF_TEST */
491
492#endif /* MBEDTLS_CHACHAPOLY_C */