blob: 5bfee0982be8be900aa516addb3c15c877357659 [file] [log] [blame]
Daniel Kingb8025c52016-05-17 14:43:01 -03001/**
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +02002 * \file chachapoly.c
Daniel Kingb8025c52016-05-17 14:43:01 -03003 *
4 * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
5 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02006 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00007 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Daniel Kingb8025c52016-05-17 14:43:01 -03008 */
Gilles Peskinedb09ef62020-06-03 01:43:33 +02009#include "common.h"
Daniel Kingb8025c52016-05-17 14:43:01 -030010
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020011#if defined(MBEDTLS_CHACHAPOLY_C)
Daniel Kingb8025c52016-05-17 14:43:01 -030012
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020013#include "mbedtls/chachapoly.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020014#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000015#include "mbedtls/error.h"
Dave Rodgmand26a3d62023-09-11 18:25:16 +010016#include "mbedtls/constant_time.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020017
Daniel Kingb8025c52016-05-17 14:43:01 -030018#include <string.h>
19
Daniel Kingb8025c52016-05-17 14:43:01 -030020#include "mbedtls/platform.h"
Daniel Kingb8025c52016-05-17 14:43:01 -030021
Gilles Peskine449bd832023-01-11 14:50:10 +010022#define CHACHAPOLY_STATE_INIT (0)
23#define CHACHAPOLY_STATE_AAD (1)
24#define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
25#define CHACHAPOLY_STATE_FINISHED (3)
Daniel Kingb8025c52016-05-17 14:43:01 -030026
Daniel Kingb8025c52016-05-17 14:43:01 -030027/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020028 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030029 *
30 * \param ctx The ChaCha20-Poly1305 context.
31 */
Gilles Peskine449bd832023-01-11 14:50:10 +010032static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030033{
Gilles Peskine449bd832023-01-11 14:50:10 +010034 uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030035 unsigned char zeroes[15];
36
Gilles Peskine449bd832023-01-11 14:50:10 +010037 if (partial_block_len == 0U) {
38 return 0;
39 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020040
Gilles Peskine449bd832023-01-11 14:50:10 +010041 memset(zeroes, 0, sizeof(zeroes));
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020042
Gilles Peskine449bd832023-01-11 14:50:10 +010043 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
44 zeroes,
45 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030046}
47
48/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020049 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030050 *
51 * \param ctx The ChaCha20-Poly1305 context.
52 */
Gilles Peskine449bd832023-01-11 14:50:10 +010053static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030054{
Gilles Peskine449bd832023-01-11 14:50:10 +010055 uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030056 unsigned char zeroes[15];
57
Gilles Peskine449bd832023-01-11 14:50:10 +010058 if (partial_block_len == 0U) {
59 return 0;
60 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020061
Gilles Peskine449bd832023-01-11 14:50:10 +010062 memset(zeroes, 0, sizeof(zeroes));
63 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
64 zeroes,
65 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030066}
67
Gilles Peskine449bd832023-01-11 14:50:10 +010068void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030069{
Gilles Peskine449bd832023-01-11 14:50:10 +010070 mbedtls_chacha20_init(&ctx->chacha20_ctx);
71 mbedtls_poly1305_init(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050072 ctx->aad_len = 0U;
73 ctx->ciphertext_len = 0U;
74 ctx->state = CHACHAPOLY_STATE_INIT;
75 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -030076}
77
Gilles Peskine449bd832023-01-11 14:50:10 +010078void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030079{
Gilles Peskine449bd832023-01-11 14:50:10 +010080 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050081 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010082 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050083
Gilles Peskine449bd832023-01-11 14:50:10 +010084 mbedtls_chacha20_free(&ctx->chacha20_ctx);
85 mbedtls_poly1305_free(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050086 ctx->aad_len = 0U;
87 ctx->ciphertext_len = 0U;
88 ctx->state = CHACHAPOLY_STATE_INIT;
89 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -030090}
91
Gilles Peskine449bd832023-01-11 14:50:10 +010092int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
93 const unsigned char key[32])
Daniel Kingb8025c52016-05-17 14:43:01 -030094{
Janos Follath24eed8d2019-11-22 13:21:35 +000095 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -030096
Gilles Peskine449bd832023-01-11 14:50:10 +010097 ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
Daniel Kingb8025c52016-05-17 14:43:01 -030098
Gilles Peskine449bd832023-01-11 14:50:10 +010099 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300100}
101
Gilles Peskine449bd832023-01-11 14:50:10 +0100102int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
103 const unsigned char nonce[12],
104 mbedtls_chachapoly_mode_t mode)
Daniel Kingb8025c52016-05-17 14:43:01 -0300105{
Janos Follath24eed8d2019-11-22 13:21:35 +0000106 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300107 unsigned char poly1305_key[64];
Daniel Kingb8025c52016-05-17 14:43:01 -0300108
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200109 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
111 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300112 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100113 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300114
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200115 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
116 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300117 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
118 * The other 256 bits are discarded.
119 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100120 memset(poly1305_key, 0, sizeof(poly1305_key));
121 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
122 poly1305_key, poly1305_key);
123 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300124 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100125 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300126
Gilles Peskine449bd832023-01-11 14:50:10 +0100127 ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300128
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 if (ret == 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300130 ctx->aad_len = 0U;
131 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200132 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300133 ctx->mode = mode;
134 }
135
136cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 mbedtls_platform_zeroize(poly1305_key, 64U);
138 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300139}
140
Gilles Peskine449bd832023-01-11 14:50:10 +0100141int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
142 const unsigned char *aad,
143 size_t aad_len)
Daniel Kingb8025c52016-05-17 14:43:01 -0300144{
Gilles Peskine449bd832023-01-11 14:50:10 +0100145 if (ctx->state != CHACHAPOLY_STATE_AAD) {
146 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
147 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300148
149 ctx->aad_len += aad_len;
150
Gilles Peskine449bd832023-01-11 14:50:10 +0100151 return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
Daniel Kingb8025c52016-05-17 14:43:01 -0300152}
153
Gilles Peskine449bd832023-01-11 14:50:10 +0100154int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
155 size_t len,
156 const unsigned char *input,
157 unsigned char *output)
Daniel Kingb8025c52016-05-17 14:43:01 -0300158{
Janos Follath24eed8d2019-11-22 13:21:35 +0000159 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200160
Gilles Peskine449bd832023-01-11 14:50:10 +0100161 if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
162 (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
163 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300164 }
165
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 if (ctx->state == CHACHAPOLY_STATE_AAD) {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200167 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300168
Gilles Peskine449bd832023-01-11 14:50:10 +0100169 ret = chachapoly_pad_aad(ctx);
170 if (ret != 0) {
171 return ret;
172 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300173 }
174
175 ctx->ciphertext_len += len;
176
Gilles Peskine449bd832023-01-11 14:50:10 +0100177 if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
178 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
179 if (ret != 0) {
180 return ret;
181 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200182
Gilles Peskine449bd832023-01-11 14:50:10 +0100183 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
184 if (ret != 0) {
185 return ret;
186 }
187 } else { /* DECRYPT */
188 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
189 if (ret != 0) {
190 return ret;
191 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200192
Gilles Peskine449bd832023-01-11 14:50:10 +0100193 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
194 if (ret != 0) {
195 return ret;
196 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300197 }
198
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300200}
201
Gilles Peskine449bd832023-01-11 14:50:10 +0100202int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
203 unsigned char mac[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300204{
Janos Follath24eed8d2019-11-22 13:21:35 +0000205 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300206 unsigned char len_block[16];
207
Gilles Peskine449bd832023-01-11 14:50:10 +0100208 if (ctx->state == CHACHAPOLY_STATE_INIT) {
209 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300210 }
211
Gilles Peskine449bd832023-01-11 14:50:10 +0100212 if (ctx->state == CHACHAPOLY_STATE_AAD) {
213 ret = chachapoly_pad_aad(ctx);
214 if (ret != 0) {
215 return ret;
216 }
217 } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
218 ret = chachapoly_pad_ciphertext(ctx);
219 if (ret != 0) {
220 return ret;
221 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300222 }
223
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200224 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300225
226 /* The lengths of the AAD and ciphertext are processed by
227 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
228 */
Joe Subbianib6511b02021-07-16 15:02:55 +0100229 MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
230 MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
Daniel Kingb8025c52016-05-17 14:43:01 -0300231
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
233 if (ret != 0) {
234 return ret;
235 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300236
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200238
Gilles Peskine449bd832023-01-11 14:50:10 +0100239 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300240}
241
Gilles Peskine449bd832023-01-11 14:50:10 +0100242static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
243 mbedtls_chachapoly_mode_t mode,
244 size_t length,
245 const unsigned char nonce[12],
246 const unsigned char *aad,
247 size_t aad_len,
248 const unsigned char *input,
249 unsigned char *output,
250 unsigned char tag[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300251{
Janos Follath24eed8d2019-11-22 13:21:35 +0000252 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300253
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
255 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300256 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300258
Gilles Peskine449bd832023-01-11 14:50:10 +0100259 ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
260 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200261 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100262 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300263
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 ret = mbedtls_chachapoly_update(ctx, length, input, output);
265 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200266 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100267 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300268
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 ret = mbedtls_chachapoly_finish(ctx, tag);
Daniel Kingb8025c52016-05-17 14:43:01 -0300270
271cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300273}
274
Gilles Peskine449bd832023-01-11 14:50:10 +0100275int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
276 size_t length,
277 const unsigned char nonce[12],
278 const unsigned char *aad,
279 size_t aad_len,
280 const unsigned char *input,
281 unsigned char *output,
282 unsigned char tag[16])
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200283{
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
285 length, nonce, aad, aad_len,
286 input, output, tag);
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200287}
288
Gilles Peskine449bd832023-01-11 14:50:10 +0100289int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
290 size_t length,
291 const unsigned char nonce[12],
292 const unsigned char *aad,
293 size_t aad_len,
294 const unsigned char tag[16],
295 const unsigned char *input,
296 unsigned char *output)
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200297{
Janos Follath24eed8d2019-11-22 13:21:35 +0000298 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200299 unsigned char check_tag[16];
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200300 int diff;
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200301
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 if ((ret = chachapoly_crypt_and_tag(ctx,
303 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
304 aad, aad_len, input, output, check_tag)) != 0) {
305 return ret;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200306 }
307
308 /* Check tag in "constant-time" */
Dave Rodgmand26a3d62023-09-11 18:25:16 +0100309 diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200310
Gilles Peskine449bd832023-01-11 14:50:10 +0100311 if (diff != 0) {
312 mbedtls_platform_zeroize(output, length);
313 return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
314 }
315
316 return 0;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200317}
318
Daniel Kingb8025c52016-05-17 14:43:01 -0300319#if defined(MBEDTLS_SELF_TEST)
320
321static const unsigned char test_key[1][32] =
322{
323 {
324 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
325 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
326 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
327 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
328 }
329};
330
331static const unsigned char test_nonce[1][12] =
332{
333 {
334 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
335 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
336 }
337};
338
339static const unsigned char test_aad[1][12] =
340{
341 {
342 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
343 0xc4, 0xc5, 0xc6, 0xc7
344 }
345};
346
347static const size_t test_aad_len[1] =
348{
349 12U
350};
351
352static const unsigned char test_input[1][114] =
353{
354 {
355 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
356 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
357 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
358 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
359 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
360 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
361 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
362 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
363 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
364 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
365 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
366 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
367 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
368 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
369 0x74, 0x2e
370 }
371};
372
373static const unsigned char test_output[1][114] =
374{
375 {
376 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
377 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
378 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
379 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
380 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
381 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
382 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
383 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
384 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
385 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
386 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
387 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
388 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
389 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
390 0x61, 0x16
391 }
392};
393
394static const size_t test_input_len[1] =
395{
396 114U
397};
398
399static const unsigned char test_mac[1][16] =
400{
401 {
402 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
403 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
404 }
405};
406
Ouss4e0b26872020-08-11 16:07:09 +0100407/* Make sure no other definition is already present. */
408#undef ASSERT
409
Gilles Peskine449bd832023-01-11 14:50:10 +0100410#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200411 do \
412 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100413 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200414 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 if (verbose != 0) \
416 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200417 \
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200419 } \
420 } \
Gilles Peskine449bd832023-01-11 14:50:10 +0100421 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200422
Gilles Peskine449bd832023-01-11 14:50:10 +0100423int mbedtls_chachapoly_self_test(int verbose)
Daniel Kingb8025c52016-05-17 14:43:01 -0300424{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200425 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200426 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000427 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300428 unsigned char output[200];
429 unsigned char mac[16];
430
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 for (i = 0U; i < 1U; i++) {
432 if (verbose != 0) {
433 mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
434 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300435
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 mbedtls_chachapoly_init(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200437
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
439 ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200440
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
442 test_input_len[i],
443 test_nonce[i],
444 test_aad[i],
445 test_aad_len[i],
446 test_input[i],
447 output,
448 mac);
Daniel Kingb8025c52016-05-17 14:43:01 -0300449
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
Daniel Kingb8025c52016-05-17 14:43:01 -0300451
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
453 ("failure (wrong output)\n"));
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200454
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 ASSERT(0 == memcmp(mac, test_mac[i], 16U),
456 ("failure (wrong MAC)\n"));
Daniel Kingdedf4a32016-05-18 10:07:53 -0300457
Gilles Peskine449bd832023-01-11 14:50:10 +0100458 mbedtls_chachapoly_free(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200459
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 if (verbose != 0) {
461 mbedtls_printf("passed\n");
462 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300463 }
464
Gilles Peskine449bd832023-01-11 14:50:10 +0100465 if (verbose != 0) {
466 mbedtls_printf("\n");
467 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300468
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300470}
471
472#endif /* MBEDTLS_SELF_TEST */
473
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200474#endif /* MBEDTLS_CHACHAPOLY_C */