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 */
David Horstmannceeaeb92023-01-05 15:44:23 +000036#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
David Horstmannceeaeb92023-01-05 15:44:23 +000041#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 */
David Horstmannceeaeb92023-01-05 15:44:23 +000051static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030052{
David Horstmannceeaeb92023-01-05 15:44:23 +000053 uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030054 unsigned char zeroes[15];
55
David Horstmannceeaeb92023-01-05 15:44:23 +000056 if (partial_block_len == 0U) {
57 return 0;
58 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020059
David Horstmannceeaeb92023-01-05 15:44:23 +000060 memset(zeroes, 0, sizeof(zeroes));
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020061
David Horstmannceeaeb92023-01-05 15:44:23 +000062 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 */
David Horstmannceeaeb92023-01-05 15:44:23 +000072static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030073{
David Horstmannceeaeb92023-01-05 15:44:23 +000074 uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
Daniel Kingb8025c52016-05-17 14:43:01 -030075 unsigned char zeroes[15];
76
David Horstmannceeaeb92023-01-05 15:44:23 +000077 if (partial_block_len == 0U) {
78 return 0;
79 }
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +020080
David Horstmannceeaeb92023-01-05 15:44:23 +000081 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
David Horstmannceeaeb92023-01-05 15:44:23 +000087void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -030088{
David Horstmannceeaeb92023-01-05 15:44:23 +000089 CHACHAPOLY_VALIDATE(ctx != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050090
David Horstmannceeaeb92023-01-05 15:44:23 +000091 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
David Horstmannceeaeb92023-01-05 15:44:23 +000099void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
Daniel Kingb8025c52016-05-17 14:43:01 -0300100{
David Horstmannceeaeb92023-01-05 15:44:23 +0000101 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500102 return;
David Horstmannceeaeb92023-01-05 15:44:23 +0000103 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500104
David Horstmannceeaeb92023-01-05 15:44:23 +0000105 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000113int 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;
David Horstmannceeaeb92023-01-05 15:44:23 +0000117 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
118 CHACHAPOLY_VALIDATE_RET(key != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300119
David Horstmannceeaeb92023-01-05 15:44:23 +0000120 ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300121
David Horstmannceeaeb92023-01-05 15:44:23 +0000122 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300123}
124
David Horstmannceeaeb92023-01-05 15:44:23 +0000125int 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];
David Horstmannceeaeb92023-01-05 15:44:23 +0000131 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 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000135 ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
136 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300137 goto cleanup;
David Horstmannceeaeb92023-01-05 15:44:23 +0000138 }
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 */
David Horstmannceeaeb92023-01-05 15:44:23 +0000145 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;
David Horstmannceeaeb92023-01-05 15:44:23 +0000150 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300151
David Horstmannceeaeb92023-01-05 15:44:23 +0000152 ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
Daniel Kingb8025c52016-05-17 14:43:01 -0300153
David Horstmannceeaeb92023-01-05 15:44:23 +0000154 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:
David Horstmannceeaeb92023-01-05 15:44:23 +0000162 mbedtls_platform_zeroize(poly1305_key, 64U);
163 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300164}
165
David Horstmannceeaeb92023-01-05 15:44:23 +0000166int 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{
David Horstmannceeaeb92023-01-05 15:44:23 +0000170 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
171 CHACHAPOLY_VALIDATE_RET(aad_len == 0 || aad != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500172
David Horstmannceeaeb92023-01-05 15:44:23 +0000173 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000179 return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
Daniel Kingb8025c52016-05-17 14:43:01 -0300180}
181
David Horstmannceeaeb92023-01-05 15:44:23 +0000182int 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;
David Horstmannceeaeb92023-01-05 15:44:23 +0000188 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000192 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000197 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000200 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000208 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000214 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000224 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000230 return 0;
Daniel Kingb8025c52016-05-17 14:43:01 -0300231}
232
David Horstmannceeaeb92023-01-05 15:44:23 +0000233int 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];
David Horstmannceeaeb92023-01-05 15:44:23 +0000238 CHACHAPOLY_VALIDATE_RET(ctx != NULL);
239 CHACHAPOLY_VALIDATE_RET(mac != NULL);
Daniel Kingb8025c52016-05-17 14:43:01 -0300240
David Horstmannceeaeb92023-01-05 15:44:23 +0000241 if (ctx->state == CHACHAPOLY_STATE_INIT) {
242 return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
Daniel Kingb8025c52016-05-17 14:43:01 -0300243 }
244
David Horstmannceeaeb92023-01-05 15:44:23 +0000245 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000265 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000270 ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
Manuel Pégourié-Gonnardf4f01b62018-05-24 18:43:42 +0200271
David Horstmannceeaeb92023-01-05 15:44:23 +0000272 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300273}
274
David Horstmannceeaeb92023-01-05 15:44:23 +0000275static 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000287 ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
288 if (ret != 0) {
Daniel Kingb8025c52016-05-17 14:43:01 -0300289 goto cleanup;
David Horstmannceeaeb92023-01-05 15:44:23 +0000290 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300291
David Horstmannceeaeb92023-01-05 15:44:23 +0000292 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;
David Horstmannceeaeb92023-01-05 15:44:23 +0000295 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300296
David Horstmannceeaeb92023-01-05 15:44:23 +0000297 ret = mbedtls_chachapoly_update(ctx, length, input, output);
298 if (ret != 0) {
Manuel Pégourié-Gonnard17297892018-05-24 17:53:41 +0200299 goto cleanup;
David Horstmannceeaeb92023-01-05 15:44:23 +0000300 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300301
David Horstmannceeaeb92023-01-05 15:44:23 +0000302 ret = mbedtls_chachapoly_finish(ctx, tag);
Daniel Kingb8025c52016-05-17 14:43:01 -0300303
304cleanup:
David Horstmannceeaeb92023-01-05 15:44:23 +0000305 return ret;
Daniel Kingb8025c52016-05-17 14:43:01 -0300306}
307
David Horstmannceeaeb92023-01-05 15:44:23 +0000308int 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{
David Horstmannceeaeb92023-01-05 15:44:23 +0000317 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000324 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000329int 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;
David Horstmannceeaeb92023-01-05 15:44:23 +0000342 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000349 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" */
David Horstmannceeaeb92023-01-05 15:44:23 +0000356 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000360 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000461#define ASSERT(cond, args) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200462 do \
463 { \
David Horstmannceeaeb92023-01-05 15:44:23 +0000464 if (!(cond)) \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200465 { \
David Horstmannceeaeb92023-01-05 15:44:23 +0000466 if (verbose != 0) \
467 mbedtls_printf args; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200468 \
David Horstmannceeaeb92023-01-05 15:44:23 +0000469 return -1; \
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200470 } \
471 } \
David Horstmannceeaeb92023-01-05 15:44:23 +0000472 while (0)
Manuel Pégourié-Gonnardc0dfcd42018-05-10 11:42:07 +0200473
David Horstmannceeaeb92023-01-05 15:44:23 +0000474int 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000482 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000487 mbedtls_chachapoly_init(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200488
David Horstmannceeaeb92023-01-05 15:44:23 +0000489 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000492 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000501 ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
Daniel Kingb8025c52016-05-17 14:43:01 -0300502
David Horstmannceeaeb92023-01-05 15:44:23 +0000503 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
David Horstmannceeaeb92023-01-05 15:44:23 +0000506 ASSERT(0 == memcmp(mac, test_mac[i], 16U),
507 ("failure (wrong MAC)\n"));
Daniel Kingdedf4a32016-05-18 10:07:53 -0300508
David Horstmannceeaeb92023-01-05 15:44:23 +0000509 mbedtls_chachapoly_free(&ctx);
Manuel Pégourié-Gonnard346b8d52018-05-07 12:56:36 +0200510
David Horstmannceeaeb92023-01-05 15:44:23 +0000511 if (verbose != 0) {
512 mbedtls_printf("passed\n");
513 }
Daniel Kingdedf4a32016-05-18 10:07:53 -0300514 }
515
David Horstmannceeaeb92023-01-05 15:44:23 +0000516 if (verbose != 0) {
517 mbedtls_printf("\n");
518 }
Daniel Kingb8025c52016-05-17 14:43:01 -0300519
David Horstmannceeaeb92023-01-05 15:44:23 +0000520 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 */