13d3b0591SJens Wiklander /**
23d3b0591SJens Wiklander * \file chachapoly.c
33d3b0591SJens Wiklander *
43d3b0591SJens Wiklander * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
53d3b0591SJens Wiklander *
67901324dSJerome Forissier * Copyright The Mbed TLS Contributors
7*b0563631STom Van Eyck * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
83d3b0591SJens Wiklander */
97901324dSJerome Forissier #include "common.h"
103d3b0591SJens Wiklander
113d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
123d3b0591SJens Wiklander
133d3b0591SJens Wiklander #include "mbedtls/chachapoly.h"
143d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
1511fa71b9SJerome Forissier #include "mbedtls/error.h"
16*b0563631STom Van Eyck #include "mbedtls/constant_time.h"
173d3b0591SJens Wiklander
183d3b0591SJens Wiklander #include <string.h>
193d3b0591SJens Wiklander
203d3b0591SJens Wiklander #include "mbedtls/platform.h"
213d3b0591SJens Wiklander
223d3b0591SJens Wiklander #if !defined(MBEDTLS_CHACHAPOLY_ALT)
233d3b0591SJens Wiklander
243d3b0591SJens Wiklander #define CHACHAPOLY_STATE_INIT (0)
253d3b0591SJens Wiklander #define CHACHAPOLY_STATE_AAD (1)
263d3b0591SJens Wiklander #define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
273d3b0591SJens Wiklander #define CHACHAPOLY_STATE_FINISHED (3)
283d3b0591SJens Wiklander
293d3b0591SJens Wiklander /**
303d3b0591SJens Wiklander * \brief Adds nul bytes to pad the AAD for Poly1305.
313d3b0591SJens Wiklander *
323d3b0591SJens Wiklander * \param ctx The ChaCha20-Poly1305 context.
333d3b0591SJens Wiklander */
chachapoly_pad_aad(mbedtls_chachapoly_context * ctx)343d3b0591SJens Wiklander static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
353d3b0591SJens Wiklander {
363d3b0591SJens Wiklander uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
373d3b0591SJens Wiklander unsigned char zeroes[15];
383d3b0591SJens Wiklander
3932b31808SJens Wiklander if (partial_block_len == 0U) {
4032b31808SJens Wiklander return 0;
4132b31808SJens Wiklander }
423d3b0591SJens Wiklander
433d3b0591SJens Wiklander memset(zeroes, 0, sizeof(zeroes));
443d3b0591SJens Wiklander
4532b31808SJens Wiklander return mbedtls_poly1305_update(&ctx->poly1305_ctx,
463d3b0591SJens Wiklander zeroes,
4732b31808SJens Wiklander 16U - partial_block_len);
483d3b0591SJens Wiklander }
493d3b0591SJens Wiklander
503d3b0591SJens Wiklander /**
513d3b0591SJens Wiklander * \brief Adds nul bytes to pad the ciphertext for Poly1305.
523d3b0591SJens Wiklander *
533d3b0591SJens Wiklander * \param ctx The ChaCha20-Poly1305 context.
543d3b0591SJens Wiklander */
chachapoly_pad_ciphertext(mbedtls_chachapoly_context * ctx)553d3b0591SJens Wiklander static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
563d3b0591SJens Wiklander {
573d3b0591SJens Wiklander uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
583d3b0591SJens Wiklander unsigned char zeroes[15];
593d3b0591SJens Wiklander
6032b31808SJens Wiklander if (partial_block_len == 0U) {
6132b31808SJens Wiklander return 0;
6232b31808SJens Wiklander }
633d3b0591SJens Wiklander
643d3b0591SJens Wiklander memset(zeroes, 0, sizeof(zeroes));
6532b31808SJens Wiklander return mbedtls_poly1305_update(&ctx->poly1305_ctx,
663d3b0591SJens Wiklander zeroes,
6732b31808SJens Wiklander 16U - partial_block_len);
683d3b0591SJens Wiklander }
693d3b0591SJens Wiklander
mbedtls_chachapoly_init(mbedtls_chachapoly_context * ctx)703d3b0591SJens Wiklander void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
713d3b0591SJens Wiklander {
723d3b0591SJens Wiklander mbedtls_chacha20_init(&ctx->chacha20_ctx);
733d3b0591SJens Wiklander mbedtls_poly1305_init(&ctx->poly1305_ctx);
743d3b0591SJens Wiklander ctx->aad_len = 0U;
753d3b0591SJens Wiklander ctx->ciphertext_len = 0U;
763d3b0591SJens Wiklander ctx->state = CHACHAPOLY_STATE_INIT;
773d3b0591SJens Wiklander ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
783d3b0591SJens Wiklander }
793d3b0591SJens Wiklander
mbedtls_chachapoly_free(mbedtls_chachapoly_context * ctx)803d3b0591SJens Wiklander void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
813d3b0591SJens Wiklander {
8232b31808SJens Wiklander if (ctx == NULL) {
833d3b0591SJens Wiklander return;
8432b31808SJens Wiklander }
853d3b0591SJens Wiklander
863d3b0591SJens Wiklander mbedtls_chacha20_free(&ctx->chacha20_ctx);
873d3b0591SJens Wiklander mbedtls_poly1305_free(&ctx->poly1305_ctx);
883d3b0591SJens Wiklander ctx->aad_len = 0U;
893d3b0591SJens Wiklander ctx->ciphertext_len = 0U;
903d3b0591SJens Wiklander ctx->state = CHACHAPOLY_STATE_INIT;
913d3b0591SJens Wiklander ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
923d3b0591SJens Wiklander }
933d3b0591SJens Wiklander
mbedtls_chachapoly_setkey(mbedtls_chachapoly_context * ctx,const unsigned char key[32])943d3b0591SJens Wiklander int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
953d3b0591SJens Wiklander const unsigned char key[32])
963d3b0591SJens Wiklander {
9711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
983d3b0591SJens Wiklander
993d3b0591SJens Wiklander ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
1003d3b0591SJens Wiklander
10132b31808SJens Wiklander return ret;
1023d3b0591SJens Wiklander }
1033d3b0591SJens Wiklander
mbedtls_chachapoly_starts(mbedtls_chachapoly_context * ctx,const unsigned char nonce[12],mbedtls_chachapoly_mode_t mode)1043d3b0591SJens Wiklander int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
1053d3b0591SJens Wiklander const unsigned char nonce[12],
1063d3b0591SJens Wiklander mbedtls_chachapoly_mode_t mode)
1073d3b0591SJens Wiklander {
10811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1093d3b0591SJens Wiklander unsigned char poly1305_key[64];
1103d3b0591SJens Wiklander
1113d3b0591SJens Wiklander /* Set counter = 0, will be update to 1 when generating Poly1305 key */
1123d3b0591SJens Wiklander ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
11332b31808SJens Wiklander if (ret != 0) {
1143d3b0591SJens Wiklander goto cleanup;
11532b31808SJens Wiklander }
1163d3b0591SJens Wiklander
1173d3b0591SJens Wiklander /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
1183d3b0591SJens Wiklander * counter = 0. This is the same as encrypting a buffer of zeroes.
1193d3b0591SJens Wiklander * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
1203d3b0591SJens Wiklander * The other 256 bits are discarded.
1213d3b0591SJens Wiklander */
1223d3b0591SJens Wiklander memset(poly1305_key, 0, sizeof(poly1305_key));
1233d3b0591SJens Wiklander ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
1243d3b0591SJens Wiklander poly1305_key, poly1305_key);
12532b31808SJens Wiklander if (ret != 0) {
1263d3b0591SJens Wiklander goto cleanup;
12732b31808SJens Wiklander }
1283d3b0591SJens Wiklander
1293d3b0591SJens Wiklander ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
1303d3b0591SJens Wiklander
13132b31808SJens Wiklander if (ret == 0) {
1323d3b0591SJens Wiklander ctx->aad_len = 0U;
1333d3b0591SJens Wiklander ctx->ciphertext_len = 0U;
1343d3b0591SJens Wiklander ctx->state = CHACHAPOLY_STATE_AAD;
1353d3b0591SJens Wiklander ctx->mode = mode;
1363d3b0591SJens Wiklander }
1373d3b0591SJens Wiklander
1383d3b0591SJens Wiklander cleanup:
1393d3b0591SJens Wiklander mbedtls_platform_zeroize(poly1305_key, 64U);
14032b31808SJens Wiklander return ret;
1413d3b0591SJens Wiklander }
1423d3b0591SJens Wiklander
mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context * ctx,const unsigned char * aad,size_t aad_len)1433d3b0591SJens Wiklander int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
1443d3b0591SJens Wiklander const unsigned char *aad,
1453d3b0591SJens Wiklander size_t aad_len)
1463d3b0591SJens Wiklander {
14732b31808SJens Wiklander if (ctx->state != CHACHAPOLY_STATE_AAD) {
14832b31808SJens Wiklander return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
14932b31808SJens Wiklander }
1503d3b0591SJens Wiklander
1513d3b0591SJens Wiklander ctx->aad_len += aad_len;
1523d3b0591SJens Wiklander
15332b31808SJens Wiklander return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
1543d3b0591SJens Wiklander }
1553d3b0591SJens Wiklander
mbedtls_chachapoly_update(mbedtls_chachapoly_context * ctx,size_t len,const unsigned char * input,unsigned char * output)1563d3b0591SJens Wiklander int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
1573d3b0591SJens Wiklander size_t len,
1583d3b0591SJens Wiklander const unsigned char *input,
1593d3b0591SJens Wiklander unsigned char *output)
1603d3b0591SJens Wiklander {
16111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1623d3b0591SJens Wiklander
1633d3b0591SJens Wiklander if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
16432b31808SJens Wiklander (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
16532b31808SJens Wiklander return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
1663d3b0591SJens Wiklander }
1673d3b0591SJens Wiklander
16832b31808SJens Wiklander if (ctx->state == CHACHAPOLY_STATE_AAD) {
1693d3b0591SJens Wiklander ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
1703d3b0591SJens Wiklander
1713d3b0591SJens Wiklander ret = chachapoly_pad_aad(ctx);
17232b31808SJens Wiklander if (ret != 0) {
17332b31808SJens Wiklander return ret;
17432b31808SJens Wiklander }
1753d3b0591SJens Wiklander }
1763d3b0591SJens Wiklander
1773d3b0591SJens Wiklander ctx->ciphertext_len += len;
1783d3b0591SJens Wiklander
17932b31808SJens Wiklander if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
1803d3b0591SJens Wiklander ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
18132b31808SJens Wiklander if (ret != 0) {
18232b31808SJens Wiklander return ret;
18332b31808SJens Wiklander }
1843d3b0591SJens Wiklander
1853d3b0591SJens Wiklander ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
18632b31808SJens Wiklander if (ret != 0) {
18732b31808SJens Wiklander return ret;
1883d3b0591SJens Wiklander }
18932b31808SJens Wiklander } else { /* DECRYPT */
1903d3b0591SJens Wiklander ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
19132b31808SJens Wiklander if (ret != 0) {
19232b31808SJens Wiklander return ret;
19332b31808SJens Wiklander }
1943d3b0591SJens Wiklander
1953d3b0591SJens Wiklander ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
19632b31808SJens Wiklander if (ret != 0) {
19732b31808SJens Wiklander return ret;
19832b31808SJens Wiklander }
1993d3b0591SJens Wiklander }
2003d3b0591SJens Wiklander
20132b31808SJens Wiklander return 0;
2023d3b0591SJens Wiklander }
2033d3b0591SJens Wiklander
mbedtls_chachapoly_finish(mbedtls_chachapoly_context * ctx,unsigned char mac[16])2043d3b0591SJens Wiklander int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
2053d3b0591SJens Wiklander unsigned char mac[16])
2063d3b0591SJens Wiklander {
20711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2083d3b0591SJens Wiklander unsigned char len_block[16];
2093d3b0591SJens Wiklander
21032b31808SJens Wiklander if (ctx->state == CHACHAPOLY_STATE_INIT) {
21132b31808SJens Wiklander return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
2123d3b0591SJens Wiklander }
2133d3b0591SJens Wiklander
21432b31808SJens Wiklander if (ctx->state == CHACHAPOLY_STATE_AAD) {
2153d3b0591SJens Wiklander ret = chachapoly_pad_aad(ctx);
21632b31808SJens Wiklander if (ret != 0) {
21732b31808SJens Wiklander return ret;
2183d3b0591SJens Wiklander }
21932b31808SJens Wiklander } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
2203d3b0591SJens Wiklander ret = chachapoly_pad_ciphertext(ctx);
22132b31808SJens Wiklander if (ret != 0) {
22232b31808SJens Wiklander return ret;
22332b31808SJens Wiklander }
2243d3b0591SJens Wiklander }
2253d3b0591SJens Wiklander
2263d3b0591SJens Wiklander ctx->state = CHACHAPOLY_STATE_FINISHED;
2273d3b0591SJens Wiklander
2283d3b0591SJens Wiklander /* The lengths of the AAD and ciphertext are processed by
2293d3b0591SJens Wiklander * Poly1305 as the final 128-bit block, encoded as little-endian integers.
2303d3b0591SJens Wiklander */
231039e02dfSJerome Forissier MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
232039e02dfSJerome Forissier MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
2333d3b0591SJens Wiklander
2343d3b0591SJens Wiklander ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
23532b31808SJens Wiklander if (ret != 0) {
23632b31808SJens Wiklander return ret;
23732b31808SJens Wiklander }
2383d3b0591SJens Wiklander
2393d3b0591SJens Wiklander ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
2403d3b0591SJens Wiklander
24132b31808SJens Wiklander return ret;
2423d3b0591SJens Wiklander }
2433d3b0591SJens Wiklander
chachapoly_crypt_and_tag(mbedtls_chachapoly_context * ctx,mbedtls_chachapoly_mode_t mode,size_t length,const unsigned char nonce[12],const unsigned char * aad,size_t aad_len,const unsigned char * input,unsigned char * output,unsigned char tag[16])2443d3b0591SJens Wiklander static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
2453d3b0591SJens Wiklander mbedtls_chachapoly_mode_t mode,
2463d3b0591SJens Wiklander size_t length,
2473d3b0591SJens Wiklander const unsigned char nonce[12],
2483d3b0591SJens Wiklander const unsigned char *aad,
2493d3b0591SJens Wiklander size_t aad_len,
2503d3b0591SJens Wiklander const unsigned char *input,
2513d3b0591SJens Wiklander unsigned char *output,
2523d3b0591SJens Wiklander unsigned char tag[16])
2533d3b0591SJens Wiklander {
25411fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2553d3b0591SJens Wiklander
2563d3b0591SJens Wiklander ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
25732b31808SJens Wiklander if (ret != 0) {
2583d3b0591SJens Wiklander goto cleanup;
25932b31808SJens Wiklander }
2603d3b0591SJens Wiklander
2613d3b0591SJens Wiklander ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
26232b31808SJens Wiklander if (ret != 0) {
2633d3b0591SJens Wiklander goto cleanup;
26432b31808SJens Wiklander }
2653d3b0591SJens Wiklander
2663d3b0591SJens Wiklander ret = mbedtls_chachapoly_update(ctx, length, input, output);
26732b31808SJens Wiklander if (ret != 0) {
2683d3b0591SJens Wiklander goto cleanup;
26932b31808SJens Wiklander }
2703d3b0591SJens Wiklander
2713d3b0591SJens Wiklander ret = mbedtls_chachapoly_finish(ctx, tag);
2723d3b0591SJens Wiklander
2733d3b0591SJens Wiklander cleanup:
27432b31808SJens Wiklander return ret;
2753d3b0591SJens Wiklander }
2763d3b0591SJens Wiklander
mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context * ctx,size_t length,const unsigned char nonce[12],const unsigned char * aad,size_t aad_len,const unsigned char * input,unsigned char * output,unsigned char tag[16])2773d3b0591SJens Wiklander int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
2783d3b0591SJens Wiklander size_t length,
2793d3b0591SJens Wiklander const unsigned char nonce[12],
2803d3b0591SJens Wiklander const unsigned char *aad,
2813d3b0591SJens Wiklander size_t aad_len,
2823d3b0591SJens Wiklander const unsigned char *input,
2833d3b0591SJens Wiklander unsigned char *output,
2843d3b0591SJens Wiklander unsigned char tag[16])
2853d3b0591SJens Wiklander {
28632b31808SJens Wiklander return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
2873d3b0591SJens Wiklander length, nonce, aad, aad_len,
28832b31808SJens Wiklander input, output, tag);
2893d3b0591SJens Wiklander }
2903d3b0591SJens Wiklander
mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context * ctx,size_t length,const unsigned char nonce[12],const unsigned char * aad,size_t aad_len,const unsigned char tag[16],const unsigned char * input,unsigned char * output)2913d3b0591SJens Wiklander int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
2923d3b0591SJens Wiklander size_t length,
2933d3b0591SJens Wiklander const unsigned char nonce[12],
2943d3b0591SJens Wiklander const unsigned char *aad,
2953d3b0591SJens Wiklander size_t aad_len,
2963d3b0591SJens Wiklander const unsigned char tag[16],
2973d3b0591SJens Wiklander const unsigned char *input,
2983d3b0591SJens Wiklander unsigned char *output)
2993d3b0591SJens Wiklander {
30011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3013d3b0591SJens Wiklander unsigned char check_tag[16];
3023d3b0591SJens Wiklander int diff;
3033d3b0591SJens Wiklander
3043d3b0591SJens Wiklander if ((ret = chachapoly_crypt_and_tag(ctx,
3053d3b0591SJens Wiklander MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
30632b31808SJens Wiklander aad, aad_len, input, output, check_tag)) != 0) {
30732b31808SJens Wiklander return ret;
3083d3b0591SJens Wiklander }
3093d3b0591SJens Wiklander
3103d3b0591SJens Wiklander /* Check tag in "constant-time" */
311*b0563631STom Van Eyck diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));
3123d3b0591SJens Wiklander
31332b31808SJens Wiklander if (diff != 0) {
31432b31808SJens Wiklander mbedtls_platform_zeroize(output, length);
31532b31808SJens Wiklander return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
31632b31808SJens Wiklander }
31732b31808SJens Wiklander
31832b31808SJens Wiklander return 0;
3193d3b0591SJens Wiklander }
3203d3b0591SJens Wiklander
3213d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_ALT */
3223d3b0591SJens Wiklander
3233d3b0591SJens Wiklander #if defined(MBEDTLS_SELF_TEST)
3243d3b0591SJens Wiklander
3253d3b0591SJens Wiklander static const unsigned char test_key[1][32] =
3263d3b0591SJens Wiklander {
3273d3b0591SJens Wiklander {
3283d3b0591SJens Wiklander 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
3293d3b0591SJens Wiklander 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
3303d3b0591SJens Wiklander 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
3313d3b0591SJens Wiklander 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
3323d3b0591SJens Wiklander }
3333d3b0591SJens Wiklander };
3343d3b0591SJens Wiklander
3353d3b0591SJens Wiklander static const unsigned char test_nonce[1][12] =
3363d3b0591SJens Wiklander {
3373d3b0591SJens Wiklander {
3383d3b0591SJens Wiklander 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
3393d3b0591SJens Wiklander 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
3403d3b0591SJens Wiklander }
3413d3b0591SJens Wiklander };
3423d3b0591SJens Wiklander
3433d3b0591SJens Wiklander static const unsigned char test_aad[1][12] =
3443d3b0591SJens Wiklander {
3453d3b0591SJens Wiklander {
3463d3b0591SJens Wiklander 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
3473d3b0591SJens Wiklander 0xc4, 0xc5, 0xc6, 0xc7
3483d3b0591SJens Wiklander }
3493d3b0591SJens Wiklander };
3503d3b0591SJens Wiklander
3513d3b0591SJens Wiklander static const size_t test_aad_len[1] =
3523d3b0591SJens Wiklander {
3533d3b0591SJens Wiklander 12U
3543d3b0591SJens Wiklander };
3553d3b0591SJens Wiklander
3563d3b0591SJens Wiklander static const unsigned char test_input[1][114] =
3573d3b0591SJens Wiklander {
3583d3b0591SJens Wiklander {
3593d3b0591SJens Wiklander 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
3603d3b0591SJens Wiklander 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
3613d3b0591SJens Wiklander 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
3623d3b0591SJens Wiklander 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
3633d3b0591SJens Wiklander 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
3643d3b0591SJens Wiklander 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
3653d3b0591SJens Wiklander 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
3663d3b0591SJens Wiklander 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
3673d3b0591SJens Wiklander 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
3683d3b0591SJens Wiklander 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
3693d3b0591SJens Wiklander 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
3703d3b0591SJens Wiklander 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
3713d3b0591SJens Wiklander 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
3723d3b0591SJens Wiklander 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
3733d3b0591SJens Wiklander 0x74, 0x2e
3743d3b0591SJens Wiklander }
3753d3b0591SJens Wiklander };
3763d3b0591SJens Wiklander
3773d3b0591SJens Wiklander static const unsigned char test_output[1][114] =
3783d3b0591SJens Wiklander {
3793d3b0591SJens Wiklander {
3803d3b0591SJens Wiklander 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
3813d3b0591SJens Wiklander 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
3823d3b0591SJens Wiklander 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
3833d3b0591SJens Wiklander 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
3843d3b0591SJens Wiklander 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
3853d3b0591SJens Wiklander 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
3863d3b0591SJens Wiklander 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
3873d3b0591SJens Wiklander 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
3883d3b0591SJens Wiklander 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
3893d3b0591SJens Wiklander 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
3903d3b0591SJens Wiklander 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
3913d3b0591SJens Wiklander 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
3923d3b0591SJens Wiklander 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
3933d3b0591SJens Wiklander 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
3943d3b0591SJens Wiklander 0x61, 0x16
3953d3b0591SJens Wiklander }
3963d3b0591SJens Wiklander };
3973d3b0591SJens Wiklander
3983d3b0591SJens Wiklander static const size_t test_input_len[1] =
3993d3b0591SJens Wiklander {
4003d3b0591SJens Wiklander 114U
4013d3b0591SJens Wiklander };
4023d3b0591SJens Wiklander
4033d3b0591SJens Wiklander static const unsigned char test_mac[1][16] =
4043d3b0591SJens Wiklander {
4053d3b0591SJens Wiklander {
4063d3b0591SJens Wiklander 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
4073d3b0591SJens Wiklander 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
4083d3b0591SJens Wiklander }
4093d3b0591SJens Wiklander };
4103d3b0591SJens Wiklander
4117901324dSJerome Forissier /* Make sure no other definition is already present. */
4127901324dSJerome Forissier #undef ASSERT
4137901324dSJerome Forissier
4143d3b0591SJens Wiklander #define ASSERT(cond, args) \
4153d3b0591SJens Wiklander do \
4163d3b0591SJens Wiklander { \
4173d3b0591SJens Wiklander if (!(cond)) \
4183d3b0591SJens Wiklander { \
4193d3b0591SJens Wiklander if (verbose != 0) \
4203d3b0591SJens Wiklander mbedtls_printf args; \
4213d3b0591SJens Wiklander \
42232b31808SJens Wiklander return -1; \
4233d3b0591SJens Wiklander } \
4243d3b0591SJens Wiklander } \
4253d3b0591SJens Wiklander while (0)
4263d3b0591SJens Wiklander
mbedtls_chachapoly_self_test(int verbose)4273d3b0591SJens Wiklander int mbedtls_chachapoly_self_test(int verbose)
4283d3b0591SJens Wiklander {
4293d3b0591SJens Wiklander mbedtls_chachapoly_context ctx;
4303d3b0591SJens Wiklander unsigned i;
43111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4323d3b0591SJens Wiklander unsigned char output[200];
4333d3b0591SJens Wiklander unsigned char mac[16];
4343d3b0591SJens Wiklander
43532b31808SJens Wiklander for (i = 0U; i < 1U; i++) {
43632b31808SJens Wiklander if (verbose != 0) {
4373d3b0591SJens Wiklander mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
43832b31808SJens Wiklander }
4393d3b0591SJens Wiklander
4403d3b0591SJens Wiklander mbedtls_chachapoly_init(&ctx);
4413d3b0591SJens Wiklander
4423d3b0591SJens Wiklander ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
4433d3b0591SJens Wiklander ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
4443d3b0591SJens Wiklander
4453d3b0591SJens Wiklander ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
4463d3b0591SJens Wiklander test_input_len[i],
4473d3b0591SJens Wiklander test_nonce[i],
4483d3b0591SJens Wiklander test_aad[i],
4493d3b0591SJens Wiklander test_aad_len[i],
4503d3b0591SJens Wiklander test_input[i],
4513d3b0591SJens Wiklander output,
4523d3b0591SJens Wiklander mac);
4533d3b0591SJens Wiklander
4543d3b0591SJens Wiklander ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
4553d3b0591SJens Wiklander
4563d3b0591SJens Wiklander ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
4573d3b0591SJens Wiklander ("failure (wrong output)\n"));
4583d3b0591SJens Wiklander
4593d3b0591SJens Wiklander ASSERT(0 == memcmp(mac, test_mac[i], 16U),
4603d3b0591SJens Wiklander ("failure (wrong MAC)\n"));
4613d3b0591SJens Wiklander
4623d3b0591SJens Wiklander mbedtls_chachapoly_free(&ctx);
4633d3b0591SJens Wiklander
46432b31808SJens Wiklander if (verbose != 0) {
4653d3b0591SJens Wiklander mbedtls_printf("passed\n");
4663d3b0591SJens Wiklander }
46732b31808SJens Wiklander }
4683d3b0591SJens Wiklander
46932b31808SJens Wiklander if (verbose != 0) {
4703d3b0591SJens Wiklander mbedtls_printf("\n");
47132b31808SJens Wiklander }
4723d3b0591SJens Wiklander
47332b31808SJens Wiklander return 0;
4743d3b0591SJens Wiklander }
4753d3b0591SJens Wiklander
4763d3b0591SJens Wiklander #endif /* MBEDTLS_SELF_TEST */
4773d3b0591SJens Wiklander
4783d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */
479