blob: aebc646aa06211edd19ce18d27fa1b3046cc64a1 [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
Daniel Kingb8025c52016-05-17 14:43:01 -03007 * SPDX-License-Identifier: Apache-2.0
8 *
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.
Daniel Kingb8025c52016-05-17 14:43:01 -030020 */
Gilles Peskinedb09ef62020-06-03 01:43:33 +020021#include "common.h"
Daniel Kingb8025c52016-05-17 14:43:01 -030022
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020023#if defined(MBEDTLS_CHACHAPOLY_C)
Daniel Kingb8025c52016-05-17 14:43:01 -030024
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020025#include "mbedtls/chachapoly.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020026#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000027#include "mbedtls/error.h"
Dave Rodgmand26a3d62023-09-11 18:25:16 +010028#include "mbedtls/constant_time.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020029
Daniel Kingb8025c52016-05-17 14:43:01 -030030#include <string.h>
31
Daniel Kingb8025c52016-05-17 14:43:01 -030032#include "mbedtls/platform.h"
Daniel Kingb8025c52016-05-17 14:43:01 -030033
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020034#if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030035
Gilles Peskine449bd832023-01-11 14:50:10 +010036#define CHACHAPOLY_STATE_INIT (0)
37#define CHACHAPOLY_STATE_AAD (1)
38#define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
39#define CHACHAPOLY_STATE_FINISHED (3)
Daniel Kingb8025c52016-05-17 14:43:01 -030040
Daniel Kingb8025c52016-05-17 14:43:01 -030041/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020042 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030043 *
44 * \param ctx The ChaCha20-Poly1305 context.
45 */
Gilles Peskine449bd832023-01-11 14:50:10 +010046static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030047{
Gilles Peskine449bd832023-01-11 14:50:10 +010048 uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030049 unsigned char zeroes[15];
50
Gilles Peskine449bd832023-01-11 14:50:10 +010051 if (partial_block_len == 0U) {
52 return 0;
53 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020054
Gilles Peskine449bd832023-01-11 14:50:10 +010055 memset(zeroes, 0, sizeof(zeroes));
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020056
Gilles Peskine449bd832023-01-11 14:50:10 +010057 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
58 zeroes,
59 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030060}
61
62/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020063 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030064 *
65 * \param ctx The ChaCha20-Poly1305 context.
66 */
Gilles Peskine449bd832023-01-11 14:50:10 +010067static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030068{
Gilles Peskine449bd832023-01-11 14:50:10 +010069 uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030070 unsigned char zeroes[15];
71
Gilles Peskine449bd832023-01-11 14:50:10 +010072 if (partial_block_len == 0U) {
73 return 0;
74 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020075
Gilles Peskine449bd832023-01-11 14:50:10 +010076 memset(zeroes, 0, sizeof(zeroes));
77 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
78 zeroes,
79 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030080}
81
Gilles Peskine449bd832023-01-11 14:50:10 +010082void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030083{
Gilles Peskine449bd832023-01-11 14:50:10 +010084 mbedtls_chacha20_init(&ctx->chacha20_ctx);
85 mbedtls_poly1305_init(&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 +010092void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030093{
Gilles Peskine449bd832023-01-11 14:50:10 +010094 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050095 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010096 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050097
Gilles Peskine449bd832023-01-11 14:50:10 +010098 mbedtls_chacha20_free(&ctx->chacha20_ctx);
99 mbedtls_poly1305_free(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500100 ctx->aad_len = 0U;
101 ctx->ciphertext_len = 0U;
102 ctx->state = CHACHAPOLY_STATE_INIT;
103 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300104}
105
Gilles Peskine449bd832023-01-11 14:50:10 +0100106int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
107 const unsigned char key[32])
Daniel Kingb8025c52016-05-17 14:43:01 -0300108{
Janos Follath24eed8d2019-11-22 13:21:35 +0000109 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300110
Gilles Peskine449bd832023-01-11 14:50:10 +0100111 ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300112
Gilles Peskine449bd832023-01-11 14:50:10 +0100113 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300114}
115
Gilles Peskine449bd832023-01-11 14:50:10 +0100116int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
117 const unsigned char nonce[12],
118 mbedtls_chachapoly_mode_t mode)
Daniel Kingb8025c52016-05-17 14:43:01 -0300119{
Janos Follath24eed8d2019-11-22 13:21:35 +0000120 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300121 unsigned char poly1305_key[64];
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 Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +0100139 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300140
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300142
Gilles Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +0100151 mbedtls_platform_zeroize(poly1305_key, 64U);
152 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300153}
154
Gilles Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +0100159 if (ctx->state != CHACHAPOLY_STATE_AAD) {
160 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
161 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300162
163 ctx->aad_len += aad_len;
164
Gilles Peskine449bd832023-01-11 14:50:10 +0100165 return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
Daniel Kingb8025c52016-05-17 14:43:01 -0300166}
167
Gilles Peskine449bd832023-01-11 14:50:10 +0100168int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
169 size_t len,
170 const unsigned char *input,
171 unsigned char *output)
Daniel Kingb8025c52016-05-17 14:43:01 -0300172{
Janos Follath24eed8d2019-11-22 13:21:35 +0000173 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200174
Gilles Peskine449bd832023-01-11 14:50:10 +0100175 if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
176 (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
177 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300178 }
179
Gilles Peskine449bd832023-01-11 14:50:10 +0100180 if (ctx->state == CHACHAPOLY_STATE_AAD) {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200181 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300182
Gilles Peskine449bd832023-01-11 14:50:10 +0100183 ret = chachapoly_pad_aad(ctx);
184 if (ret != 0) {
185 return ret;
186 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300187 }
188
189 ctx->ciphertext_len += len;
190
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
192 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
193 if (ret != 0) {
194 return ret;
195 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200196
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
198 if (ret != 0) {
199 return ret;
200 }
201 } else { /* DECRYPT */
202 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
203 if (ret != 0) {
204 return ret;
205 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200206
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
208 if (ret != 0) {
209 return ret;
210 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300211 }
212
Gilles Peskine449bd832023-01-11 14:50:10 +0100213 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300214}
215
Gilles Peskine449bd832023-01-11 14:50:10 +0100216int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
217 unsigned char mac[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300218{
Janos Follath24eed8d2019-11-22 13:21:35 +0000219 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300220 unsigned char len_block[16];
221
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 if (ctx->state == CHACHAPOLY_STATE_INIT) {
223 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300224 }
225
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 if (ctx->state == CHACHAPOLY_STATE_AAD) {
227 ret = chachapoly_pad_aad(ctx);
228 if (ret != 0) {
229 return ret;
230 }
231 } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
232 ret = chachapoly_pad_ciphertext(ctx);
233 if (ret != 0) {
234 return ret;
235 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300236 }
237
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200238 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300239
240 /* The lengths of the AAD and ciphertext are processed by
241 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
242 */
Joe Subbianib6511b02021-07-16 15:02:55 +0100243 MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
244 MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
Daniel Kingb8025c52016-05-17 14:43:01 -0300245
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
247 if (ret != 0) {
248 return ret;
249 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300250
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200252
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300254}
255
Gilles Peskine449bd832023-01-11 14:50:10 +0100256static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
257 mbedtls_chachapoly_mode_t mode,
258 size_t length,
259 const unsigned char nonce[12],
260 const unsigned char *aad,
261 size_t aad_len,
262 const unsigned char *input,
263 unsigned char *output,
264 unsigned char tag[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300265{
Janos Follath24eed8d2019-11-22 13:21:35 +0000266 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300267
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
269 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300270 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300272
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
274 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200275 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300277
Gilles Peskine449bd832023-01-11 14:50:10 +0100278 ret = mbedtls_chachapoly_update(ctx, length, input, output);
279 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200280 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300282
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 ret = mbedtls_chachapoly_finish(ctx, tag);
Daniel Kingb8025c52016-05-17 14:43:01 -0300284
285cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300287}
288
Gilles Peskine449bd832023-01-11 14:50:10 +0100289int mbedtls_chachapoly_encrypt_and_tag(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 *input,
295 unsigned char *output,
296 unsigned char tag[16])
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200297{
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
299 length, nonce, aad, aad_len,
300 input, output, tag);
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200301}
302
Gilles Peskine449bd832023-01-11 14:50:10 +0100303int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
304 size_t length,
305 const unsigned char nonce[12],
306 const unsigned char *aad,
307 size_t aad_len,
308 const unsigned char tag[16],
309 const unsigned char *input,
310 unsigned char *output)
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200311{
Janos Follath24eed8d2019-11-22 13:21:35 +0000312 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200313 unsigned char check_tag[16];
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200314 int diff;
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200315
Gilles Peskine449bd832023-01-11 14:50:10 +0100316 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;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200320 }
321
322 /* Check tag in "constant-time" */
Dave Rodgmand26a3d62023-09-11 18:25:16 +0100323 diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200324
Gilles Peskine449bd832023-01-11 14:50:10 +0100325 if (diff != 0) {
326 mbedtls_platform_zeroize(output, length);
327 return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
328 }
329
330 return 0;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200331}
332
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200333#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200334
Daniel Kingb8025c52016-05-17 14:43:01 -0300335#if defined(MBEDTLS_SELF_TEST)
336
337static const unsigned char test_key[1][32] =
338{
339 {
340 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
341 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
342 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
343 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
344 }
345};
346
347static const unsigned char test_nonce[1][12] =
348{
349 {
350 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
351 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
352 }
353};
354
355static const unsigned char test_aad[1][12] =
356{
357 {
358 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
359 0xc4, 0xc5, 0xc6, 0xc7
360 }
361};
362
363static const size_t test_aad_len[1] =
364{
365 12U
366};
367
368static const unsigned char test_input[1][114] =
369{
370 {
371 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
372 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
373 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
374 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
375 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
376 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
377 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
378 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
379 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
380 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
381 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
382 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
383 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
384 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
385 0x74, 0x2e
386 }
387};
388
389static const unsigned char test_output[1][114] =
390{
391 {
392 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
393 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
394 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
395 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
396 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
397 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
398 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
399 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
400 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
401 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
402 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
403 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
404 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
405 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
406 0x61, 0x16
407 }
408};
409
410static const size_t test_input_len[1] =
411{
412 114U
413};
414
415static const unsigned char test_mac[1][16] =
416{
417 {
418 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
419 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
420 }
421};
422
Ouss4e0b26872020-08-11 16:07:09 +0100423/* Make sure no other definition is already present. */
424#undef ASSERT
425
Gilles Peskine449bd832023-01-11 14:50:10 +0100426#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200427 do \
428 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200430 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 if (verbose != 0) \
432 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200433 \
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200435 } \
436 } \
Gilles Peskine449bd832023-01-11 14:50:10 +0100437 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200438
Gilles Peskine449bd832023-01-11 14:50:10 +0100439int mbedtls_chachapoly_self_test(int verbose)
Daniel Kingb8025c52016-05-17 14:43:01 -0300440{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200441 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200442 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000443 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300444 unsigned char output[200];
445 unsigned char mac[16];
446
Gilles Peskine449bd832023-01-11 14:50:10 +0100447 for (i = 0U; i < 1U; i++) {
448 if (verbose != 0) {
449 mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
450 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300451
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 mbedtls_chachapoly_init(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200453
Gilles Peskine449bd832023-01-11 14:50:10 +0100454 ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
455 ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200456
Gilles Peskine449bd832023-01-11 14:50:10 +0100457 ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
458 test_input_len[i],
459 test_nonce[i],
460 test_aad[i],
461 test_aad_len[i],
462 test_input[i],
463 output,
464 mac);
Daniel Kingb8025c52016-05-17 14:43:01 -0300465
Gilles Peskine449bd832023-01-11 14:50:10 +0100466 ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
Daniel Kingb8025c52016-05-17 14:43:01 -0300467
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
469 ("failure (wrong output)\n"));
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200470
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 ASSERT(0 == memcmp(mac, test_mac[i], 16U),
472 ("failure (wrong MAC)\n"));
Daniel Kingdedf4a32016-05-18 10:07:53 -0300473
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 mbedtls_chachapoly_free(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200475
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 if (verbose != 0) {
477 mbedtls_printf("passed\n");
478 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300479 }
480
Gilles Peskine449bd832023-01-11 14:50:10 +0100481 if (verbose != 0) {
482 mbedtls_printf("\n");
483 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300484
Gilles Peskine449bd832023-01-11 14:50:10 +0100485 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300486}
487
488#endif /* MBEDTLS_SELF_TEST */
489
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200490#endif /* MBEDTLS_CHACHAPOLY_C */