xref: /optee_os/lib/libmbedtls/mbedtls/library/chacha20.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
13d3b0591SJens Wiklander /**
23d3b0591SJens Wiklander  * \file chacha20.c
33d3b0591SJens Wiklander  *
43d3b0591SJens Wiklander  * \brief ChaCha20 cipher.
53d3b0591SJens Wiklander  *
63d3b0591SJens Wiklander  * \author Daniel King <damaki.gh@gmail.com>
73d3b0591SJens Wiklander  *
87901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
97901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
103d3b0591SJens Wiklander  *
113d3b0591SJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
123d3b0591SJens Wiklander  *  not use this file except in compliance with the License.
133d3b0591SJens Wiklander  *  You may obtain a copy of the License at
143d3b0591SJens Wiklander  *
153d3b0591SJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
163d3b0591SJens Wiklander  *
173d3b0591SJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
183d3b0591SJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
193d3b0591SJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
203d3b0591SJens Wiklander  *  See the License for the specific language governing permissions and
213d3b0591SJens Wiklander  *  limitations under the License.
223d3b0591SJens Wiklander  */
233d3b0591SJens Wiklander 
247901324dSJerome Forissier #include "common.h"
253d3b0591SJens Wiklander 
263d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C)
273d3b0591SJens Wiklander 
283d3b0591SJens Wiklander #include "mbedtls/chacha20.h"
293d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
3011fa71b9SJerome Forissier #include "mbedtls/error.h"
313d3b0591SJens Wiklander 
323d3b0591SJens Wiklander #include <stddef.h>
333d3b0591SJens Wiklander #include <string.h>
343d3b0591SJens Wiklander 
353d3b0591SJens Wiklander #include "mbedtls/platform.h"
363d3b0591SJens Wiklander 
373d3b0591SJens Wiklander #if !defined(MBEDTLS_CHACHA20_ALT)
383d3b0591SJens Wiklander 
393d3b0591SJens Wiklander #define ROTL32(value, amount) \
405b25c76aSJerome Forissier     ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
413d3b0591SJens Wiklander 
423d3b0591SJens Wiklander #define CHACHA20_CTR_INDEX (12U)
433d3b0591SJens Wiklander 
443d3b0591SJens Wiklander #define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
453d3b0591SJens Wiklander 
463d3b0591SJens Wiklander /**
473d3b0591SJens Wiklander  * \brief           ChaCha20 quarter round operation.
483d3b0591SJens Wiklander  *
493d3b0591SJens Wiklander  *                  The quarter round is defined as follows (from RFC 7539):
503d3b0591SJens Wiklander  *                      1.  a += b; d ^= a; d <<<= 16;
513d3b0591SJens Wiklander  *                      2.  c += d; b ^= c; b <<<= 12;
523d3b0591SJens Wiklander  *                      3.  a += b; d ^= a; d <<<= 8;
533d3b0591SJens Wiklander  *                      4.  c += d; b ^= c; b <<<= 7;
543d3b0591SJens Wiklander  *
553d3b0591SJens Wiklander  * \param state     ChaCha20 state to modify.
563d3b0591SJens Wiklander  * \param a         The index of 'a' in the state.
573d3b0591SJens Wiklander  * \param b         The index of 'b' in the state.
583d3b0591SJens Wiklander  * \param c         The index of 'c' in the state.
593d3b0591SJens Wiklander  * \param d         The index of 'd' in the state.
603d3b0591SJens Wiklander  */
613d3b0591SJens Wiklander static inline void chacha20_quarter_round(uint32_t state[16],
623d3b0591SJens Wiklander                                           size_t a,
633d3b0591SJens Wiklander                                           size_t b,
643d3b0591SJens Wiklander                                           size_t c,
653d3b0591SJens Wiklander                                           size_t d)
663d3b0591SJens Wiklander {
673d3b0591SJens Wiklander     /* a += b; d ^= a; d <<<= 16; */
683d3b0591SJens Wiklander     state[a] += state[b];
693d3b0591SJens Wiklander     state[d] ^= state[a];
703d3b0591SJens Wiklander     state[d] = ROTL32(state[d], 16);
713d3b0591SJens Wiklander 
723d3b0591SJens Wiklander     /* c += d; b ^= c; b <<<= 12 */
733d3b0591SJens Wiklander     state[c] += state[d];
743d3b0591SJens Wiklander     state[b] ^= state[c];
753d3b0591SJens Wiklander     state[b] = ROTL32(state[b], 12);
763d3b0591SJens Wiklander 
773d3b0591SJens Wiklander     /* a += b; d ^= a; d <<<= 8; */
783d3b0591SJens Wiklander     state[a] += state[b];
793d3b0591SJens Wiklander     state[d] ^= state[a];
803d3b0591SJens Wiklander     state[d] = ROTL32(state[d], 8);
813d3b0591SJens Wiklander 
823d3b0591SJens Wiklander     /* c += d; b ^= c; b <<<= 7; */
833d3b0591SJens Wiklander     state[c] += state[d];
843d3b0591SJens Wiklander     state[b] ^= state[c];
853d3b0591SJens Wiklander     state[b] = ROTL32(state[b], 7);
863d3b0591SJens Wiklander }
873d3b0591SJens Wiklander 
883d3b0591SJens Wiklander /**
893d3b0591SJens Wiklander  * \brief           Perform the ChaCha20 inner block operation.
903d3b0591SJens Wiklander  *
913d3b0591SJens Wiklander  *                  This function performs two rounds: the column round and the
923d3b0591SJens Wiklander  *                  diagonal round.
933d3b0591SJens Wiklander  *
943d3b0591SJens Wiklander  * \param state     The ChaCha20 state to update.
953d3b0591SJens Wiklander  */
963d3b0591SJens Wiklander static void chacha20_inner_block(uint32_t state[16])
973d3b0591SJens Wiklander {
983d3b0591SJens Wiklander     chacha20_quarter_round(state, 0, 4, 8,  12);
993d3b0591SJens Wiklander     chacha20_quarter_round(state, 1, 5, 9,  13);
1003d3b0591SJens Wiklander     chacha20_quarter_round(state, 2, 6, 10, 14);
1013d3b0591SJens Wiklander     chacha20_quarter_round(state, 3, 7, 11, 15);
1023d3b0591SJens Wiklander 
1033d3b0591SJens Wiklander     chacha20_quarter_round(state, 0, 5, 10, 15);
1043d3b0591SJens Wiklander     chacha20_quarter_round(state, 1, 6, 11, 12);
1053d3b0591SJens Wiklander     chacha20_quarter_round(state, 2, 7, 8,  13);
1063d3b0591SJens Wiklander     chacha20_quarter_round(state, 3, 4, 9,  14);
1073d3b0591SJens Wiklander }
1083d3b0591SJens Wiklander 
1093d3b0591SJens Wiklander /**
1103d3b0591SJens Wiklander  * \brief               Generates a keystream block.
1113d3b0591SJens Wiklander  *
1123d3b0591SJens Wiklander  * \param initial_state The initial ChaCha20 state (key, nonce, counter).
1133d3b0591SJens Wiklander  * \param keystream     Generated keystream bytes are written to this buffer.
1143d3b0591SJens Wiklander  */
1153d3b0591SJens Wiklander static void chacha20_block(const uint32_t initial_state[16],
1163d3b0591SJens Wiklander                            unsigned char keystream[64])
1173d3b0591SJens Wiklander {
1183d3b0591SJens Wiklander     uint32_t working_state[16];
1193d3b0591SJens Wiklander     size_t i;
1203d3b0591SJens Wiklander 
1213d3b0591SJens Wiklander     memcpy(working_state,
1223d3b0591SJens Wiklander            initial_state,
1233d3b0591SJens Wiklander            CHACHA20_BLOCK_SIZE_BYTES);
1243d3b0591SJens Wiklander 
125*32b31808SJens Wiklander     for (i = 0U; i < 10U; i++) {
1263d3b0591SJens Wiklander         chacha20_inner_block(working_state);
127*32b31808SJens Wiklander     }
1283d3b0591SJens Wiklander 
1293d3b0591SJens Wiklander     working_state[0] += initial_state[0];
1303d3b0591SJens Wiklander     working_state[1] += initial_state[1];
1313d3b0591SJens Wiklander     working_state[2] += initial_state[2];
1323d3b0591SJens Wiklander     working_state[3] += initial_state[3];
1333d3b0591SJens Wiklander     working_state[4] += initial_state[4];
1343d3b0591SJens Wiklander     working_state[5] += initial_state[5];
1353d3b0591SJens Wiklander     working_state[6] += initial_state[6];
1363d3b0591SJens Wiklander     working_state[7] += initial_state[7];
1373d3b0591SJens Wiklander     working_state[8] += initial_state[8];
1383d3b0591SJens Wiklander     working_state[9] += initial_state[9];
1393d3b0591SJens Wiklander     working_state[10] += initial_state[10];
1403d3b0591SJens Wiklander     working_state[11] += initial_state[11];
1413d3b0591SJens Wiklander     working_state[12] += initial_state[12];
1423d3b0591SJens Wiklander     working_state[13] += initial_state[13];
1433d3b0591SJens Wiklander     working_state[14] += initial_state[14];
1443d3b0591SJens Wiklander     working_state[15] += initial_state[15];
1453d3b0591SJens Wiklander 
146*32b31808SJens Wiklander     for (i = 0U; i < 16; i++) {
1473d3b0591SJens Wiklander         size_t offset = i * 4U;
1483d3b0591SJens Wiklander 
149039e02dfSJerome Forissier         MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
1503d3b0591SJens Wiklander     }
1513d3b0591SJens Wiklander 
1523d3b0591SJens Wiklander     mbedtls_platform_zeroize(working_state, sizeof(working_state));
1533d3b0591SJens Wiklander }
1543d3b0591SJens Wiklander 
1553d3b0591SJens Wiklander void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
1563d3b0591SJens Wiklander {
1573d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
1583d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
1593d3b0591SJens Wiklander 
1603d3b0591SJens Wiklander     /* Initially, there's no keystream bytes available */
1613d3b0591SJens Wiklander     ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
1623d3b0591SJens Wiklander }
1633d3b0591SJens Wiklander 
1643d3b0591SJens Wiklander void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
1653d3b0591SJens Wiklander {
166*32b31808SJens Wiklander     if (ctx != NULL) {
1673d3b0591SJens Wiklander         mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
1683d3b0591SJens Wiklander     }
1693d3b0591SJens Wiklander }
1703d3b0591SJens Wiklander 
1713d3b0591SJens Wiklander int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
1723d3b0591SJens Wiklander                             const unsigned char key[32])
1733d3b0591SJens Wiklander {
1743d3b0591SJens Wiklander     /* ChaCha20 constants - the string "expand 32-byte k" */
1753d3b0591SJens Wiklander     ctx->state[0] = 0x61707865;
1763d3b0591SJens Wiklander     ctx->state[1] = 0x3320646e;
1773d3b0591SJens Wiklander     ctx->state[2] = 0x79622d32;
1783d3b0591SJens Wiklander     ctx->state[3] = 0x6b206574;
1793d3b0591SJens Wiklander 
1803d3b0591SJens Wiklander     /* Set key */
181039e02dfSJerome Forissier     ctx->state[4]  = MBEDTLS_GET_UINT32_LE(key, 0);
182039e02dfSJerome Forissier     ctx->state[5]  = MBEDTLS_GET_UINT32_LE(key, 4);
183039e02dfSJerome Forissier     ctx->state[6]  = MBEDTLS_GET_UINT32_LE(key, 8);
184039e02dfSJerome Forissier     ctx->state[7]  = MBEDTLS_GET_UINT32_LE(key, 12);
185039e02dfSJerome Forissier     ctx->state[8]  = MBEDTLS_GET_UINT32_LE(key, 16);
186039e02dfSJerome Forissier     ctx->state[9]  = MBEDTLS_GET_UINT32_LE(key, 20);
187039e02dfSJerome Forissier     ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24);
188039e02dfSJerome Forissier     ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28);
1893d3b0591SJens Wiklander 
190*32b31808SJens Wiklander     return 0;
1913d3b0591SJens Wiklander }
1923d3b0591SJens Wiklander 
1933d3b0591SJens Wiklander int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
1943d3b0591SJens Wiklander                             const unsigned char nonce[12],
1953d3b0591SJens Wiklander                             uint32_t counter)
1963d3b0591SJens Wiklander {
1973d3b0591SJens Wiklander     /* Counter */
1983d3b0591SJens Wiklander     ctx->state[12] = counter;
1993d3b0591SJens Wiklander 
2003d3b0591SJens Wiklander     /* Nonce */
201039e02dfSJerome Forissier     ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0);
202039e02dfSJerome Forissier     ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4);
203039e02dfSJerome Forissier     ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8);
2043d3b0591SJens Wiklander 
2053d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
2063d3b0591SJens Wiklander 
2073d3b0591SJens Wiklander     /* Initially, there's no keystream bytes available */
2083d3b0591SJens Wiklander     ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
2093d3b0591SJens Wiklander 
210*32b31808SJens Wiklander     return 0;
2113d3b0591SJens Wiklander }
2123d3b0591SJens Wiklander 
2133d3b0591SJens Wiklander int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
2143d3b0591SJens Wiklander                             size_t size,
2153d3b0591SJens Wiklander                             const unsigned char *input,
2163d3b0591SJens Wiklander                             unsigned char *output)
2173d3b0591SJens Wiklander {
2183d3b0591SJens Wiklander     size_t offset = 0U;
2193d3b0591SJens Wiklander 
2203d3b0591SJens Wiklander     /* Use leftover keystream bytes, if available */
221*32b31808SJens Wiklander     while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
2223d3b0591SJens Wiklander         output[offset] = input[offset]
2233d3b0591SJens Wiklander                          ^ ctx->keystream8[ctx->keystream_bytes_used];
2243d3b0591SJens Wiklander 
2253d3b0591SJens Wiklander         ctx->keystream_bytes_used++;
2263d3b0591SJens Wiklander         offset++;
2273d3b0591SJens Wiklander         size--;
2283d3b0591SJens Wiklander     }
2293d3b0591SJens Wiklander 
2303d3b0591SJens Wiklander     /* Process full blocks */
231*32b31808SJens Wiklander     while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
2323d3b0591SJens Wiklander         /* Generate new keystream block and increment counter */
2333d3b0591SJens Wiklander         chacha20_block(ctx->state, ctx->keystream8);
2343d3b0591SJens Wiklander         ctx->state[CHACHA20_CTR_INDEX]++;
2353d3b0591SJens Wiklander 
236*32b31808SJens Wiklander         mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U);
2373d3b0591SJens Wiklander 
2383d3b0591SJens Wiklander         offset += CHACHA20_BLOCK_SIZE_BYTES;
2393d3b0591SJens Wiklander         size   -= CHACHA20_BLOCK_SIZE_BYTES;
2403d3b0591SJens Wiklander     }
2413d3b0591SJens Wiklander 
2423d3b0591SJens Wiklander     /* Last (partial) block */
243*32b31808SJens Wiklander     if (size > 0U) {
2443d3b0591SJens Wiklander         /* Generate new keystream block and increment counter */
2453d3b0591SJens Wiklander         chacha20_block(ctx->state, ctx->keystream8);
2463d3b0591SJens Wiklander         ctx->state[CHACHA20_CTR_INDEX]++;
2473d3b0591SJens Wiklander 
248*32b31808SJens Wiklander         mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);
2493d3b0591SJens Wiklander 
2503d3b0591SJens Wiklander         ctx->keystream_bytes_used = size;
2513d3b0591SJens Wiklander 
2523d3b0591SJens Wiklander     }
2533d3b0591SJens Wiklander 
254*32b31808SJens Wiklander     return 0;
2553d3b0591SJens Wiklander }
2563d3b0591SJens Wiklander 
2573d3b0591SJens Wiklander int mbedtls_chacha20_crypt(const unsigned char key[32],
2583d3b0591SJens Wiklander                            const unsigned char nonce[12],
2593d3b0591SJens Wiklander                            uint32_t counter,
2603d3b0591SJens Wiklander                            size_t data_len,
2613d3b0591SJens Wiklander                            const unsigned char *input,
2623d3b0591SJens Wiklander                            unsigned char *output)
2633d3b0591SJens Wiklander {
2643d3b0591SJens Wiklander     mbedtls_chacha20_context ctx;
26511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2663d3b0591SJens Wiklander 
2673d3b0591SJens Wiklander     mbedtls_chacha20_init(&ctx);
2683d3b0591SJens Wiklander 
2693d3b0591SJens Wiklander     ret = mbedtls_chacha20_setkey(&ctx, key);
270*32b31808SJens Wiklander     if (ret != 0) {
2713d3b0591SJens Wiklander         goto cleanup;
272*32b31808SJens Wiklander     }
2733d3b0591SJens Wiklander 
2743d3b0591SJens Wiklander     ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
275*32b31808SJens Wiklander     if (ret != 0) {
2763d3b0591SJens Wiklander         goto cleanup;
277*32b31808SJens Wiklander     }
2783d3b0591SJens Wiklander 
2793d3b0591SJens Wiklander     ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
2803d3b0591SJens Wiklander 
2813d3b0591SJens Wiklander cleanup:
2823d3b0591SJens Wiklander     mbedtls_chacha20_free(&ctx);
283*32b31808SJens Wiklander     return ret;
2843d3b0591SJens Wiklander }
2853d3b0591SJens Wiklander 
2863d3b0591SJens Wiklander #endif /* !MBEDTLS_CHACHA20_ALT */
2873d3b0591SJens Wiklander 
2883d3b0591SJens Wiklander #if defined(MBEDTLS_SELF_TEST)
2893d3b0591SJens Wiklander 
2903d3b0591SJens Wiklander static const unsigned char test_keys[2][32] =
2913d3b0591SJens Wiklander {
2923d3b0591SJens Wiklander     {
2933d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2943d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2953d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2963d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2973d3b0591SJens Wiklander     },
2983d3b0591SJens Wiklander     {
2993d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3003d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3013d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3023d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
3033d3b0591SJens Wiklander     }
3043d3b0591SJens Wiklander };
3053d3b0591SJens Wiklander 
3063d3b0591SJens Wiklander static const unsigned char test_nonces[2][12] =
3073d3b0591SJens Wiklander {
3083d3b0591SJens Wiklander     {
3093d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3103d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00
3113d3b0591SJens Wiklander     },
3123d3b0591SJens Wiklander     {
3133d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3143d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x02
3153d3b0591SJens Wiklander     }
3163d3b0591SJens Wiklander };
3173d3b0591SJens Wiklander 
3183d3b0591SJens Wiklander static const uint32_t test_counters[2] =
3193d3b0591SJens Wiklander {
3203d3b0591SJens Wiklander     0U,
3213d3b0591SJens Wiklander     1U
3223d3b0591SJens Wiklander };
3233d3b0591SJens Wiklander 
3243d3b0591SJens Wiklander static const unsigned char test_input[2][375] =
3253d3b0591SJens Wiklander {
3263d3b0591SJens Wiklander     {
3273d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3283d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3293d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3303d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3313d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3323d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3333d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3343d3b0591SJens Wiklander         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3353d3b0591SJens Wiklander     },
3363d3b0591SJens Wiklander     {
3373d3b0591SJens Wiklander         0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
3383d3b0591SJens Wiklander         0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
3393d3b0591SJens Wiklander         0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
3403d3b0591SJens Wiklander         0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
3413d3b0591SJens Wiklander         0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
3423d3b0591SJens Wiklander         0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
3433d3b0591SJens Wiklander         0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
3443d3b0591SJens Wiklander         0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
3453d3b0591SJens Wiklander         0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
3463d3b0591SJens Wiklander         0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
3473d3b0591SJens Wiklander         0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
3483d3b0591SJens Wiklander         0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
3493d3b0591SJens Wiklander         0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3503d3b0591SJens Wiklander         0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
3513d3b0591SJens Wiklander         0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
3523d3b0591SJens Wiklander         0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
3533d3b0591SJens Wiklander         0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
3543d3b0591SJens Wiklander         0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
3553d3b0591SJens Wiklander         0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
3563d3b0591SJens Wiklander         0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
3573d3b0591SJens Wiklander         0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
3583d3b0591SJens Wiklander         0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
3593d3b0591SJens Wiklander         0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
3603d3b0591SJens Wiklander         0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
3613d3b0591SJens Wiklander         0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
3623d3b0591SJens Wiklander         0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
3633d3b0591SJens Wiklander         0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
3643d3b0591SJens Wiklander         0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
3653d3b0591SJens Wiklander         0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
3663d3b0591SJens Wiklander         0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
3673d3b0591SJens Wiklander         0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
3683d3b0591SJens Wiklander         0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
3693d3b0591SJens Wiklander         0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
3703d3b0591SJens Wiklander         0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
3713d3b0591SJens Wiklander         0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
3723d3b0591SJens Wiklander         0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
3733d3b0591SJens Wiklander         0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
3743d3b0591SJens Wiklander         0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
3753d3b0591SJens Wiklander         0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
3763d3b0591SJens Wiklander         0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
3773d3b0591SJens Wiklander         0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
3783d3b0591SJens Wiklander         0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
3793d3b0591SJens Wiklander         0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
3803d3b0591SJens Wiklander         0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
3813d3b0591SJens Wiklander         0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
3823d3b0591SJens Wiklander         0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
3833d3b0591SJens Wiklander         0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
3843d3b0591SJens Wiklander     }
3853d3b0591SJens Wiklander };
3863d3b0591SJens Wiklander 
3873d3b0591SJens Wiklander static const unsigned char test_output[2][375] =
3883d3b0591SJens Wiklander {
3893d3b0591SJens Wiklander     {
3903d3b0591SJens Wiklander         0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
3913d3b0591SJens Wiklander         0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
3923d3b0591SJens Wiklander         0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
3933d3b0591SJens Wiklander         0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
3943d3b0591SJens Wiklander         0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
3953d3b0591SJens Wiklander         0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
3963d3b0591SJens Wiklander         0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
3973d3b0591SJens Wiklander         0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
3983d3b0591SJens Wiklander     },
3993d3b0591SJens Wiklander     {
4003d3b0591SJens Wiklander         0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
4013d3b0591SJens Wiklander         0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
4023d3b0591SJens Wiklander         0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
4033d3b0591SJens Wiklander         0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
4043d3b0591SJens Wiklander         0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
4053d3b0591SJens Wiklander         0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
4063d3b0591SJens Wiklander         0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
4073d3b0591SJens Wiklander         0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
4083d3b0591SJens Wiklander         0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
4093d3b0591SJens Wiklander         0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
4103d3b0591SJens Wiklander         0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
4113d3b0591SJens Wiklander         0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
4123d3b0591SJens Wiklander         0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
4133d3b0591SJens Wiklander         0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
4143d3b0591SJens Wiklander         0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
4153d3b0591SJens Wiklander         0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
4163d3b0591SJens Wiklander         0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
4173d3b0591SJens Wiklander         0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
4183d3b0591SJens Wiklander         0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
4193d3b0591SJens Wiklander         0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
4203d3b0591SJens Wiklander         0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
4213d3b0591SJens Wiklander         0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
4223d3b0591SJens Wiklander         0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
4233d3b0591SJens Wiklander         0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
4243d3b0591SJens Wiklander         0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
4253d3b0591SJens Wiklander         0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
4263d3b0591SJens Wiklander         0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
4273d3b0591SJens Wiklander         0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
4283d3b0591SJens Wiklander         0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
4293d3b0591SJens Wiklander         0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
4303d3b0591SJens Wiklander         0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
4313d3b0591SJens Wiklander         0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
4323d3b0591SJens Wiklander         0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
4333d3b0591SJens Wiklander         0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
4343d3b0591SJens Wiklander         0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
4353d3b0591SJens Wiklander         0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
4363d3b0591SJens Wiklander         0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
4373d3b0591SJens Wiklander         0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
4383d3b0591SJens Wiklander         0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
4393d3b0591SJens Wiklander         0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
4403d3b0591SJens Wiklander         0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
4413d3b0591SJens Wiklander         0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
4423d3b0591SJens Wiklander         0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
4433d3b0591SJens Wiklander         0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
4443d3b0591SJens Wiklander         0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
4453d3b0591SJens Wiklander         0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
4463d3b0591SJens Wiklander         0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
4473d3b0591SJens Wiklander     }
4483d3b0591SJens Wiklander };
4493d3b0591SJens Wiklander 
4503d3b0591SJens Wiklander static const size_t test_lengths[2] =
4513d3b0591SJens Wiklander {
4523d3b0591SJens Wiklander     64U,
4533d3b0591SJens Wiklander     375U
4543d3b0591SJens Wiklander };
4553d3b0591SJens Wiklander 
4567901324dSJerome Forissier /* Make sure no other definition is already present. */
4577901324dSJerome Forissier #undef ASSERT
4587901324dSJerome Forissier 
4593d3b0591SJens Wiklander #define ASSERT(cond, args)            \
4603d3b0591SJens Wiklander     do                                  \
4613d3b0591SJens Wiklander     {                                   \
4623d3b0591SJens Wiklander         if (!(cond))                \
4633d3b0591SJens Wiklander         {                               \
4643d3b0591SJens Wiklander             if (verbose != 0)          \
4653d3b0591SJens Wiklander             mbedtls_printf args;    \
4663d3b0591SJens Wiklander                                         \
467*32b31808SJens Wiklander             return -1;               \
4683d3b0591SJens Wiklander         }                               \
4693d3b0591SJens Wiklander     }                                   \
4703d3b0591SJens Wiklander     while (0)
4713d3b0591SJens Wiklander 
4723d3b0591SJens Wiklander int mbedtls_chacha20_self_test(int verbose)
4733d3b0591SJens Wiklander {
4743d3b0591SJens Wiklander     unsigned char output[381];
4753d3b0591SJens Wiklander     unsigned i;
47611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4773d3b0591SJens Wiklander 
478*32b31808SJens Wiklander     for (i = 0U; i < 2U; i++) {
479*32b31808SJens Wiklander         if (verbose != 0) {
4803d3b0591SJens Wiklander             mbedtls_printf("  ChaCha20 test %u ", i);
481*32b31808SJens Wiklander         }
4823d3b0591SJens Wiklander 
4833d3b0591SJens Wiklander         ret = mbedtls_chacha20_crypt(test_keys[i],
4843d3b0591SJens Wiklander                                      test_nonces[i],
4853d3b0591SJens Wiklander                                      test_counters[i],
4863d3b0591SJens Wiklander                                      test_lengths[i],
4873d3b0591SJens Wiklander                                      test_input[i],
4883d3b0591SJens Wiklander                                      output);
4893d3b0591SJens Wiklander 
4903d3b0591SJens Wiklander         ASSERT(0 == ret, ("error code: %i\n", ret));
4913d3b0591SJens Wiklander 
4923d3b0591SJens Wiklander         ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
4933d3b0591SJens Wiklander                ("failed (output)\n"));
4943d3b0591SJens Wiklander 
495*32b31808SJens Wiklander         if (verbose != 0) {
4963d3b0591SJens Wiklander             mbedtls_printf("passed\n");
4973d3b0591SJens Wiklander         }
498*32b31808SJens Wiklander     }
4993d3b0591SJens Wiklander 
500*32b31808SJens Wiklander     if (verbose != 0) {
5013d3b0591SJens Wiklander         mbedtls_printf("\n");
502*32b31808SJens Wiklander     }
5033d3b0591SJens Wiklander 
504*32b31808SJens Wiklander     return 0;
5053d3b0591SJens Wiklander }
5063d3b0591SJens Wiklander 
5073d3b0591SJens Wiklander #endif /* MBEDTLS_SELF_TEST */
5083d3b0591SJens Wiklander 
5093d3b0591SJens Wiklander #endif /* !MBEDTLS_CHACHA20_C */
510