blob: 547ffb2ed241e9f8d92772b65efa499bd6dbc1d1 [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 Rodgmanc2805202023-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
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050036/* Parameter validation macros */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010037#define CHACHAPOLY_VALIDATE_RET(cond) \
38 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA)
39#define CHACHAPOLY_VALIDATE(cond) \
40 MBEDTLS_INTERNAL_VALIDATE(cond)
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050041
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010042#define CHACHAPOLY_STATE_INIT (0)
43#define CHACHAPOLY_STATE_AAD (1)
44#define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
45#define CHACHAPOLY_STATE_FINISHED (3)
Daniel Kingb8025c52016-05-17 14:43:01 -030046
Daniel Kingb8025c52016-05-17 14:43:01 -030047/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020048 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030049 *
50 * \param ctx The ChaCha20-Poly1305 context.
51 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010052static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030053{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010054 uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030055 unsigned char zeroes[15];
56
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010057 if (partial_block_len == 0U) {
58 return 0;
59 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020060
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010061 memset(zeroes, 0, sizeof(zeroes));
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020062
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010063 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
64 zeroes,
65 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030066}
67
68/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020069 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030070 *
71 * \param ctx The ChaCha20-Poly1305 context.
72 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010073static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030074{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010075 uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030076 unsigned char zeroes[15];
77
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010078 if (partial_block_len == 0U) {
79 return 0;
80 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020081
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010082 memset(zeroes, 0, sizeof(zeroes));
83 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
84 zeroes,
85 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030086}
87
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010088void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030089{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010090 CHACHAPOLY_VALIDATE(ctx != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050091
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010092 mbedtls_chacha20_init(&ctx->chacha20_ctx);
93 mbedtls_poly1305_init(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050094 ctx->aad_len = 0U;
95 ctx->ciphertext_len = 0U;
96 ctx->state = CHACHAPOLY_STATE_INIT;
97 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -030098}
99
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100100void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -0300101{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100102 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500103 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100104 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500105
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100106 mbedtls_chacha20_free(&ctx->chacha20_ctx);
107 mbedtls_poly1305_free(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500108 ctx->aad_len = 0U;
109 ctx->ciphertext_len = 0U;
110 ctx->state = CHACHAPOLY_STATE_INIT;
111 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300112}
113
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100114int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
115 const unsigned char key[32])
Daniel Kingb8025c52016-05-17 14:43:01 -0300116{
Janos Follath24eed8d2019-11-22 13:21:35 +0000117 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100118 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
119 CHACHAPOLY_VALIDATE_RET(key != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300120
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100121 ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300122
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100123 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300124}
125
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100126int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
127 const unsigned char nonce[12],
128 mbedtls_chachapoly_mode_t mode)
Daniel Kingb8025c52016-05-17 14:43:01 -0300129{
Janos Follath24eed8d2019-11-22 13:21:35 +0000130 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300131 unsigned char poly1305_key[64];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100132 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
133 CHACHAPOLY_VALIDATE_RET(nonce != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300134
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200135 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100136 ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
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
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 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100146 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;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300152
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100153 ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300154
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100155 if (ret == 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300156 ctx->aad_len = 0U;
157 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200158 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300159 ctx->mode = mode;
160 }
161
162cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100163 mbedtls_platform_zeroize(poly1305_key, 64U);
164 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300165}
166
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100167int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
168 const unsigned char *aad,
169 size_t aad_len)
Daniel Kingb8025c52016-05-17 14:43:01 -0300170{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100171 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
172 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500173
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100174 if (ctx->state != CHACHAPOLY_STATE_AAD) {
175 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
176 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300177
178 ctx->aad_len += aad_len;
179
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100180 return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
Daniel Kingb8025c52016-05-17 14:43:01 -0300181}
182
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100183int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
184 size_t len,
185 const unsigned char *input,
186 unsigned char *output)
Daniel Kingb8025c52016-05-17 14:43:01 -0300187{
Janos Follath24eed8d2019-11-22 13:21:35 +0000188 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100189 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
190 CHACHAPOLY_VALIDATE_RET(len == 0 || input != NULL);
191 CHACHAPOLY_VALIDATE_RET(len == 0 || output != NULL);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200192
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100193 if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
194 (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
195 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300196 }
197
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100198 if (ctx->state == CHACHAPOLY_STATE_AAD) {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200199 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300200
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100201 ret = chachapoly_pad_aad(ctx);
202 if (ret != 0) {
203 return ret;
204 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300205 }
206
207 ctx->ciphertext_len += len;
208
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100209 if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
210 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
211 if (ret != 0) {
212 return ret;
213 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200214
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100215 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
216 if (ret != 0) {
217 return ret;
218 }
219 } else { /* DECRYPT */
220 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
221 if (ret != 0) {
222 return ret;
223 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200224
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100225 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
226 if (ret != 0) {
227 return ret;
228 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300229 }
230
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100231 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300232}
233
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100234int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
235 unsigned char mac[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300236{
Janos Follath24eed8d2019-11-22 13:21:35 +0000237 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300238 unsigned char len_block[16];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100239 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
240 CHACHAPOLY_VALIDATE_RET(mac != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300241
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100242 if (ctx->state == CHACHAPOLY_STATE_INIT) {
243 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300244 }
245
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100246 if (ctx->state == CHACHAPOLY_STATE_AAD) {
247 ret = chachapoly_pad_aad(ctx);
248 if (ret != 0) {
249 return ret;
250 }
251 } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
252 ret = chachapoly_pad_ciphertext(ctx);
253 if (ret != 0) {
254 return ret;
255 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300256 }
257
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200258 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300259
260 /* The lengths of the AAD and ciphertext are processed by
261 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
262 */
Joe Subbiani6627fb22021-07-16 15:02:55 +0100263 MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
264 MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
Daniel Kingb8025c52016-05-17 14:43:01 -0300265
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100266 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
267 if (ret != 0) {
268 return ret;
269 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300270
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100271 ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200272
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100273 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300274}
275
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100276static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
277 mbedtls_chachapoly_mode_t mode,
278 size_t length,
279 const unsigned char nonce[12],
280 const unsigned char *aad,
281 size_t aad_len,
282 const unsigned char *input,
283 unsigned char *output,
284 unsigned char tag[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300285{
Janos Follath24eed8d2019-11-22 13:21:35 +0000286 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300287
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100288 ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
289 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300290 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100291 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300292
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100293 ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
294 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200295 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100296 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300297
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100298 ret = mbedtls_chachapoly_update(ctx, length, input, output);
299 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200300 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100301 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300302
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100303 ret = mbedtls_chachapoly_finish(ctx, tag);
Daniel Kingb8025c52016-05-17 14:43:01 -0300304
305cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100306 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300307}
308
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100309int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
310 size_t length,
311 const unsigned char nonce[12],
312 const unsigned char *aad,
313 size_t aad_len,
314 const unsigned char *input,
315 unsigned char *output,
316 unsigned char tag[16])
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200317{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100318 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
319 CHACHAPOLY_VALIDATE_RET(nonce != NULL);
320 CHACHAPOLY_VALIDATE_RET(tag != NULL);
321 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
322 CHACHAPOLY_VALIDATE_RET(length == 0 || input != NULL);
323 CHACHAPOLY_VALIDATE_RET(length == 0 || output != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500324
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100325 return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
326 length, nonce, aad, aad_len,
327 input, output, tag);
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200328}
329
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100330int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
331 size_t length,
332 const unsigned char nonce[12],
333 const unsigned char *aad,
334 size_t aad_len,
335 const unsigned char tag[16],
336 const unsigned char *input,
337 unsigned char *output)
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200338{
Janos Follath24eed8d2019-11-22 13:21:35 +0000339 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200340 unsigned char check_tag[16];
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200341 int diff;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100342 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
343 CHACHAPOLY_VALIDATE_RET(nonce != NULL);
344 CHACHAPOLY_VALIDATE_RET(tag != NULL);
345 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
346 CHACHAPOLY_VALIDATE_RET(length == 0 || input != NULL);
347 CHACHAPOLY_VALIDATE_RET(length == 0 || output != NULL);
Manuel Pégourié-Gonnard59d2c302018-05-10 10:39:32 +0200348
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100349 if ((ret = chachapoly_crypt_and_tag(ctx,
350 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
351 aad, aad_len, input, output, check_tag)) != 0) {
352 return ret;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200353 }
354
355 /* Check tag in "constant-time" */
Dave Rodgmanc2805202023-09-11 18:25:16 +0100356 diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200357
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100358 if (diff != 0) {
359 mbedtls_platform_zeroize(output, length);
360 return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
361 }
362
363 return 0;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200364}
365
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200366#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200367
Daniel Kingb8025c52016-05-17 14:43:01 -0300368#if defined(MBEDTLS_SELF_TEST)
369
370static const unsigned char test_key[1][32] =
371{
372 {
373 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
374 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
375 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
376 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
377 }
378};
379
380static const unsigned char test_nonce[1][12] =
381{
382 {
383 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
384 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
385 }
386};
387
388static const unsigned char test_aad[1][12] =
389{
390 {
391 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
392 0xc4, 0xc5, 0xc6, 0xc7
393 }
394};
395
396static const size_t test_aad_len[1] =
397{
398 12U
399};
400
401static const unsigned char test_input[1][114] =
402{
403 {
404 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
405 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
406 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
407 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
408 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
409 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
410 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
411 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
412 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
413 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
414 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
415 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
416 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
417 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
418 0x74, 0x2e
419 }
420};
421
422static const unsigned char test_output[1][114] =
423{
424 {
425 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
426 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
427 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
428 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
429 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
430 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
431 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
432 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
433 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
434 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
435 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
436 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
437 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
438 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
439 0x61, 0x16
440 }
441};
442
443static const size_t test_input_len[1] =
444{
445 114U
446};
447
448static const unsigned char test_mac[1][16] =
449{
450 {
451 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
452 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
453 }
454};
455
Ouss4e0b26872020-08-11 16:07:09 +0100456/* Make sure no other definition is already present. */
457#undef ASSERT
458
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100459#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200460 do \
461 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100462 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200463 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100464 if (verbose != 0) \
465 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200466 \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100467 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200468 } \
469 } \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100470 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200471
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100472int mbedtls_chachapoly_self_test(int verbose)
Daniel Kingb8025c52016-05-17 14:43:01 -0300473{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200474 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200475 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000476 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300477 unsigned char output[200];
478 unsigned char mac[16];
479
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100480 for (i = 0U; i < 1U; i++) {
481 if (verbose != 0) {
482 mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
483 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300484
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100485 mbedtls_chachapoly_init(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200486
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100487 ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
488 ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200489
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100490 ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
491 test_input_len[i],
492 test_nonce[i],
493 test_aad[i],
494 test_aad_len[i],
495 test_input[i],
496 output,
497 mac);
Daniel Kingb8025c52016-05-17 14:43:01 -0300498
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100499 ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
Daniel Kingb8025c52016-05-17 14:43:01 -0300500
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100501 ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
502 ("failure (wrong output)\n"));
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200503
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100504 ASSERT(0 == memcmp(mac, test_mac[i], 16U),
505 ("failure (wrong MAC)\n"));
Daniel Kingdedf4a32016-05-18 10:07:53 -0300506
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100507 mbedtls_chachapoly_free(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200508
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100509 if (verbose != 0) {
510 mbedtls_printf("passed\n");
511 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300512 }
513
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100514 if (verbose != 0) {
515 mbedtls_printf("\n");
516 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300517
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100518 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300519}
520
521#endif /* MBEDTLS_SELF_TEST */
522
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200523#endif /* MBEDTLS_CHACHAPOLY_C */