blob: c5b228b532697582b838121fe3b0473a21697a08 [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
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020025# include "mbedtls/chachapoly.h"
26# include "mbedtls/platform_util.h"
27# include "mbedtls/error.h"
Manuel Pégourié-Gonnardfb78c902018-05-24 13:46:15 +020028
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020029# include <string.h>
Daniel Kingb8025c52016-05-17 14:43:01 -030030
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020031# if defined(MBEDTLS_SELF_TEST)
32# if defined(MBEDTLS_PLATFORM_C)
33# include "mbedtls/platform.h"
34# else
35# include <stdio.h>
36# define mbedtls_printf printf
37# endif /* MBEDTLS_PLATFORM_C */
38# endif /* MBEDTLS_SELF_TEST */
Daniel Kingb8025c52016-05-17 14:43:01 -030039
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020040# if !defined(MBEDTLS_CHACHAPOLY_ALT)
Daniel Kingb8025c52016-05-17 14:43:01 -030041
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050042/* Parameter validation macros */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020043# define CHACHAPOLY_VALIDATE_RET(cond) \
44 MBEDTLS_INTERNAL_VALIDATE_RET(cond, \
45 MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA)
46# define CHACHAPOLY_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond)
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050047
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020048# define CHACHAPOLY_STATE_INIT (0)
49# define CHACHAPOLY_STATE_AAD (1)
50# define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
51# define CHACHAPOLY_STATE_FINISHED (3)
Daniel Kingb8025c52016-05-17 14:43:01 -030052
Daniel Kingb8025c52016-05-17 14:43:01 -030053/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020054 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030055 *
56 * \param ctx The ChaCha20-Poly1305 context.
57 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020058static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030059{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020060 uint32_t partial_block_len = (uint32_t)(ctx->aad_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030061 unsigned char zeroes[15];
62
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020063 if (partial_block_len == 0U)
64 return 0;
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020065
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020066 memset(zeroes, 0, sizeof(zeroes));
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020067
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020068 return (mbedtls_poly1305_update(&ctx->poly1305_ctx, zeroes,
69 16U - partial_block_len));
Daniel Kingb8025c52016-05-17 14:43:01 -030070}
71
72/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020073 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030074 *
75 * \param ctx The ChaCha20-Poly1305 context.
76 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020077static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030078{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020079 uint32_t partial_block_len = (uint32_t)(ctx->ciphertext_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030080 unsigned char zeroes[15];
81
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020082 if (partial_block_len == 0U)
83 return 0;
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020084
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020085 memset(zeroes, 0, sizeof(zeroes));
86 return (mbedtls_poly1305_update(&ctx->poly1305_ctx, zeroes,
87 16U - partial_block_len));
Daniel Kingb8025c52016-05-17 14:43:01 -030088}
89
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020090void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030091{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020092 CHACHAPOLY_VALIDATE(ctx != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050093
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020094 mbedtls_chacha20_init(&ctx->chacha20_ctx);
95 mbedtls_poly1305_init(&ctx->poly1305_ctx);
96 ctx->aad_len = 0U;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050097 ctx->ciphertext_len = 0U;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020098 ctx->state = CHACHAPOLY_STATE_INIT;
99 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300100}
101
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200102void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -0300103{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200104 if (ctx == NULL)
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500105 return;
106
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200107 mbedtls_chacha20_free(&ctx->chacha20_ctx);
108 mbedtls_poly1305_free(&ctx->poly1305_ctx);
109 ctx->aad_len = 0U;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500110 ctx->ciphertext_len = 0U;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200111 ctx->state = CHACHAPOLY_STATE_INIT;
112 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300113}
114
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200115int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
116 const unsigned char key[32])
Daniel Kingb8025c52016-05-17 14:43:01 -0300117{
Janos Follath24eed8d2019-11-22 13:21:35 +0000118 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200119 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
120 CHACHAPOLY_VALIDATE_RET(key != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300121
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200122 ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300123
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200124 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300125}
126
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200127int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
128 const unsigned char nonce[12],
129 mbedtls_chachapoly_mode_t mode)
Daniel Kingb8025c52016-05-17 14:43:01 -0300130{
Janos Follath24eed8d2019-11-22 13:21:35 +0000131 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300132 unsigned char poly1305_key[64];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200133 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
134 CHACHAPOLY_VALIDATE_RET(nonce != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300135
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200136 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200137 ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
138 if (ret != 0)
Daniel Kingb8025c52016-05-17 14:43:01 -0300139 goto cleanup;
140
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200141 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
142 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300143 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
144 * The other 256 bits are discarded.
145 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200146 memset(poly1305_key, 0, sizeof(poly1305_key));
147 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
148 poly1305_key, poly1305_key);
149 if (ret != 0)
Daniel Kingb8025c52016-05-17 14:43:01 -0300150 goto cleanup;
151
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200152 ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300153
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200154 if (ret == 0) {
155 ctx->aad_len = 0U;
Daniel Kingb8025c52016-05-17 14:43:01 -0300156 ctx->ciphertext_len = 0U;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200157 ctx->state = CHACHAPOLY_STATE_AAD;
158 ctx->mode = mode;
Daniel Kingb8025c52016-05-17 14:43:01 -0300159 }
160
161cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200162 mbedtls_platform_zeroize(poly1305_key, 64U);
163 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300164}
165
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200166int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
167 const unsigned char *aad,
168 size_t aad_len)
Daniel Kingb8025c52016-05-17 14:43:01 -0300169{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200170 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
171 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500172
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200173 if (ctx->state != CHACHAPOLY_STATE_AAD)
174 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300175
176 ctx->aad_len += aad_len;
177
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200178 return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
Daniel Kingb8025c52016-05-17 14:43:01 -0300179}
180
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200181int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
182 size_t len,
183 const unsigned char *input,
184 unsigned char *output)
Daniel Kingb8025c52016-05-17 14:43:01 -0300185{
Janos Follath24eed8d2019-11-22 13:21:35 +0000186 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200187 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
188 CHACHAPOLY_VALIDATE_RET(len == 0 || input != NULL);
189 CHACHAPOLY_VALIDATE_RET(len == 0 || output != NULL);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200190
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200191 if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
192 (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
193 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300194 }
195
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200196 if (ctx->state == CHACHAPOLY_STATE_AAD) {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200197 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300198
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200199 ret = chachapoly_pad_aad(ctx);
200 if (ret != 0)
201 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300202 }
203
204 ctx->ciphertext_len += len;
205
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200206 if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
207 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
208 if (ret != 0)
209 return ret;
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200210
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200211 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
212 if (ret != 0)
213 return ret;
214 } else /* DECRYPT */
Daniel Kingb8025c52016-05-17 14:43:01 -0300215 {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200216 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
217 if (ret != 0)
218 return ret;
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200219
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200220 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
221 if (ret != 0)
222 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300223 }
224
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200225 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300226}
227
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200228int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
229 unsigned char mac[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300230{
Janos Follath24eed8d2019-11-22 13:21:35 +0000231 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300232 unsigned char len_block[16];
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200233 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
234 CHACHAPOLY_VALIDATE_RET(mac != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300235
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200236 if (ctx->state == CHACHAPOLY_STATE_INIT) {
237 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300238 }
239
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200240 if (ctx->state == CHACHAPOLY_STATE_AAD) {
241 ret = chachapoly_pad_aad(ctx);
242 if (ret != 0)
243 return ret;
244 } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
245 ret = chachapoly_pad_ciphertext(ctx);
246 if (ret != 0)
247 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300248 }
249
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200250 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300251
252 /* The lengths of the AAD and ciphertext are processed by
253 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
254 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200255 len_block[0] = (unsigned char)(ctx->aad_len);
256 len_block[1] = (unsigned char)(ctx->aad_len >> 8);
257 len_block[2] = (unsigned char)(ctx->aad_len >> 16);
258 len_block[3] = (unsigned char)(ctx->aad_len >> 24);
259 len_block[4] = (unsigned char)(ctx->aad_len >> 32);
260 len_block[5] = (unsigned char)(ctx->aad_len >> 40);
261 len_block[6] = (unsigned char)(ctx->aad_len >> 48);
262 len_block[7] = (unsigned char)(ctx->aad_len >> 56);
263 len_block[8] = (unsigned char)(ctx->ciphertext_len);
264 len_block[9] = (unsigned char)(ctx->ciphertext_len >> 8);
265 len_block[10] = (unsigned char)(ctx->ciphertext_len >> 16);
266 len_block[11] = (unsigned char)(ctx->ciphertext_len >> 24);
267 len_block[12] = (unsigned char)(ctx->ciphertext_len >> 32);
268 len_block[13] = (unsigned char)(ctx->ciphertext_len >> 40);
269 len_block[14] = (unsigned char)(ctx->ciphertext_len >> 48);
270 len_block[15] = (unsigned char)(ctx->ciphertext_len >> 56);
Daniel Kingb8025c52016-05-17 14:43:01 -0300271
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200272 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
273 if (ret != 0)
274 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300275
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200276 ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200277
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200278 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300279}
280
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200281static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
282 mbedtls_chachapoly_mode_t mode,
283 size_t length,
284 const unsigned char nonce[12],
285 const unsigned char *aad,
286 size_t aad_len,
287 const unsigned char *input,
288 unsigned char *output,
289 unsigned char tag[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300290{
Janos Follath24eed8d2019-11-22 13:21:35 +0000291 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300292
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200293 ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
294 if (ret != 0)
Daniel Kingb8025c52016-05-17 14:43:01 -0300295 goto cleanup;
296
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200297 ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
298 if (ret != 0)
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200299 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300300
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200301 ret = mbedtls_chachapoly_update(ctx, length, input, output);
302 if (ret != 0)
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200303 goto cleanup;
Daniel Kingb8025c52016-05-17 14:43:01 -0300304
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200305 ret = mbedtls_chachapoly_finish(ctx, tag);
Daniel Kingb8025c52016-05-17 14:43:01 -0300306
307cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200308 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300309}
310
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200311int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
312 size_t length,
313 const unsigned char nonce[12],
314 const unsigned char *aad,
315 size_t aad_len,
316 const unsigned char *input,
317 unsigned char *output,
318 unsigned char tag[16])
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200319{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200320 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
321 CHACHAPOLY_VALIDATE_RET(nonce != NULL);
322 CHACHAPOLY_VALIDATE_RET(tag != NULL);
323 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
324 CHACHAPOLY_VALIDATE_RET(length == 0 || input != NULL);
325 CHACHAPOLY_VALIDATE_RET(length == 0 || output != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500326
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200327 return (chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, length,
328 nonce, aad, aad_len, input, output, tag));
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200329}
330
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200331int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
332 size_t length,
333 const unsigned char nonce[12],
334 const unsigned char *aad,
335 size_t aad_len,
336 const unsigned char tag[16],
337 const unsigned char *input,
338 unsigned char *output)
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200339{
Janos Follath24eed8d2019-11-22 13:21:35 +0000340 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200341 unsigned char check_tag[16];
342 size_t i;
343 int diff;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200344 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
345 CHACHAPOLY_VALIDATE_RET(nonce != NULL);
346 CHACHAPOLY_VALIDATE_RET(tag != NULL);
347 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
348 CHACHAPOLY_VALIDATE_RET(length == 0 || input != NULL);
349 CHACHAPOLY_VALIDATE_RET(length == 0 || output != NULL);
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200350
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200351 if ((ret = chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_DECRYPT, length,
352 nonce, aad, aad_len, input, output,
353 check_tag)) != 0) {
354 return ret;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200355 }
356
357 /* Check tag in "constant-time" */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200358 for (diff = 0, i = 0; i < sizeof(check_tag); i++)
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200359 diff |= tag[i] ^ check_tag[i];
360
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200361 if (diff != 0) {
362 mbedtls_platform_zeroize(output, length);
363 return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200364 }
365
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200366 return 0;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200367}
368
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200369# endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200370
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200371# if defined(MBEDTLS_SELF_TEST)
Daniel Kingb8025c52016-05-17 14:43:01 -0300372
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200373static const unsigned char test_key[1][32] = {
374 { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
375 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95,
376 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }
Daniel Kingb8025c52016-05-17 14:43:01 -0300377};
378
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200379static const unsigned char test_nonce[1][12] = { {
380 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
381 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
382} };
383
384static const unsigned char test_aad[1][12] = {
385 { 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300386};
387
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200388static const size_t test_aad_len[1] = { 12U };
389
390static const unsigned char test_input[1][114] = {
391 { 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47,
392 0x65, 0x6e, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
393 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66,
394 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
395 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79,
396 0x6f, 0x75, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
397 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
398 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
399 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
400 0x62, 0x65, 0x20, 0x69, 0x74, 0x2e }
Daniel Kingb8025c52016-05-17 14:43:01 -0300401};
402
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200403static const unsigned char test_output[1][114] = {
404 { 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc,
405 0x53, 0xef, 0x7e, 0xc2, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
406 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 0x3d, 0xbe, 0xa4, 0x5e,
407 0x8c, 0xa9, 0x67, 0x12, 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
408 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 0x05, 0xd6, 0xa5, 0xb6,
409 0x7e, 0xcd, 0x3b, 0x36, 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
410 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 0xfa, 0xb3, 0x24, 0xe4,
411 0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
412 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65,
413 0x86, 0xce, 0xc6, 0x4b, 0x61, 0x16 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300414};
415
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200416static const size_t test_input_len[1] = { 114U };
Daniel Kingb8025c52016-05-17 14:43:01 -0300417
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200418static const unsigned char test_mac[1][16] = {
419 { 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb,
420 0xd0, 0x60, 0x06, 0x91 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300421};
422
Ouss4e0b26872020-08-11 16:07:09 +0100423/* Make sure no other definition is already present. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200424# undef ASSERT
Ouss4e0b26872020-08-11 16:07:09 +0100425
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200426# define ASSERT(cond, args) \
427 do { \
428 if (!(cond)) { \
429 if (verbose != 0) \
430 mbedtls_printf args; \
431 \
432 return -1; \
433 } \
434 } while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200435
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200436int mbedtls_chachapoly_self_test(int verbose)
Daniel Kingb8025c52016-05-17 14:43:01 -0300437{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200438 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200439 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000440 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300441 unsigned char output[200];
442 unsigned char mac[16];
443
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200444 for (i = 0U; i < 1U; i++) {
445 if (verbose != 0)
446 mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
Daniel Kingdedf4a32016-05-18 10:07:53 -0300447
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200448 mbedtls_chachapoly_init(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200449
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200450 ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
451 ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200452
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200453 ret = mbedtls_chachapoly_encrypt_and_tag(&ctx, test_input_len[i],
454 test_nonce[i], test_aad[i],
455 test_aad_len[i], test_input[i],
456 output, mac);
Daniel Kingb8025c52016-05-17 14:43:01 -0300457
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200458 ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
Daniel Kingb8025c52016-05-17 14:43:01 -0300459
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200460 ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
461 ("failure (wrong output)\n"));
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200462
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200463 ASSERT(0 == memcmp(mac, test_mac[i], 16U), ("failure (wrong MAC)\n"));
Daniel Kingdedf4a32016-05-18 10:07:53 -0300464
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200465 mbedtls_chachapoly_free(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200466
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200467 if (verbose != 0)
468 mbedtls_printf("passed\n");
Daniel Kingdedf4a32016-05-18 10:07:53 -0300469 }
470
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200471 if (verbose != 0)
472 mbedtls_printf("\n");
Daniel Kingb8025c52016-05-17 14:43:01 -0300473
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200474 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300475}
476
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200477# endif /* MBEDTLS_SELF_TEST */
Daniel Kingb8025c52016-05-17 14:43:01 -0300478
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200479#endif /* MBEDTLS_CHACHAPOLY_C */