blob: 0124d757016bbf83c20ea0ad14c743ff017088c6 [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"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020028
Daniel Kingb8025c52016-05-17 14:43:01 -030029#include <string.h>
30
Daniel Kingb8025c52016-05-17 14:43:01 -030031#include "mbedtls/platform.h"
Daniel Kingb8025c52016-05-17 14:43:01 -030032
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +020033#if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030034
Gilles Peskine449bd832023-01-11 14:50:10 +010035#define CHACHAPOLY_STATE_INIT (0)
36#define CHACHAPOLY_STATE_AAD (1)
37#define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
38#define CHACHAPOLY_STATE_FINISHED (3)
Daniel Kingb8025c52016-05-17 14:43:01 -030039
Daniel Kingb8025c52016-05-17 14:43:01 -030040/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020041 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030042 *
43 * \param ctx The ChaCha20-Poly1305 context.
44 */
Gilles Peskine449bd832023-01-11 14:50:10 +010045static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030046{
Gilles Peskine449bd832023-01-11 14:50:10 +010047 uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030048 unsigned char zeroes[15];
49
Gilles Peskine449bd832023-01-11 14:50:10 +010050 if (partial_block_len == 0U) {
51 return 0;
52 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020053
Gilles Peskine449bd832023-01-11 14:50:10 +010054 memset(zeroes, 0, sizeof(zeroes));
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020055
Gilles Peskine449bd832023-01-11 14:50:10 +010056 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
57 zeroes,
58 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030059}
60
61/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020062 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030063 *
64 * \param ctx The ChaCha20-Poly1305 context.
65 */
Gilles Peskine449bd832023-01-11 14:50:10 +010066static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030067{
Gilles Peskine449bd832023-01-11 14:50:10 +010068 uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030069 unsigned char zeroes[15];
70
Gilles Peskine449bd832023-01-11 14:50:10 +010071 if (partial_block_len == 0U) {
72 return 0;
73 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020074
Gilles Peskine449bd832023-01-11 14:50:10 +010075 memset(zeroes, 0, sizeof(zeroes));
76 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
77 zeroes,
78 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030079}
80
Gilles Peskine449bd832023-01-11 14:50:10 +010081void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030082{
Gilles Peskine449bd832023-01-11 14:50:10 +010083 mbedtls_chacha20_init(&ctx->chacha20_ctx);
84 mbedtls_poly1305_init(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050085 ctx->aad_len = 0U;
86 ctx->ciphertext_len = 0U;
87 ctx->state = CHACHAPOLY_STATE_INIT;
88 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -030089}
90
Gilles Peskine449bd832023-01-11 14:50:10 +010091void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030092{
Gilles Peskine449bd832023-01-11 14:50:10 +010093 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050094 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010095 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050096
Gilles Peskine449bd832023-01-11 14:50:10 +010097 mbedtls_chacha20_free(&ctx->chacha20_ctx);
98 mbedtls_poly1305_free(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050099 ctx->aad_len = 0U;
100 ctx->ciphertext_len = 0U;
101 ctx->state = CHACHAPOLY_STATE_INIT;
102 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300103}
104
Gilles Peskine449bd832023-01-11 14:50:10 +0100105int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
106 const unsigned char key[32])
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
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300111
Gilles Peskine449bd832023-01-11 14:50:10 +0100112 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300113}
114
Gilles Peskine449bd832023-01-11 14:50:10 +0100115int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
116 const unsigned char nonce[12],
117 mbedtls_chachapoly_mode_t mode)
Daniel Kingb8025c52016-05-17 14:43:01 -0300118{
Janos Follath24eed8d2019-11-22 13:21:35 +0000119 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300120 unsigned char poly1305_key[64];
Daniel Kingb8025c52016-05-17 14:43:01 -0300121
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200122 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Gilles Peskine449bd832023-01-11 14:50:10 +0100123 ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
124 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300125 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100126 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300127
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200128 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
129 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300130 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
131 * The other 256 bits are discarded.
132 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 memset(poly1305_key, 0, sizeof(poly1305_key));
134 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
135 poly1305_key, poly1305_key);
136 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300137 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100138 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300139
Gilles Peskine449bd832023-01-11 14:50:10 +0100140 ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300141
Gilles Peskine449bd832023-01-11 14:50:10 +0100142 if (ret == 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300143 ctx->aad_len = 0U;
144 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200145 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300146 ctx->mode = mode;
147 }
148
149cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100150 mbedtls_platform_zeroize(poly1305_key, 64U);
151 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300152}
153
Gilles Peskine449bd832023-01-11 14:50:10 +0100154int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
155 const unsigned char *aad,
156 size_t aad_len)
Daniel Kingb8025c52016-05-17 14:43:01 -0300157{
Gilles Peskine449bd832023-01-11 14:50:10 +0100158 if (ctx->state != CHACHAPOLY_STATE_AAD) {
159 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
160 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300161
162 ctx->aad_len += aad_len;
163
Gilles Peskine449bd832023-01-11 14:50:10 +0100164 return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
Daniel Kingb8025c52016-05-17 14:43:01 -0300165}
166
Gilles Peskine449bd832023-01-11 14:50:10 +0100167int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
168 size_t len,
169 const unsigned char *input,
170 unsigned char *output)
Daniel Kingb8025c52016-05-17 14:43:01 -0300171{
Janos Follath24eed8d2019-11-22 13:21:35 +0000172 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200173
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
175 (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
176 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300177 }
178
Gilles Peskine449bd832023-01-11 14:50:10 +0100179 if (ctx->state == CHACHAPOLY_STATE_AAD) {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200180 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300181
Gilles Peskine449bd832023-01-11 14:50:10 +0100182 ret = chachapoly_pad_aad(ctx);
183 if (ret != 0) {
184 return ret;
185 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300186 }
187
188 ctx->ciphertext_len += len;
189
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
191 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
192 if (ret != 0) {
193 return ret;
194 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200195
Gilles Peskine449bd832023-01-11 14:50:10 +0100196 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
197 if (ret != 0) {
198 return ret;
199 }
200 } else { /* DECRYPT */
201 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
202 if (ret != 0) {
203 return ret;
204 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200205
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
207 if (ret != 0) {
208 return ret;
209 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300210 }
211
Gilles Peskine449bd832023-01-11 14:50:10 +0100212 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300213}
214
Gilles Peskine449bd832023-01-11 14:50:10 +0100215int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
216 unsigned char mac[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300217{
Janos Follath24eed8d2019-11-22 13:21:35 +0000218 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300219 unsigned char len_block[16];
220
Gilles Peskine449bd832023-01-11 14:50:10 +0100221 if (ctx->state == CHACHAPOLY_STATE_INIT) {
222 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300223 }
224
Gilles Peskine449bd832023-01-11 14:50:10 +0100225 if (ctx->state == CHACHAPOLY_STATE_AAD) {
226 ret = chachapoly_pad_aad(ctx);
227 if (ret != 0) {
228 return ret;
229 }
230 } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
231 ret = chachapoly_pad_ciphertext(ctx);
232 if (ret != 0) {
233 return ret;
234 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300235 }
236
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200237 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300238
239 /* The lengths of the AAD and ciphertext are processed by
240 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
241 */
Joe Subbianib6511b02021-07-16 15:02:55 +0100242 MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
243 MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
Daniel Kingb8025c52016-05-17 14:43:01 -0300244
Gilles Peskine449bd832023-01-11 14:50:10 +0100245 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
246 if (ret != 0) {
247 return ret;
248 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300249
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200251
Gilles Peskine449bd832023-01-11 14:50:10 +0100252 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300253}
254
Gilles Peskine449bd832023-01-11 14:50:10 +0100255static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
256 mbedtls_chachapoly_mode_t mode,
257 size_t length,
258 const unsigned char nonce[12],
259 const unsigned char *aad,
260 size_t aad_len,
261 const unsigned char *input,
262 unsigned char *output,
263 unsigned char tag[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300264{
Janos Follath24eed8d2019-11-22 13:21:35 +0000265 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300266
Gilles Peskine449bd832023-01-11 14:50:10 +0100267 ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
268 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300269 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300271
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
273 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200274 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300276
Gilles Peskine449bd832023-01-11 14:50:10 +0100277 ret = mbedtls_chachapoly_update(ctx, length, input, output);
278 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200279 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300281
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 ret = mbedtls_chachapoly_finish(ctx, tag);
Daniel Kingb8025c52016-05-17 14:43:01 -0300283
284cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300286}
287
Gilles Peskine449bd832023-01-11 14:50:10 +0100288int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
289 size_t length,
290 const unsigned char nonce[12],
291 const unsigned char *aad,
292 size_t aad_len,
293 const unsigned char *input,
294 unsigned char *output,
295 unsigned char tag[16])
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200296{
Gilles Peskine449bd832023-01-11 14:50:10 +0100297 return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
298 length, nonce, aad, aad_len,
299 input, output, tag);
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200300}
301
Gilles Peskine449bd832023-01-11 14:50:10 +0100302int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
303 size_t length,
304 const unsigned char nonce[12],
305 const unsigned char *aad,
306 size_t aad_len,
307 const unsigned char tag[16],
308 const unsigned char *input,
309 unsigned char *output)
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200310{
Janos Follath24eed8d2019-11-22 13:21:35 +0000311 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200312 unsigned char check_tag[16];
313 size_t i;
314 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" */
Gilles Peskine449bd832023-01-11 14:50:10 +0100323 for (diff = 0, i = 0; i < sizeof(check_tag); i++) {
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200324 diff |= tag[i] ^ check_tag[i];
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200325 }
326
Gilles Peskine449bd832023-01-11 14:50:10 +0100327 if (diff != 0) {
328 mbedtls_platform_zeroize(output, length);
329 return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
330 }
331
332 return 0;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200333}
334
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200335#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200336
Daniel Kingb8025c52016-05-17 14:43:01 -0300337#if defined(MBEDTLS_SELF_TEST)
338
339static const unsigned char test_key[1][32] =
340{
341 {
342 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
343 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
344 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
345 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
346 }
347};
348
349static const unsigned char test_nonce[1][12] =
350{
351 {
352 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
353 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
354 }
355};
356
357static const unsigned char test_aad[1][12] =
358{
359 {
360 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
361 0xc4, 0xc5, 0xc6, 0xc7
362 }
363};
364
365static const size_t test_aad_len[1] =
366{
367 12U
368};
369
370static const unsigned char test_input[1][114] =
371{
372 {
373 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
374 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
375 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
376 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
377 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
378 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
379 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
380 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
381 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
382 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
383 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
384 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
385 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
386 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
387 0x74, 0x2e
388 }
389};
390
391static const unsigned char test_output[1][114] =
392{
393 {
394 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
395 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
396 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
397 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
398 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
399 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
400 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
401 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
402 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
403 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
404 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
405 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
406 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
407 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
408 0x61, 0x16
409 }
410};
411
412static const size_t test_input_len[1] =
413{
414 114U
415};
416
417static const unsigned char test_mac[1][16] =
418{
419 {
420 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
421 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
422 }
423};
424
Ouss4e0b26872020-08-11 16:07:09 +0100425/* Make sure no other definition is already present. */
426#undef ASSERT
427
Gilles Peskine449bd832023-01-11 14:50:10 +0100428#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200429 do \
430 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200432 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 if (verbose != 0) \
434 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200435 \
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200437 } \
438 } \
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200440
Gilles Peskine449bd832023-01-11 14:50:10 +0100441int mbedtls_chachapoly_self_test(int verbose)
Daniel Kingb8025c52016-05-17 14:43:01 -0300442{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200443 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200444 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000445 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300446 unsigned char output[200];
447 unsigned char mac[16];
448
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 for (i = 0U; i < 1U; i++) {
450 if (verbose != 0) {
451 mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
452 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300453
Gilles Peskine449bd832023-01-11 14:50:10 +0100454 mbedtls_chachapoly_init(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200455
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
457 ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200458
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
460 test_input_len[i],
461 test_nonce[i],
462 test_aad[i],
463 test_aad_len[i],
464 test_input[i],
465 output,
466 mac);
Daniel Kingb8025c52016-05-17 14:43:01 -0300467
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
Daniel Kingb8025c52016-05-17 14:43:01 -0300469
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
471 ("failure (wrong output)\n"));
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200472
Gilles Peskine449bd832023-01-11 14:50:10 +0100473 ASSERT(0 == memcmp(mac, test_mac[i], 16U),
474 ("failure (wrong MAC)\n"));
Daniel Kingdedf4a32016-05-18 10:07:53 -0300475
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 mbedtls_chachapoly_free(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200477
Gilles Peskine449bd832023-01-11 14:50:10 +0100478 if (verbose != 0) {
479 mbedtls_printf("passed\n");
480 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300481 }
482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 if (verbose != 0) {
484 mbedtls_printf("\n");
485 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300486
Gilles Peskine449bd832023-01-11 14:50:10 +0100487 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300488}
489
490#endif /* MBEDTLS_SELF_TEST */
491
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200492#endif /* MBEDTLS_CHACHAPOLY_C */