blob: dd678f4c331d7d6418da2d150c69d7be578ca79a [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 Rodgman7ff79652023-11-03 12:04:52 +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 Rodgmanc2805202023-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
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050024/* Parameter validation macros */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010025#define CHACHAPOLY_VALIDATE_RET(cond) \
26 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA)
27#define CHACHAPOLY_VALIDATE(cond) \
28 MBEDTLS_INTERNAL_VALIDATE(cond)
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050029
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010030#define CHACHAPOLY_STATE_INIT (0)
31#define CHACHAPOLY_STATE_AAD (1)
32#define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
33#define CHACHAPOLY_STATE_FINISHED (3)
Daniel Kingb8025c52016-05-17 14:43:01 -030034
Daniel Kingb8025c52016-05-17 14:43:01 -030035/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020036 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030037 *
38 * \param ctx The ChaCha20-Poly1305 context.
39 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010040static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030041{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010042 uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030043 unsigned char zeroes[15];
44
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010045 if (partial_block_len == 0U) {
46 return 0;
47 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020048
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010049 memset(zeroes, 0, sizeof(zeroes));
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020050
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010051 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
52 zeroes,
53 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030054}
55
56/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020057 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030058 *
59 * \param ctx The ChaCha20-Poly1305 context.
60 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010061static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030062{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010063 uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030064 unsigned char zeroes[15];
65
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010066 if (partial_block_len == 0U) {
67 return 0;
68 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020069
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010070 memset(zeroes, 0, sizeof(zeroes));
71 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
72 zeroes,
73 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030074}
75
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010076void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030077{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010078 CHACHAPOLY_VALIDATE(ctx != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050079
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010080 mbedtls_chacha20_init(&ctx->chacha20_ctx);
81 mbedtls_poly1305_init(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050082 ctx->aad_len = 0U;
83 ctx->ciphertext_len = 0U;
84 ctx->state = CHACHAPOLY_STATE_INIT;
85 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -030086}
87
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010088void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030089{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010090 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050091 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010092 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050093
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010094 mbedtls_chacha20_free(&ctx->chacha20_ctx);
95 mbedtls_poly1305_free(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050096 ctx->aad_len = 0U;
97 ctx->ciphertext_len = 0U;
98 ctx->state = CHACHAPOLY_STATE_INIT;
99 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300100}
101
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100102int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
103 const unsigned char key[32])
Daniel Kingb8025c52016-05-17 14:43:01 -0300104{
Janos Follath24eed8d2019-11-22 13:21:35 +0000105 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100106 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
107 CHACHAPOLY_VALIDATE_RET(key != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300108
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100109 ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300110
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100111 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300112}
113
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100114int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
115 const unsigned char nonce[12],
116 mbedtls_chachapoly_mode_t mode)
Daniel Kingb8025c52016-05-17 14:43:01 -0300117{
Janos Follath24eed8d2019-11-22 13:21:35 +0000118 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300119 unsigned char poly1305_key[64];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100120 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
121 CHACHAPOLY_VALIDATE_RET(nonce != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300122
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200123 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100124 ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
125 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300126 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100127 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300128
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200129 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
130 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300131 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
132 * The other 256 bits are discarded.
133 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100134 memset(poly1305_key, 0, sizeof(poly1305_key));
135 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
136 poly1305_key, poly1305_key);
137 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300138 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100139 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300140
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100141 ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300142
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100143 if (ret == 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300144 ctx->aad_len = 0U;
145 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200146 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300147 ctx->mode = mode;
148 }
149
150cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151 mbedtls_platform_zeroize(poly1305_key, 64U);
152 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300153}
154
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100155int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
156 const unsigned char *aad,
157 size_t aad_len)
Daniel Kingb8025c52016-05-17 14:43:01 -0300158{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100159 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
160 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500161
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100162 if (ctx->state != CHACHAPOLY_STATE_AAD) {
163 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
164 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300165
166 ctx->aad_len += aad_len;
167
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100168 return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
Daniel Kingb8025c52016-05-17 14:43:01 -0300169}
170
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100171int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
172 size_t len,
173 const unsigned char *input,
174 unsigned char *output)
Daniel Kingb8025c52016-05-17 14:43:01 -0300175{
Janos Follath24eed8d2019-11-22 13:21:35 +0000176 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100177 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
178 CHACHAPOLY_VALIDATE_RET(len == 0 || input != NULL);
179 CHACHAPOLY_VALIDATE_RET(len == 0 || output != NULL);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200180
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100181 if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
182 (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
183 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300184 }
185
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100186 if (ctx->state == CHACHAPOLY_STATE_AAD) {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200187 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300188
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100189 ret = chachapoly_pad_aad(ctx);
190 if (ret != 0) {
191 return ret;
192 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300193 }
194
195 ctx->ciphertext_len += len;
196
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100197 if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
198 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
199 if (ret != 0) {
200 return ret;
201 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200202
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100203 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
204 if (ret != 0) {
205 return ret;
206 }
207 } else { /* DECRYPT */
208 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
209 if (ret != 0) {
210 return ret;
211 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200212
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100213 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
214 if (ret != 0) {
215 return ret;
216 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300217 }
218
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300220}
221
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100222int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
223 unsigned char mac[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300224{
Janos Follath24eed8d2019-11-22 13:21:35 +0000225 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300226 unsigned char len_block[16];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100227 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
228 CHACHAPOLY_VALIDATE_RET(mac != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300229
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100230 if (ctx->state == CHACHAPOLY_STATE_INIT) {
231 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300232 }
233
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100234 if (ctx->state == CHACHAPOLY_STATE_AAD) {
235 ret = chachapoly_pad_aad(ctx);
236 if (ret != 0) {
237 return ret;
238 }
239 } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
240 ret = chachapoly_pad_ciphertext(ctx);
241 if (ret != 0) {
242 return ret;
243 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300244 }
245
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200246 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300247
248 /* The lengths of the AAD and ciphertext are processed by
249 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
250 */
Joe Subbiani6627fb22021-07-16 15:02:55 +0100251 MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
252 MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
Daniel Kingb8025c52016-05-17 14:43:01 -0300253
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100254 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
255 if (ret != 0) {
256 return ret;
257 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300258
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100259 ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200260
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100261 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300262}
263
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100264static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
265 mbedtls_chachapoly_mode_t mode,
266 size_t length,
267 const unsigned char nonce[12],
268 const unsigned char *aad,
269 size_t aad_len,
270 const unsigned char *input,
271 unsigned char *output,
272 unsigned char tag[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300273{
Janos Follath24eed8d2019-11-22 13:21:35 +0000274 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300275
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100276 ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
277 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300278 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100279 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300280
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100281 ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
282 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200283 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100284 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300285
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100286 ret = mbedtls_chachapoly_update(ctx, length, input, output);
287 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200288 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100289 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300290
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100291 ret = mbedtls_chachapoly_finish(ctx, tag);
Daniel Kingb8025c52016-05-17 14:43:01 -0300292
293cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100294 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300295}
296
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100297int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
298 size_t length,
299 const unsigned char nonce[12],
300 const unsigned char *aad,
301 size_t aad_len,
302 const unsigned char *input,
303 unsigned char *output,
304 unsigned char tag[16])
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200305{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100306 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
307 CHACHAPOLY_VALIDATE_RET(nonce != NULL);
308 CHACHAPOLY_VALIDATE_RET(tag != NULL);
309 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
310 CHACHAPOLY_VALIDATE_RET(length == 0 || input != NULL);
311 CHACHAPOLY_VALIDATE_RET(length == 0 || output != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500312
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100313 return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
314 length, nonce, aad, aad_len,
315 input, output, tag);
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200316}
317
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100318int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
319 size_t length,
320 const unsigned char nonce[12],
321 const unsigned char *aad,
322 size_t aad_len,
323 const unsigned char tag[16],
324 const unsigned char *input,
325 unsigned char *output)
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200326{
Janos Follath24eed8d2019-11-22 13:21:35 +0000327 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200328 unsigned char check_tag[16];
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200329 int diff;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100330 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
331 CHACHAPOLY_VALIDATE_RET(nonce != NULL);
332 CHACHAPOLY_VALIDATE_RET(tag != NULL);
333 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
334 CHACHAPOLY_VALIDATE_RET(length == 0 || input != NULL);
335 CHACHAPOLY_VALIDATE_RET(length == 0 || output != NULL);
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200336
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100337 if ((ret = chachapoly_crypt_and_tag(ctx,
338 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
339 aad, aad_len, input, output, check_tag)) != 0) {
340 return ret;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200341 }
342
343 /* Check tag in "constant-time" */
Dave Rodgmanc2805202023-09-11 18:25:16 +0100344 diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200345
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100346 if (diff != 0) {
347 mbedtls_platform_zeroize(output, length);
348 return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
349 }
350
351 return 0;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200352}
353
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200354#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200355
Daniel Kingb8025c52016-05-17 14:43:01 -0300356#if defined(MBEDTLS_SELF_TEST)
357
358static const unsigned char test_key[1][32] =
359{
360 {
361 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
362 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
363 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
364 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
365 }
366};
367
368static const unsigned char test_nonce[1][12] =
369{
370 {
371 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
372 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
373 }
374};
375
376static const unsigned char test_aad[1][12] =
377{
378 {
379 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
380 0xc4, 0xc5, 0xc6, 0xc7
381 }
382};
383
384static const size_t test_aad_len[1] =
385{
386 12U
387};
388
389static const unsigned char test_input[1][114] =
390{
391 {
392 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
393 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
394 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
395 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
396 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
397 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
398 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
399 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
400 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
401 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
402 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
403 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
404 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
405 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
406 0x74, 0x2e
407 }
408};
409
410static const unsigned char test_output[1][114] =
411{
412 {
413 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
414 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
415 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
416 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
417 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
418 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
419 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
420 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
421 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
422 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
423 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
424 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
425 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
426 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
427 0x61, 0x16
428 }
429};
430
431static const size_t test_input_len[1] =
432{
433 114U
434};
435
436static const unsigned char test_mac[1][16] =
437{
438 {
439 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
440 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
441 }
442};
443
Ouss4e0b26872020-08-11 16:07:09 +0100444/* Make sure no other definition is already present. */
445#undef ASSERT
446
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100447#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200448 do \
449 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100450 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200451 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100452 if (verbose != 0) \
453 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200454 \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100455 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200456 } \
457 } \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100458 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200459
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100460int mbedtls_chachapoly_self_test(int verbose)
Daniel Kingb8025c52016-05-17 14:43:01 -0300461{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200462 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200463 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000464 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300465 unsigned char output[200];
466 unsigned char mac[16];
467
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100468 for (i = 0U; i < 1U; i++) {
469 if (verbose != 0) {
470 mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
471 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300472
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100473 mbedtls_chachapoly_init(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200474
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100475 ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
476 ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200477
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100478 ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
479 test_input_len[i],
480 test_nonce[i],
481 test_aad[i],
482 test_aad_len[i],
483 test_input[i],
484 output,
485 mac);
Daniel Kingb8025c52016-05-17 14:43:01 -0300486
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100487 ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
Daniel Kingb8025c52016-05-17 14:43:01 -0300488
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100489 ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
490 ("failure (wrong output)\n"));
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200491
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100492 ASSERT(0 == memcmp(mac, test_mac[i], 16U),
493 ("failure (wrong MAC)\n"));
Daniel Kingdedf4a32016-05-18 10:07:53 -0300494
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100495 mbedtls_chachapoly_free(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200496
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100497 if (verbose != 0) {
498 mbedtls_printf("passed\n");
499 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300500 }
501
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100502 if (verbose != 0) {
503 mbedtls_printf("\n");
504 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300505
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100506 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300507}
508
509#endif /* MBEDTLS_SELF_TEST */
510
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200511#endif /* MBEDTLS_CHACHAPOLY_C */