blob: a1314eab6dfba44204dfef4cf5a10e135fd09875 [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
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020022#if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030023
Gilles Peskine449bd832023-01-11 14:50:10 +010024#define CHACHAPOLY_STATE_INIT (0)
25#define CHACHAPOLY_STATE_AAD (1)
26#define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
27#define CHACHAPOLY_STATE_FINISHED (3)
Daniel Kingb8025c52016-05-17 14:43:01 -030028
Daniel Kingb8025c52016-05-17 14:43:01 -030029/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020030 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030031 *
32 * \param ctx The ChaCha20-Poly1305 context.
33 */
Gilles Peskine449bd832023-01-11 14:50:10 +010034static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030035{
Gilles Peskine449bd832023-01-11 14:50:10 +010036 uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030037 unsigned char zeroes[15];
38
Gilles Peskine449bd832023-01-11 14:50:10 +010039 if (partial_block_len == 0U) {
40 return 0;
41 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020042
Gilles Peskine449bd832023-01-11 14:50:10 +010043 memset(zeroes, 0, sizeof(zeroes));
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020044
Gilles Peskine449bd832023-01-11 14:50:10 +010045 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
46 zeroes,
47 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030048}
49
50/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020051 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030052 *
53 * \param ctx The ChaCha20-Poly1305 context.
54 */
Gilles Peskine449bd832023-01-11 14:50:10 +010055static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030056{
Gilles Peskine449bd832023-01-11 14:50:10 +010057 uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030058 unsigned char zeroes[15];
59
Gilles Peskine449bd832023-01-11 14:50:10 +010060 if (partial_block_len == 0U) {
61 return 0;
62 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020063
Gilles Peskine449bd832023-01-11 14:50:10 +010064 memset(zeroes, 0, sizeof(zeroes));
65 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
66 zeroes,
67 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030068}
69
Gilles Peskine449bd832023-01-11 14:50:10 +010070void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030071{
Gilles Peskine449bd832023-01-11 14:50:10 +010072 mbedtls_chacha20_init(&ctx->chacha20_ctx);
73 mbedtls_poly1305_init(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050074 ctx->aad_len = 0U;
75 ctx->ciphertext_len = 0U;
76 ctx->state = CHACHAPOLY_STATE_INIT;
77 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -030078}
79
Gilles Peskine449bd832023-01-11 14:50:10 +010080void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030081{
Gilles Peskine449bd832023-01-11 14:50:10 +010082 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050083 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010084 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050085
Gilles Peskine449bd832023-01-11 14:50:10 +010086 mbedtls_chacha20_free(&ctx->chacha20_ctx);
87 mbedtls_poly1305_free(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050088 ctx->aad_len = 0U;
89 ctx->ciphertext_len = 0U;
90 ctx->state = CHACHAPOLY_STATE_INIT;
91 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -030092}
93
Gilles Peskine449bd832023-01-11 14:50:10 +010094int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
95 const unsigned char key[32])
Daniel Kingb8025c52016-05-17 14:43:01 -030096{
Janos Follath24eed8d2019-11-22 13:21:35 +000097 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -030098
Gilles Peskine449bd832023-01-11 14:50:10 +010099 ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300100
Gilles Peskine449bd832023-01-11 14:50:10 +0100101 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300102}
103
Gilles Peskine449bd832023-01-11 14:50:10 +0100104int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
105 const unsigned char nonce[12],
106 mbedtls_chachapoly_mode_t mode)
Daniel Kingb8025c52016-05-17 14:43:01 -0300107{
Janos Follath24eed8d2019-11-22 13:21:35 +0000108 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300109 unsigned char poly1305_key[64];
Daniel Kingb8025c52016-05-17 14:43:01 -0300110
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200111 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100112 ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
113 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300114 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100115 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300116
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200117 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
118 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300119 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
120 * The other 256 bits are discarded.
121 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100122 memset(poly1305_key, 0, sizeof(poly1305_key));
123 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
124 poly1305_key, poly1305_key);
125 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300126 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100127 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300128
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300130
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 if (ret == 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300132 ctx->aad_len = 0U;
133 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200134 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300135 ctx->mode = mode;
136 }
137
138cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 mbedtls_platform_zeroize(poly1305_key, 64U);
140 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300141}
142
Gilles Peskine449bd832023-01-11 14:50:10 +0100143int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
144 const unsigned char *aad,
145 size_t aad_len)
Daniel Kingb8025c52016-05-17 14:43:01 -0300146{
Gilles Peskine449bd832023-01-11 14:50:10 +0100147 if (ctx->state != CHACHAPOLY_STATE_AAD) {
148 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
149 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300150
151 ctx->aad_len += aad_len;
152
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
Daniel Kingb8025c52016-05-17 14:43:01 -0300154}
155
Gilles Peskine449bd832023-01-11 14:50:10 +0100156int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
157 size_t len,
158 const unsigned char *input,
159 unsigned char *output)
Daniel Kingb8025c52016-05-17 14:43:01 -0300160{
Janos Follath24eed8d2019-11-22 13:21:35 +0000161 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200162
Gilles Peskine449bd832023-01-11 14:50:10 +0100163 if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
164 (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
165 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300166 }
167
Gilles Peskine449bd832023-01-11 14:50:10 +0100168 if (ctx->state == CHACHAPOLY_STATE_AAD) {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200169 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300170
Gilles Peskine449bd832023-01-11 14:50:10 +0100171 ret = chachapoly_pad_aad(ctx);
172 if (ret != 0) {
173 return ret;
174 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300175 }
176
177 ctx->ciphertext_len += len;
178
Gilles Peskine449bd832023-01-11 14:50:10 +0100179 if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
180 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
181 if (ret != 0) {
182 return ret;
183 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200184
Gilles Peskine449bd832023-01-11 14:50:10 +0100185 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
186 if (ret != 0) {
187 return ret;
188 }
189 } else { /* DECRYPT */
190 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
191 if (ret != 0) {
192 return ret;
193 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200194
Gilles Peskine449bd832023-01-11 14:50:10 +0100195 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
196 if (ret != 0) {
197 return ret;
198 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300199 }
200
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300202}
203
Gilles Peskine449bd832023-01-11 14:50:10 +0100204int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
205 unsigned char mac[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300206{
Janos Follath24eed8d2019-11-22 13:21:35 +0000207 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300208 unsigned char len_block[16];
209
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 if (ctx->state == CHACHAPOLY_STATE_INIT) {
211 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300212 }
213
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 if (ctx->state == CHACHAPOLY_STATE_AAD) {
215 ret = chachapoly_pad_aad(ctx);
216 if (ret != 0) {
217 return ret;
218 }
219 } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
220 ret = chachapoly_pad_ciphertext(ctx);
221 if (ret != 0) {
222 return ret;
223 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300224 }
225
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200226 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300227
228 /* The lengths of the AAD and ciphertext are processed by
229 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
230 */
Joe Subbianib6511b02021-07-16 15:02:55 +0100231 MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
232 MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
Daniel Kingb8025c52016-05-17 14:43:01 -0300233
Gilles Peskine449bd832023-01-11 14:50:10 +0100234 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
235 if (ret != 0) {
236 return ret;
237 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300238
Gilles Peskine449bd832023-01-11 14:50:10 +0100239 ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200240
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300242}
243
Gilles Peskine449bd832023-01-11 14:50:10 +0100244static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
245 mbedtls_chachapoly_mode_t mode,
246 size_t length,
247 const unsigned char nonce[12],
248 const unsigned char *aad,
249 size_t aad_len,
250 const unsigned char *input,
251 unsigned char *output,
252 unsigned char tag[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300253{
Janos Follath24eed8d2019-11-22 13:21:35 +0000254 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300255
Gilles Peskine449bd832023-01-11 14:50:10 +0100256 ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
257 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300258 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100259 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300260
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
262 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200263 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300265
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 ret = mbedtls_chachapoly_update(ctx, length, input, output);
267 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200268 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300270
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 ret = mbedtls_chachapoly_finish(ctx, tag);
Daniel Kingb8025c52016-05-17 14:43:01 -0300272
273cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300275}
276
Gilles Peskine449bd832023-01-11 14:50:10 +0100277int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
278 size_t length,
279 const unsigned char nonce[12],
280 const unsigned char *aad,
281 size_t aad_len,
282 const unsigned char *input,
283 unsigned char *output,
284 unsigned char tag[16])
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200285{
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
287 length, nonce, aad, aad_len,
288 input, output, tag);
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200289}
290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
292 size_t length,
293 const unsigned char nonce[12],
294 const unsigned char *aad,
295 size_t aad_len,
296 const unsigned char tag[16],
297 const unsigned char *input,
298 unsigned char *output)
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200299{
Janos Follath24eed8d2019-11-22 13:21:35 +0000300 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200301 unsigned char check_tag[16];
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200302 int diff;
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200303
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 if ((ret = chachapoly_crypt_and_tag(ctx,
305 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
306 aad, aad_len, input, output, check_tag)) != 0) {
307 return ret;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200308 }
309
310 /* Check tag in "constant-time" */
Dave Rodgmand26a3d62023-09-11 18:25:16 +0100311 diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200312
Gilles Peskine449bd832023-01-11 14:50:10 +0100313 if (diff != 0) {
314 mbedtls_platform_zeroize(output, length);
315 return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
316 }
317
318 return 0;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200319}
320
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200321#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200322
Daniel Kingb8025c52016-05-17 14:43:01 -0300323#if defined(MBEDTLS_SELF_TEST)
324
325static const unsigned char test_key[1][32] =
326{
327 {
328 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
329 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
330 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
331 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
332 }
333};
334
335static const unsigned char test_nonce[1][12] =
336{
337 {
338 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
339 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
340 }
341};
342
343static const unsigned char test_aad[1][12] =
344{
345 {
346 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
347 0xc4, 0xc5, 0xc6, 0xc7
348 }
349};
350
351static const size_t test_aad_len[1] =
352{
353 12U
354};
355
356static const unsigned char test_input[1][114] =
357{
358 {
359 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
360 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
361 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
362 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
363 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
364 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
365 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
366 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
367 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
368 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
369 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
370 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
371 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
372 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
373 0x74, 0x2e
374 }
375};
376
377static const unsigned char test_output[1][114] =
378{
379 {
380 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
381 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
382 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
383 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
384 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
385 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
386 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
387 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
388 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
389 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
390 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
391 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
392 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
393 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
394 0x61, 0x16
395 }
396};
397
398static const size_t test_input_len[1] =
399{
400 114U
401};
402
403static const unsigned char test_mac[1][16] =
404{
405 {
406 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
407 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
408 }
409};
410
Ouss4e0b26872020-08-11 16:07:09 +0100411/* Make sure no other definition is already present. */
412#undef ASSERT
413
Gilles Peskine449bd832023-01-11 14:50:10 +0100414#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200415 do \
416 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100417 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200418 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100419 if (verbose != 0) \
420 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200421 \
Gilles Peskine449bd832023-01-11 14:50:10 +0100422 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200423 } \
424 } \
Gilles Peskine449bd832023-01-11 14:50:10 +0100425 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200426
Gilles Peskine449bd832023-01-11 14:50:10 +0100427int mbedtls_chachapoly_self_test(int verbose)
Daniel Kingb8025c52016-05-17 14:43:01 -0300428{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200429 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200430 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000431 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300432 unsigned char output[200];
433 unsigned char mac[16];
434
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 for (i = 0U; i < 1U; i++) {
436 if (verbose != 0) {
437 mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
438 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300439
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 mbedtls_chachapoly_init(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200441
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
443 ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
446 test_input_len[i],
447 test_nonce[i],
448 test_aad[i],
449 test_aad_len[i],
450 test_input[i],
451 output,
452 mac);
Daniel Kingb8025c52016-05-17 14:43:01 -0300453
Gilles Peskine449bd832023-01-11 14:50:10 +0100454 ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
Daniel Kingb8025c52016-05-17 14:43:01 -0300455
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
457 ("failure (wrong output)\n"));
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200458
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 ASSERT(0 == memcmp(mac, test_mac[i], 16U),
460 ("failure (wrong MAC)\n"));
Daniel Kingdedf4a32016-05-18 10:07:53 -0300461
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 mbedtls_chachapoly_free(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200463
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 if (verbose != 0) {
465 mbedtls_printf("passed\n");
466 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300467 }
468
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 if (verbose != 0) {
470 mbedtls_printf("\n");
471 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300472
Gilles Peskine449bd832023-01-11 14:50:10 +0100473 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300474}
475
476#endif /* MBEDTLS_SELF_TEST */
477
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200478#endif /* MBEDTLS_CHACHAPOLY_C */