xref: /optee_os/lib/libmbedtls/mbedtls/library/chachapoly.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
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
77901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
83d3b0591SJens Wiklander  *
93d3b0591SJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
103d3b0591SJens Wiklander  *  not use this file except in compliance with the License.
113d3b0591SJens Wiklander  *  You may obtain a copy of the License at
123d3b0591SJens Wiklander  *
133d3b0591SJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
143d3b0591SJens Wiklander  *
153d3b0591SJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
163d3b0591SJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
173d3b0591SJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
183d3b0591SJens Wiklander  *  See the License for the specific language governing permissions and
193d3b0591SJens Wiklander  *  limitations under the License.
203d3b0591SJens Wiklander  */
217901324dSJerome Forissier #include "common.h"
223d3b0591SJens Wiklander 
233d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHAPOLY_C)
243d3b0591SJens Wiklander 
253d3b0591SJens Wiklander #include "mbedtls/chachapoly.h"
263d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
2711fa71b9SJerome Forissier #include "mbedtls/error.h"
283d3b0591SJens Wiklander 
293d3b0591SJens Wiklander #include <string.h>
303d3b0591SJens Wiklander 
313d3b0591SJens Wiklander #include "mbedtls/platform.h"
323d3b0591SJens Wiklander 
333d3b0591SJens Wiklander #if !defined(MBEDTLS_CHACHAPOLY_ALT)
343d3b0591SJens Wiklander 
353d3b0591SJens Wiklander #define CHACHAPOLY_STATE_INIT       (0)
363d3b0591SJens Wiklander #define CHACHAPOLY_STATE_AAD        (1)
373d3b0591SJens Wiklander #define CHACHAPOLY_STATE_CIPHERTEXT (2)   /* Encrypting or decrypting */
383d3b0591SJens Wiklander #define CHACHAPOLY_STATE_FINISHED   (3)
393d3b0591SJens Wiklander 
403d3b0591SJens Wiklander /**
413d3b0591SJens Wiklander  * \brief           Adds nul bytes to pad the AAD for Poly1305.
423d3b0591SJens Wiklander  *
433d3b0591SJens Wiklander  * \param ctx       The ChaCha20-Poly1305 context.
443d3b0591SJens Wiklander  */
453d3b0591SJens Wiklander static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
463d3b0591SJens Wiklander {
473d3b0591SJens Wiklander     uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
483d3b0591SJens Wiklander     unsigned char zeroes[15];
493d3b0591SJens Wiklander 
50*32b31808SJens Wiklander     if (partial_block_len == 0U) {
51*32b31808SJens Wiklander         return 0;
52*32b31808SJens Wiklander     }
533d3b0591SJens Wiklander 
543d3b0591SJens Wiklander     memset(zeroes, 0, sizeof(zeroes));
553d3b0591SJens Wiklander 
56*32b31808SJens Wiklander     return mbedtls_poly1305_update(&ctx->poly1305_ctx,
573d3b0591SJens Wiklander                                    zeroes,
58*32b31808SJens Wiklander                                    16U - partial_block_len);
593d3b0591SJens Wiklander }
603d3b0591SJens Wiklander 
613d3b0591SJens Wiklander /**
623d3b0591SJens Wiklander  * \brief           Adds nul bytes to pad the ciphertext for Poly1305.
633d3b0591SJens Wiklander  *
643d3b0591SJens Wiklander  * \param ctx       The ChaCha20-Poly1305 context.
653d3b0591SJens Wiklander  */
663d3b0591SJens Wiklander static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
673d3b0591SJens Wiklander {
683d3b0591SJens Wiklander     uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
693d3b0591SJens Wiklander     unsigned char zeroes[15];
703d3b0591SJens Wiklander 
71*32b31808SJens Wiklander     if (partial_block_len == 0U) {
72*32b31808SJens Wiklander         return 0;
73*32b31808SJens Wiklander     }
743d3b0591SJens Wiklander 
753d3b0591SJens Wiklander     memset(zeroes, 0, sizeof(zeroes));
76*32b31808SJens Wiklander     return mbedtls_poly1305_update(&ctx->poly1305_ctx,
773d3b0591SJens Wiklander                                    zeroes,
78*32b31808SJens Wiklander                                    16U - partial_block_len);
793d3b0591SJens Wiklander }
803d3b0591SJens Wiklander 
813d3b0591SJens Wiklander void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
823d3b0591SJens Wiklander {
833d3b0591SJens Wiklander     mbedtls_chacha20_init(&ctx->chacha20_ctx);
843d3b0591SJens Wiklander     mbedtls_poly1305_init(&ctx->poly1305_ctx);
853d3b0591SJens Wiklander     ctx->aad_len        = 0U;
863d3b0591SJens Wiklander     ctx->ciphertext_len = 0U;
873d3b0591SJens Wiklander     ctx->state          = CHACHAPOLY_STATE_INIT;
883d3b0591SJens Wiklander     ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
893d3b0591SJens Wiklander }
903d3b0591SJens Wiklander 
913d3b0591SJens Wiklander void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
923d3b0591SJens Wiklander {
93*32b31808SJens Wiklander     if (ctx == NULL) {
943d3b0591SJens Wiklander         return;
95*32b31808SJens Wiklander     }
963d3b0591SJens Wiklander 
973d3b0591SJens Wiklander     mbedtls_chacha20_free(&ctx->chacha20_ctx);
983d3b0591SJens Wiklander     mbedtls_poly1305_free(&ctx->poly1305_ctx);
993d3b0591SJens Wiklander     ctx->aad_len        = 0U;
1003d3b0591SJens Wiklander     ctx->ciphertext_len = 0U;
1013d3b0591SJens Wiklander     ctx->state          = CHACHAPOLY_STATE_INIT;
1023d3b0591SJens Wiklander     ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
1033d3b0591SJens Wiklander }
1043d3b0591SJens Wiklander 
1053d3b0591SJens Wiklander int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
1063d3b0591SJens Wiklander                               const unsigned char key[32])
1073d3b0591SJens Wiklander {
10811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1093d3b0591SJens Wiklander 
1103d3b0591SJens Wiklander     ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
1113d3b0591SJens Wiklander 
112*32b31808SJens Wiklander     return ret;
1133d3b0591SJens Wiklander }
1143d3b0591SJens Wiklander 
1153d3b0591SJens Wiklander int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
1163d3b0591SJens Wiklander                               const unsigned char nonce[12],
1173d3b0591SJens Wiklander                               mbedtls_chachapoly_mode_t mode)
1183d3b0591SJens Wiklander {
11911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1203d3b0591SJens Wiklander     unsigned char poly1305_key[64];
1213d3b0591SJens Wiklander 
1223d3b0591SJens Wiklander     /* Set counter = 0, will be update to 1 when generating Poly1305 key */
1233d3b0591SJens Wiklander     ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
124*32b31808SJens Wiklander     if (ret != 0) {
1253d3b0591SJens Wiklander         goto cleanup;
126*32b31808SJens Wiklander     }
1273d3b0591SJens Wiklander 
1283d3b0591SJens Wiklander     /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
1293d3b0591SJens Wiklander      * counter = 0.  This is the same as encrypting a buffer of zeroes.
1303d3b0591SJens Wiklander      * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
1313d3b0591SJens Wiklander      * The other 256 bits are discarded.
1323d3b0591SJens Wiklander      */
1333d3b0591SJens Wiklander     memset(poly1305_key, 0, sizeof(poly1305_key));
1343d3b0591SJens Wiklander     ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
1353d3b0591SJens Wiklander                                   poly1305_key, poly1305_key);
136*32b31808SJens Wiklander     if (ret != 0) {
1373d3b0591SJens Wiklander         goto cleanup;
138*32b31808SJens Wiklander     }
1393d3b0591SJens Wiklander 
1403d3b0591SJens Wiklander     ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
1413d3b0591SJens Wiklander 
142*32b31808SJens Wiklander     if (ret == 0) {
1433d3b0591SJens Wiklander         ctx->aad_len        = 0U;
1443d3b0591SJens Wiklander         ctx->ciphertext_len = 0U;
1453d3b0591SJens Wiklander         ctx->state          = CHACHAPOLY_STATE_AAD;
1463d3b0591SJens Wiklander         ctx->mode           = mode;
1473d3b0591SJens Wiklander     }
1483d3b0591SJens Wiklander 
1493d3b0591SJens Wiklander cleanup:
1503d3b0591SJens Wiklander     mbedtls_platform_zeroize(poly1305_key, 64U);
151*32b31808SJens Wiklander     return ret;
1523d3b0591SJens Wiklander }
1533d3b0591SJens Wiklander 
1543d3b0591SJens Wiklander int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
1553d3b0591SJens Wiklander                                   const unsigned char *aad,
1563d3b0591SJens Wiklander                                   size_t aad_len)
1573d3b0591SJens Wiklander {
158*32b31808SJens Wiklander     if (ctx->state != CHACHAPOLY_STATE_AAD) {
159*32b31808SJens Wiklander         return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
160*32b31808SJens Wiklander     }
1613d3b0591SJens Wiklander 
1623d3b0591SJens Wiklander     ctx->aad_len += aad_len;
1633d3b0591SJens Wiklander 
164*32b31808SJens Wiklander     return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
1653d3b0591SJens Wiklander }
1663d3b0591SJens Wiklander 
1673d3b0591SJens Wiklander int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
1683d3b0591SJens Wiklander                               size_t len,
1693d3b0591SJens Wiklander                               const unsigned char *input,
1703d3b0591SJens Wiklander                               unsigned char *output)
1713d3b0591SJens Wiklander {
17211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1733d3b0591SJens Wiklander 
1743d3b0591SJens Wiklander     if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
175*32b31808SJens Wiklander         (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
176*32b31808SJens Wiklander         return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
1773d3b0591SJens Wiklander     }
1783d3b0591SJens Wiklander 
179*32b31808SJens Wiklander     if (ctx->state == CHACHAPOLY_STATE_AAD) {
1803d3b0591SJens Wiklander         ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
1813d3b0591SJens Wiklander 
1823d3b0591SJens Wiklander         ret = chachapoly_pad_aad(ctx);
183*32b31808SJens Wiklander         if (ret != 0) {
184*32b31808SJens Wiklander             return ret;
185*32b31808SJens Wiklander         }
1863d3b0591SJens Wiklander     }
1873d3b0591SJens Wiklander 
1883d3b0591SJens Wiklander     ctx->ciphertext_len += len;
1893d3b0591SJens Wiklander 
190*32b31808SJens Wiklander     if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
1913d3b0591SJens Wiklander         ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
192*32b31808SJens Wiklander         if (ret != 0) {
193*32b31808SJens Wiklander             return ret;
194*32b31808SJens Wiklander         }
1953d3b0591SJens Wiklander 
1963d3b0591SJens Wiklander         ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
197*32b31808SJens Wiklander         if (ret != 0) {
198*32b31808SJens Wiklander             return ret;
1993d3b0591SJens Wiklander         }
200*32b31808SJens Wiklander     } else { /* DECRYPT */
2013d3b0591SJens Wiklander         ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
202*32b31808SJens Wiklander         if (ret != 0) {
203*32b31808SJens Wiklander             return ret;
204*32b31808SJens Wiklander         }
2053d3b0591SJens Wiklander 
2063d3b0591SJens Wiklander         ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
207*32b31808SJens Wiklander         if (ret != 0) {
208*32b31808SJens Wiklander             return ret;
209*32b31808SJens Wiklander         }
2103d3b0591SJens Wiklander     }
2113d3b0591SJens Wiklander 
212*32b31808SJens Wiklander     return 0;
2133d3b0591SJens Wiklander }
2143d3b0591SJens Wiklander 
2153d3b0591SJens Wiklander int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
2163d3b0591SJens Wiklander                               unsigned char mac[16])
2173d3b0591SJens Wiklander {
21811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2193d3b0591SJens Wiklander     unsigned char len_block[16];
2203d3b0591SJens Wiklander 
221*32b31808SJens Wiklander     if (ctx->state == CHACHAPOLY_STATE_INIT) {
222*32b31808SJens Wiklander         return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
2233d3b0591SJens Wiklander     }
2243d3b0591SJens Wiklander 
225*32b31808SJens Wiklander     if (ctx->state == CHACHAPOLY_STATE_AAD) {
2263d3b0591SJens Wiklander         ret = chachapoly_pad_aad(ctx);
227*32b31808SJens Wiklander         if (ret != 0) {
228*32b31808SJens Wiklander             return ret;
2293d3b0591SJens Wiklander         }
230*32b31808SJens Wiklander     } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
2313d3b0591SJens Wiklander         ret = chachapoly_pad_ciphertext(ctx);
232*32b31808SJens Wiklander         if (ret != 0) {
233*32b31808SJens Wiklander             return ret;
234*32b31808SJens Wiklander         }
2353d3b0591SJens Wiklander     }
2363d3b0591SJens Wiklander 
2373d3b0591SJens Wiklander     ctx->state = CHACHAPOLY_STATE_FINISHED;
2383d3b0591SJens Wiklander 
2393d3b0591SJens Wiklander     /* The lengths of the AAD and ciphertext are processed by
2403d3b0591SJens Wiklander      * Poly1305 as the final 128-bit block, encoded as little-endian integers.
2413d3b0591SJens Wiklander      */
242039e02dfSJerome Forissier     MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
243039e02dfSJerome Forissier     MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
2443d3b0591SJens Wiklander 
2453d3b0591SJens Wiklander     ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
246*32b31808SJens Wiklander     if (ret != 0) {
247*32b31808SJens Wiklander         return ret;
248*32b31808SJens Wiklander     }
2493d3b0591SJens Wiklander 
2503d3b0591SJens Wiklander     ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
2513d3b0591SJens Wiklander 
252*32b31808SJens Wiklander     return ret;
2533d3b0591SJens Wiklander }
2543d3b0591SJens Wiklander 
2553d3b0591SJens Wiklander static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
2563d3b0591SJens Wiklander                                     mbedtls_chachapoly_mode_t mode,
2573d3b0591SJens Wiklander                                     size_t length,
2583d3b0591SJens Wiklander                                     const unsigned char nonce[12],
2593d3b0591SJens Wiklander                                     const unsigned char *aad,
2603d3b0591SJens Wiklander                                     size_t aad_len,
2613d3b0591SJens Wiklander                                     const unsigned char *input,
2623d3b0591SJens Wiklander                                     unsigned char *output,
2633d3b0591SJens Wiklander                                     unsigned char tag[16])
2643d3b0591SJens Wiklander {
26511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2663d3b0591SJens Wiklander 
2673d3b0591SJens Wiklander     ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
268*32b31808SJens Wiklander     if (ret != 0) {
2693d3b0591SJens Wiklander         goto cleanup;
270*32b31808SJens Wiklander     }
2713d3b0591SJens Wiklander 
2723d3b0591SJens Wiklander     ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
273*32b31808SJens Wiklander     if (ret != 0) {
2743d3b0591SJens Wiklander         goto cleanup;
275*32b31808SJens Wiklander     }
2763d3b0591SJens Wiklander 
2773d3b0591SJens Wiklander     ret = mbedtls_chachapoly_update(ctx, length, input, output);
278*32b31808SJens Wiklander     if (ret != 0) {
2793d3b0591SJens Wiklander         goto cleanup;
280*32b31808SJens Wiklander     }
2813d3b0591SJens Wiklander 
2823d3b0591SJens Wiklander     ret = mbedtls_chachapoly_finish(ctx, tag);
2833d3b0591SJens Wiklander 
2843d3b0591SJens Wiklander cleanup:
285*32b31808SJens Wiklander     return ret;
2863d3b0591SJens Wiklander }
2873d3b0591SJens Wiklander 
2883d3b0591SJens Wiklander int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
2893d3b0591SJens Wiklander                                        size_t length,
2903d3b0591SJens Wiklander                                        const unsigned char nonce[12],
2913d3b0591SJens Wiklander                                        const unsigned char *aad,
2923d3b0591SJens Wiklander                                        size_t aad_len,
2933d3b0591SJens Wiklander                                        const unsigned char *input,
2943d3b0591SJens Wiklander                                        unsigned char *output,
2953d3b0591SJens Wiklander                                        unsigned char tag[16])
2963d3b0591SJens Wiklander {
297*32b31808SJens Wiklander     return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
2983d3b0591SJens Wiklander                                     length, nonce, aad, aad_len,
299*32b31808SJens Wiklander                                     input, output, tag);
3003d3b0591SJens Wiklander }
3013d3b0591SJens Wiklander 
3023d3b0591SJens Wiklander int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
3033d3b0591SJens Wiklander                                     size_t length,
3043d3b0591SJens Wiklander                                     const unsigned char nonce[12],
3053d3b0591SJens Wiklander                                     const unsigned char *aad,
3063d3b0591SJens Wiklander                                     size_t aad_len,
3073d3b0591SJens Wiklander                                     const unsigned char tag[16],
3083d3b0591SJens Wiklander                                     const unsigned char *input,
3093d3b0591SJens Wiklander                                     unsigned char *output)
3103d3b0591SJens Wiklander {
31111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3123d3b0591SJens Wiklander     unsigned char check_tag[16];
3133d3b0591SJens Wiklander     size_t i;
3143d3b0591SJens Wiklander     int diff;
3153d3b0591SJens Wiklander 
3163d3b0591SJens Wiklander     if ((ret = chachapoly_crypt_and_tag(ctx,
3173d3b0591SJens Wiklander                                         MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
318*32b31808SJens Wiklander                                         aad, aad_len, input, output, check_tag)) != 0) {
319*32b31808SJens Wiklander         return ret;
3203d3b0591SJens Wiklander     }
3213d3b0591SJens Wiklander 
3223d3b0591SJens Wiklander     /* Check tag in "constant-time" */
323*32b31808SJens Wiklander     for (diff = 0, i = 0; i < sizeof(check_tag); i++) {
3243d3b0591SJens Wiklander         diff |= tag[i] ^ check_tag[i];
3253d3b0591SJens Wiklander     }
3263d3b0591SJens Wiklander 
327*32b31808SJens Wiklander     if (diff != 0) {
328*32b31808SJens Wiklander         mbedtls_platform_zeroize(output, length);
329*32b31808SJens Wiklander         return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
330*32b31808SJens Wiklander     }
331*32b31808SJens Wiklander 
332*32b31808SJens Wiklander     return 0;
3333d3b0591SJens Wiklander }
3343d3b0591SJens Wiklander 
3353d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_ALT */
3363d3b0591SJens Wiklander 
3373d3b0591SJens Wiklander #if defined(MBEDTLS_SELF_TEST)
3383d3b0591SJens Wiklander 
3393d3b0591SJens Wiklander static const unsigned char test_key[1][32] =
3403d3b0591SJens Wiklander {
3413d3b0591SJens Wiklander     {
3423d3b0591SJens Wiklander         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
3433d3b0591SJens Wiklander         0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
3443d3b0591SJens Wiklander         0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
3453d3b0591SJens Wiklander         0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
3463d3b0591SJens Wiklander     }
3473d3b0591SJens Wiklander };
3483d3b0591SJens Wiklander 
3493d3b0591SJens Wiklander static const unsigned char test_nonce[1][12] =
3503d3b0591SJens Wiklander {
3513d3b0591SJens Wiklander     {
3523d3b0591SJens Wiklander         0x07, 0x00, 0x00, 0x00,                         /* 32-bit common part */
3533d3b0591SJens Wiklander         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47  /* 64-bit IV */
3543d3b0591SJens Wiklander     }
3553d3b0591SJens Wiklander };
3563d3b0591SJens Wiklander 
3573d3b0591SJens Wiklander static const unsigned char test_aad[1][12] =
3583d3b0591SJens Wiklander {
3593d3b0591SJens Wiklander     {
3603d3b0591SJens Wiklander         0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
3613d3b0591SJens Wiklander         0xc4, 0xc5, 0xc6, 0xc7
3623d3b0591SJens Wiklander     }
3633d3b0591SJens Wiklander };
3643d3b0591SJens Wiklander 
3653d3b0591SJens Wiklander static const size_t test_aad_len[1] =
3663d3b0591SJens Wiklander {
3673d3b0591SJens Wiklander     12U
3683d3b0591SJens Wiklander };
3693d3b0591SJens Wiklander 
3703d3b0591SJens Wiklander static const unsigned char test_input[1][114] =
3713d3b0591SJens Wiklander {
3723d3b0591SJens Wiklander     {
3733d3b0591SJens Wiklander         0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
3743d3b0591SJens Wiklander         0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
3753d3b0591SJens Wiklander         0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
3763d3b0591SJens Wiklander         0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
3773d3b0591SJens Wiklander         0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
3783d3b0591SJens Wiklander         0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
3793d3b0591SJens Wiklander         0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
3803d3b0591SJens Wiklander         0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
3813d3b0591SJens Wiklander         0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
3823d3b0591SJens Wiklander         0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
3833d3b0591SJens Wiklander         0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
3843d3b0591SJens Wiklander         0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
3853d3b0591SJens Wiklander         0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
3863d3b0591SJens Wiklander         0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
3873d3b0591SJens Wiklander         0x74, 0x2e
3883d3b0591SJens Wiklander     }
3893d3b0591SJens Wiklander };
3903d3b0591SJens Wiklander 
3913d3b0591SJens Wiklander static const unsigned char test_output[1][114] =
3923d3b0591SJens Wiklander {
3933d3b0591SJens Wiklander     {
3943d3b0591SJens Wiklander         0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
3953d3b0591SJens Wiklander         0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
3963d3b0591SJens Wiklander         0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
3973d3b0591SJens Wiklander         0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
3983d3b0591SJens Wiklander         0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
3993d3b0591SJens Wiklander         0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
4003d3b0591SJens Wiklander         0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
4013d3b0591SJens Wiklander         0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
4023d3b0591SJens Wiklander         0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
4033d3b0591SJens Wiklander         0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
4043d3b0591SJens Wiklander         0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
4053d3b0591SJens Wiklander         0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
4063d3b0591SJens Wiklander         0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
4073d3b0591SJens Wiklander         0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
4083d3b0591SJens Wiklander         0x61, 0x16
4093d3b0591SJens Wiklander     }
4103d3b0591SJens Wiklander };
4113d3b0591SJens Wiklander 
4123d3b0591SJens Wiklander static const size_t test_input_len[1] =
4133d3b0591SJens Wiklander {
4143d3b0591SJens Wiklander     114U
4153d3b0591SJens Wiklander };
4163d3b0591SJens Wiklander 
4173d3b0591SJens Wiklander static const unsigned char test_mac[1][16] =
4183d3b0591SJens Wiklander {
4193d3b0591SJens Wiklander     {
4203d3b0591SJens Wiklander         0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
4213d3b0591SJens Wiklander         0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
4223d3b0591SJens Wiklander     }
4233d3b0591SJens Wiklander };
4243d3b0591SJens Wiklander 
4257901324dSJerome Forissier /* Make sure no other definition is already present. */
4267901324dSJerome Forissier #undef ASSERT
4277901324dSJerome Forissier 
4283d3b0591SJens Wiklander #define ASSERT(cond, args)            \
4293d3b0591SJens Wiklander     do                                  \
4303d3b0591SJens Wiklander     {                                   \
4313d3b0591SJens Wiklander         if (!(cond))                \
4323d3b0591SJens Wiklander         {                               \
4333d3b0591SJens Wiklander             if (verbose != 0)          \
4343d3b0591SJens Wiklander             mbedtls_printf args;    \
4353d3b0591SJens Wiklander                                         \
436*32b31808SJens Wiklander             return -1;               \
4373d3b0591SJens Wiklander         }                               \
4383d3b0591SJens Wiklander     }                                   \
4393d3b0591SJens Wiklander     while (0)
4403d3b0591SJens Wiklander 
4413d3b0591SJens Wiklander int mbedtls_chachapoly_self_test(int verbose)
4423d3b0591SJens Wiklander {
4433d3b0591SJens Wiklander     mbedtls_chachapoly_context ctx;
4443d3b0591SJens Wiklander     unsigned i;
44511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4463d3b0591SJens Wiklander     unsigned char output[200];
4473d3b0591SJens Wiklander     unsigned char mac[16];
4483d3b0591SJens Wiklander 
449*32b31808SJens Wiklander     for (i = 0U; i < 1U; i++) {
450*32b31808SJens Wiklander         if (verbose != 0) {
4513d3b0591SJens Wiklander             mbedtls_printf("  ChaCha20-Poly1305 test %u ", i);
452*32b31808SJens Wiklander         }
4533d3b0591SJens Wiklander 
4543d3b0591SJens Wiklander         mbedtls_chachapoly_init(&ctx);
4553d3b0591SJens Wiklander 
4563d3b0591SJens Wiklander         ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
4573d3b0591SJens Wiklander         ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
4583d3b0591SJens Wiklander 
4593d3b0591SJens Wiklander         ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
4603d3b0591SJens Wiklander                                                  test_input_len[i],
4613d3b0591SJens Wiklander                                                  test_nonce[i],
4623d3b0591SJens Wiklander                                                  test_aad[i],
4633d3b0591SJens Wiklander                                                  test_aad_len[i],
4643d3b0591SJens Wiklander                                                  test_input[i],
4653d3b0591SJens Wiklander                                                  output,
4663d3b0591SJens Wiklander                                                  mac);
4673d3b0591SJens Wiklander 
4683d3b0591SJens Wiklander         ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
4693d3b0591SJens Wiklander 
4703d3b0591SJens Wiklander         ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
4713d3b0591SJens Wiklander                ("failure (wrong output)\n"));
4723d3b0591SJens Wiklander 
4733d3b0591SJens Wiklander         ASSERT(0 == memcmp(mac, test_mac[i], 16U),
4743d3b0591SJens Wiklander                ("failure (wrong MAC)\n"));
4753d3b0591SJens Wiklander 
4763d3b0591SJens Wiklander         mbedtls_chachapoly_free(&ctx);
4773d3b0591SJens Wiklander 
478*32b31808SJens Wiklander         if (verbose != 0) {
4793d3b0591SJens Wiklander             mbedtls_printf("passed\n");
4803d3b0591SJens Wiklander         }
481*32b31808SJens Wiklander     }
4823d3b0591SJens Wiklander 
483*32b31808SJens Wiklander     if (verbose != 0) {
4843d3b0591SJens Wiklander         mbedtls_printf("\n");
485*32b31808SJens Wiklander     }
4863d3b0591SJens Wiklander 
487*32b31808SJens Wiklander     return 0;
4883d3b0591SJens Wiklander }
4893d3b0591SJens Wiklander 
4903d3b0591SJens Wiklander #endif /* MBEDTLS_SELF_TEST */
4913d3b0591SJens Wiklander 
4923d3b0591SJens Wiklander #endif /* MBEDTLS_CHACHAPOLY_C */
493