blob: ceb429287b72257f00a3e5ac45ad966ad337ee8d [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
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050035/* Parameter validation macros */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010036#define CHACHAPOLY_VALIDATE_RET(cond) \
37 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA)
38#define CHACHAPOLY_VALIDATE(cond) \
39 MBEDTLS_INTERNAL_VALIDATE(cond)
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050040
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010041#define CHACHAPOLY_STATE_INIT (0)
42#define CHACHAPOLY_STATE_AAD (1)
43#define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
44#define CHACHAPOLY_STATE_FINISHED (3)
Daniel Kingb8025c52016-05-17 14:43:01 -030045
Daniel Kingb8025c52016-05-17 14:43:01 -030046/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020047 * \brief Adds nul bytes to pad the AAD for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030048 *
49 * \param ctx The ChaCha20-Poly1305 context.
50 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010051static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030052{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010053 uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030054 unsigned char zeroes[15];
55
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010056 if (partial_block_len == 0U) {
57 return 0;
58 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020059
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010060 memset(zeroes, 0, sizeof(zeroes));
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020061
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010062 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
63 zeroes,
64 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030065}
66
67/**
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +020068 * \brief Adds nul bytes to pad the ciphertext for Poly1305.
Daniel Kingb8025c52016-05-17 14:43:01 -030069 *
70 * \param ctx The ChaCha20-Poly1305 context.
71 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010072static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030073{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010074 uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030075 unsigned char zeroes[15];
76
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010077 if (partial_block_len == 0U) {
78 return 0;
79 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020080
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010081 memset(zeroes, 0, sizeof(zeroes));
82 return mbedtls_poly1305_update(&ctx->poly1305_ctx,
83 zeroes,
84 16U - partial_block_len);
Daniel Kingb8025c52016-05-17 14:43:01 -030085}
86
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010087void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030088{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010089 CHACHAPOLY_VALIDATE(ctx != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050090
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010091 mbedtls_chacha20_init(&ctx->chacha20_ctx);
92 mbedtls_poly1305_init(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050093 ctx->aad_len = 0U;
94 ctx->ciphertext_len = 0U;
95 ctx->state = CHACHAPOLY_STATE_INIT;
96 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -030097}
98
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010099void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -0300100{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100101 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500102 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100103 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500104
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100105 mbedtls_chacha20_free(&ctx->chacha20_ctx);
106 mbedtls_poly1305_free(&ctx->poly1305_ctx);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500107 ctx->aad_len = 0U;
108 ctx->ciphertext_len = 0U;
109 ctx->state = CHACHAPOLY_STATE_INIT;
110 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300111}
112
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100113int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
114 const unsigned char key[32])
Daniel Kingb8025c52016-05-17 14:43:01 -0300115{
Janos Follath24eed8d2019-11-22 13:21:35 +0000116 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100117 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
118 CHACHAPOLY_VALIDATE_RET(key != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300119
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100120 ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300121
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100122 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300123}
124
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100125int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
126 const unsigned char nonce[12],
127 mbedtls_chachapoly_mode_t mode)
Daniel Kingb8025c52016-05-17 14:43:01 -0300128{
Janos Follath24eed8d2019-11-22 13:21:35 +0000129 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300130 unsigned char poly1305_key[64];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100131 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
132 CHACHAPOLY_VALIDATE_RET(nonce != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300133
Manuel Pégourié-Gonnard56206c42018-05-07 12:18:34 +0200134 /* Set counter = 0, will be update to 1 when generating Poly1305 key */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100135 ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
136 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300137 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100138 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300139
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200140 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
141 * counter = 0. This is the same as encrypting a buffer of zeroes.
Daniel Kingb8025c52016-05-17 14:43:01 -0300142 * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
143 * The other 256 bits are discarded.
144 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100145 memset(poly1305_key, 0, sizeof(poly1305_key));
146 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
147 poly1305_key, poly1305_key);
148 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300149 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100150 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300151
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100152 ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300153
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100154 if (ret == 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300155 ctx->aad_len = 0U;
156 ctx->ciphertext_len = 0U;
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200157 ctx->state = CHACHAPOLY_STATE_AAD;
Daniel Kingb8025c52016-05-17 14:43:01 -0300158 ctx->mode = mode;
159 }
160
161cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100162 mbedtls_platform_zeroize(poly1305_key, 64U);
163 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300164}
165
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100166int 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{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100170 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
171 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500172
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100173 if (ctx->state != CHACHAPOLY_STATE_AAD) {
174 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
175 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300176
177 ctx->aad_len += aad_len;
178
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100179 return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
Daniel Kingb8025c52016-05-17 14:43:01 -0300180}
181
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100182int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
183 size_t len,
184 const unsigned char *input,
185 unsigned char *output)
Daniel Kingb8025c52016-05-17 14:43:01 -0300186{
Janos Follath24eed8d2019-11-22 13:21:35 +0000187 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100188 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
189 CHACHAPOLY_VALIDATE_RET(len == 0 || input != NULL);
190 CHACHAPOLY_VALIDATE_RET(len == 0 || output != NULL);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200191
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100192 if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
193 (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
194 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300195 }
196
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100197 if (ctx->state == CHACHAPOLY_STATE_AAD) {
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200198 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
Daniel Kingb8025c52016-05-17 14:43:01 -0300199
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100200 ret = chachapoly_pad_aad(ctx);
201 if (ret != 0) {
202 return ret;
203 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300204 }
205
206 ctx->ciphertext_len += len;
207
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100208 if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
209 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
210 if (ret != 0) {
211 return ret;
212 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200213
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100214 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
215 if (ret != 0) {
216 return ret;
217 }
218 } else { /* DECRYPT */
219 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
220 if (ret != 0) {
221 return ret;
222 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200223
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100224 ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
225 if (ret != 0) {
226 return ret;
227 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300228 }
229
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100230 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300231}
232
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100233int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
234 unsigned char mac[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300235{
Janos Follath24eed8d2019-11-22 13:21:35 +0000236 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300237 unsigned char len_block[16];
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100238 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
239 CHACHAPOLY_VALIDATE_RET(mac != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300240
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100241 if (ctx->state == CHACHAPOLY_STATE_INIT) {
242 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300243 }
244
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100245 if (ctx->state == CHACHAPOLY_STATE_AAD) {
246 ret = chachapoly_pad_aad(ctx);
247 if (ret != 0) {
248 return ret;
249 }
250 } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
251 ret = chachapoly_pad_ciphertext(ctx);
252 if (ret != 0) {
253 return ret;
254 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300255 }
256
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200257 ctx->state = CHACHAPOLY_STATE_FINISHED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300258
259 /* The lengths of the AAD and ciphertext are processed by
260 * Poly1305 as the final 128-bit block, encoded as little-endian integers.
261 */
Joe Subbiani6627fb22021-07-16 15:02:55 +0100262 MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
263 MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
Daniel Kingb8025c52016-05-17 14:43:01 -0300264
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100265 ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
266 if (ret != 0) {
267 return ret;
268 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300269
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100270 ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200271
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100272 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300273}
274
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100275static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
276 mbedtls_chachapoly_mode_t mode,
277 size_t length,
278 const unsigned char nonce[12],
279 const unsigned char *aad,
280 size_t aad_len,
281 const unsigned char *input,
282 unsigned char *output,
283 unsigned char tag[16])
Daniel Kingb8025c52016-05-17 14:43:01 -0300284{
Janos Follath24eed8d2019-11-22 13:21:35 +0000285 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300286
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100287 ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
288 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300289 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100290 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300291
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100292 ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
293 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200294 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100295 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300296
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100297 ret = mbedtls_chachapoly_update(ctx, length, input, output);
298 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200299 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100300 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300301
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100302 ret = mbedtls_chachapoly_finish(ctx, tag);
Daniel Kingb8025c52016-05-17 14:43:01 -0300303
304cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100305 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300306}
307
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100308int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
309 size_t length,
310 const unsigned char nonce[12],
311 const unsigned char *aad,
312 size_t aad_len,
313 const unsigned char *input,
314 unsigned char *output,
315 unsigned char tag[16])
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200316{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100317 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
318 CHACHAPOLY_VALIDATE_RET(nonce != NULL);
319 CHACHAPOLY_VALIDATE_RET(tag != NULL);
320 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
321 CHACHAPOLY_VALIDATE_RET(length == 0 || input != NULL);
322 CHACHAPOLY_VALIDATE_RET(length == 0 || output != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500323
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100324 return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
325 length, nonce, aad, aad_len,
326 input, output, tag);
Manuel Pégourié-Gonnard3dc62a02018-06-04 12:18:19 +0200327}
328
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100329int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
330 size_t length,
331 const unsigned char nonce[12],
332 const unsigned char *aad,
333 size_t aad_len,
334 const unsigned char tag[16],
335 const unsigned char *input,
336 unsigned char *output)
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200337{
Janos Follath24eed8d2019-11-22 13:21:35 +0000338 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200339 unsigned char check_tag[16];
340 size_t i;
341 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" */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100356 for (diff = 0, i = 0; i < sizeof(check_tag); i++) {
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200357 diff |= tag[i] ^ check_tag[i];
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200358 }
359
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100360 if (diff != 0) {
361 mbedtls_platform_zeroize(output, length);
362 return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
363 }
364
365 return 0;
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200366}
367
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200368#endif /* MBEDTLS_CHACHAPOLY_ALT */
Manuel Pégourié-Gonnard95d0bdb2018-05-07 09:58:35 +0200369
Daniel Kingb8025c52016-05-17 14:43:01 -0300370#if defined(MBEDTLS_SELF_TEST)
371
372static const unsigned char test_key[1][32] =
373{
374 {
375 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
376 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
377 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
378 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
379 }
380};
381
382static const unsigned char test_nonce[1][12] =
383{
384 {
385 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
386 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
387 }
388};
389
390static const unsigned char test_aad[1][12] =
391{
392 {
393 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
394 0xc4, 0xc5, 0xc6, 0xc7
395 }
396};
397
398static const size_t test_aad_len[1] =
399{
400 12U
401};
402
403static const unsigned char test_input[1][114] =
404{
405 {
406 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
407 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
408 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
409 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
410 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
411 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
412 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
413 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
414 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
415 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
416 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
417 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
418 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
419 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
420 0x74, 0x2e
421 }
422};
423
424static const unsigned char test_output[1][114] =
425{
426 {
427 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
428 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
429 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
430 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
431 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
432 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
433 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
434 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
435 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
436 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
437 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
438 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
439 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
440 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
441 0x61, 0x16
442 }
443};
444
445static const size_t test_input_len[1] =
446{
447 114U
448};
449
450static const unsigned char test_mac[1][16] =
451{
452 {
453 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
454 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
455 }
456};
457
Ouss4e0b26872020-08-11 16:07:09 +0100458/* Make sure no other definition is already present. */
459#undef ASSERT
460
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100461#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200462 do \
463 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100464 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200465 { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100466 if (verbose != 0) \
467 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200468 \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100469 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200470 } \
471 } \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100472 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200473
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100474int mbedtls_chachapoly_self_test(int verbose)
Daniel Kingb8025c52016-05-17 14:43:01 -0300475{
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200476 mbedtls_chachapoly_context ctx;
Manuel Pégourié-Gonnardb7e99002018-05-07 10:14:18 +0200477 unsigned i;
Janos Follath24eed8d2019-11-22 13:21:35 +0000478 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Kingb8025c52016-05-17 14:43:01 -0300479 unsigned char output[200];
480 unsigned char mac[16];
481
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100482 for (i = 0U; i < 1U; i++) {
483 if (verbose != 0) {
484 mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
485 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300486
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100487 mbedtls_chachapoly_init(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200488
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100489 ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
490 ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200491
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100492 ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
493 test_input_len[i],
494 test_nonce[i],
495 test_aad[i],
496 test_aad_len[i],
497 test_input[i],
498 output,
499 mac);
Daniel Kingb8025c52016-05-17 14:43:01 -0300500
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100501 ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
Daniel Kingb8025c52016-05-17 14:43:01 -0300502
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100503 ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
504 ("failure (wrong output)\n"));
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200505
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100506 ASSERT(0 == memcmp(mac, test_mac[i], 16U),
507 ("failure (wrong MAC)\n"));
Daniel Kingdedf4a32016-05-18 10:07:53 -0300508
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100509 mbedtls_chachapoly_free(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200510
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100511 if (verbose != 0) {
512 mbedtls_printf("passed\n");
513 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300514 }
515
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100516 if (verbose != 0) {
517 mbedtls_printf("\n");
518 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300519
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100520 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300521}
522
523#endif /* MBEDTLS_SELF_TEST */
524
Manuel Pégourié-Gonnarddca3a5d2018-05-07 10:43:27 +0200525#endif /* MBEDTLS_CHACHAPOLY_C */