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
9*b0563631STom Van Eyck * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
103d3b0591SJens Wiklander */
113d3b0591SJens Wiklander
127901324dSJerome Forissier #include "common.h"
133d3b0591SJens Wiklander
143d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C)
153d3b0591SJens Wiklander
163d3b0591SJens Wiklander #include "mbedtls/chacha20.h"
173d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
1811fa71b9SJerome Forissier #include "mbedtls/error.h"
193d3b0591SJens Wiklander
203d3b0591SJens Wiklander #include <stddef.h>
213d3b0591SJens Wiklander #include <string.h>
223d3b0591SJens Wiklander
233d3b0591SJens Wiklander #include "mbedtls/platform.h"
243d3b0591SJens Wiklander
253d3b0591SJens Wiklander #if !defined(MBEDTLS_CHACHA20_ALT)
263d3b0591SJens Wiklander
273d3b0591SJens Wiklander #define ROTL32(value, amount) \
285b25c76aSJerome Forissier ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
293d3b0591SJens Wiklander
303d3b0591SJens Wiklander #define CHACHA20_CTR_INDEX (12U)
313d3b0591SJens Wiklander
323d3b0591SJens Wiklander #define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
333d3b0591SJens Wiklander
343d3b0591SJens Wiklander /**
353d3b0591SJens Wiklander * \brief ChaCha20 quarter round operation.
363d3b0591SJens Wiklander *
373d3b0591SJens Wiklander * The quarter round is defined as follows (from RFC 7539):
383d3b0591SJens Wiklander * 1. a += b; d ^= a; d <<<= 16;
393d3b0591SJens Wiklander * 2. c += d; b ^= c; b <<<= 12;
403d3b0591SJens Wiklander * 3. a += b; d ^= a; d <<<= 8;
413d3b0591SJens Wiklander * 4. c += d; b ^= c; b <<<= 7;
423d3b0591SJens Wiklander *
433d3b0591SJens Wiklander * \param state ChaCha20 state to modify.
443d3b0591SJens Wiklander * \param a The index of 'a' in the state.
453d3b0591SJens Wiklander * \param b The index of 'b' in the state.
463d3b0591SJens Wiklander * \param c The index of 'c' in the state.
473d3b0591SJens Wiklander * \param d The index of 'd' in the state.
483d3b0591SJens Wiklander */
chacha20_quarter_round(uint32_t state[16],size_t a,size_t b,size_t c,size_t d)493d3b0591SJens Wiklander static inline void chacha20_quarter_round(uint32_t state[16],
503d3b0591SJens Wiklander size_t a,
513d3b0591SJens Wiklander size_t b,
523d3b0591SJens Wiklander size_t c,
533d3b0591SJens Wiklander size_t d)
543d3b0591SJens Wiklander {
553d3b0591SJens Wiklander /* a += b; d ^= a; d <<<= 16; */
563d3b0591SJens Wiklander state[a] += state[b];
573d3b0591SJens Wiklander state[d] ^= state[a];
583d3b0591SJens Wiklander state[d] = ROTL32(state[d], 16);
593d3b0591SJens Wiklander
603d3b0591SJens Wiklander /* c += d; b ^= c; b <<<= 12 */
613d3b0591SJens Wiklander state[c] += state[d];
623d3b0591SJens Wiklander state[b] ^= state[c];
633d3b0591SJens Wiklander state[b] = ROTL32(state[b], 12);
643d3b0591SJens Wiklander
653d3b0591SJens Wiklander /* a += b; d ^= a; d <<<= 8; */
663d3b0591SJens Wiklander state[a] += state[b];
673d3b0591SJens Wiklander state[d] ^= state[a];
683d3b0591SJens Wiklander state[d] = ROTL32(state[d], 8);
693d3b0591SJens Wiklander
703d3b0591SJens Wiklander /* c += d; b ^= c; b <<<= 7; */
713d3b0591SJens Wiklander state[c] += state[d];
723d3b0591SJens Wiklander state[b] ^= state[c];
733d3b0591SJens Wiklander state[b] = ROTL32(state[b], 7);
743d3b0591SJens Wiklander }
753d3b0591SJens Wiklander
763d3b0591SJens Wiklander /**
773d3b0591SJens Wiklander * \brief Perform the ChaCha20 inner block operation.
783d3b0591SJens Wiklander *
793d3b0591SJens Wiklander * This function performs two rounds: the column round and the
803d3b0591SJens Wiklander * diagonal round.
813d3b0591SJens Wiklander *
823d3b0591SJens Wiklander * \param state The ChaCha20 state to update.
833d3b0591SJens Wiklander */
chacha20_inner_block(uint32_t state[16])843d3b0591SJens Wiklander static void chacha20_inner_block(uint32_t state[16])
853d3b0591SJens Wiklander {
863d3b0591SJens Wiklander chacha20_quarter_round(state, 0, 4, 8, 12);
873d3b0591SJens Wiklander chacha20_quarter_round(state, 1, 5, 9, 13);
883d3b0591SJens Wiklander chacha20_quarter_round(state, 2, 6, 10, 14);
893d3b0591SJens Wiklander chacha20_quarter_round(state, 3, 7, 11, 15);
903d3b0591SJens Wiklander
913d3b0591SJens Wiklander chacha20_quarter_round(state, 0, 5, 10, 15);
923d3b0591SJens Wiklander chacha20_quarter_round(state, 1, 6, 11, 12);
933d3b0591SJens Wiklander chacha20_quarter_round(state, 2, 7, 8, 13);
943d3b0591SJens Wiklander chacha20_quarter_round(state, 3, 4, 9, 14);
953d3b0591SJens Wiklander }
963d3b0591SJens Wiklander
973d3b0591SJens Wiklander /**
983d3b0591SJens Wiklander * \brief Generates a keystream block.
993d3b0591SJens Wiklander *
1003d3b0591SJens Wiklander * \param initial_state The initial ChaCha20 state (key, nonce, counter).
1013d3b0591SJens Wiklander * \param keystream Generated keystream bytes are written to this buffer.
1023d3b0591SJens Wiklander */
chacha20_block(const uint32_t initial_state[16],unsigned char keystream[64])1033d3b0591SJens Wiklander static void chacha20_block(const uint32_t initial_state[16],
1043d3b0591SJens Wiklander unsigned char keystream[64])
1053d3b0591SJens Wiklander {
1063d3b0591SJens Wiklander uint32_t working_state[16];
1073d3b0591SJens Wiklander size_t i;
1083d3b0591SJens Wiklander
1093d3b0591SJens Wiklander memcpy(working_state,
1103d3b0591SJens Wiklander initial_state,
1113d3b0591SJens Wiklander CHACHA20_BLOCK_SIZE_BYTES);
1123d3b0591SJens Wiklander
11332b31808SJens Wiklander for (i = 0U; i < 10U; i++) {
1143d3b0591SJens Wiklander chacha20_inner_block(working_state);
11532b31808SJens Wiklander }
1163d3b0591SJens Wiklander
1173d3b0591SJens Wiklander working_state[0] += initial_state[0];
1183d3b0591SJens Wiklander working_state[1] += initial_state[1];
1193d3b0591SJens Wiklander working_state[2] += initial_state[2];
1203d3b0591SJens Wiklander working_state[3] += initial_state[3];
1213d3b0591SJens Wiklander working_state[4] += initial_state[4];
1223d3b0591SJens Wiklander working_state[5] += initial_state[5];
1233d3b0591SJens Wiklander working_state[6] += initial_state[6];
1243d3b0591SJens Wiklander working_state[7] += initial_state[7];
1253d3b0591SJens Wiklander working_state[8] += initial_state[8];
1263d3b0591SJens Wiklander working_state[9] += initial_state[9];
1273d3b0591SJens Wiklander working_state[10] += initial_state[10];
1283d3b0591SJens Wiklander working_state[11] += initial_state[11];
1293d3b0591SJens Wiklander working_state[12] += initial_state[12];
1303d3b0591SJens Wiklander working_state[13] += initial_state[13];
1313d3b0591SJens Wiklander working_state[14] += initial_state[14];
1323d3b0591SJens Wiklander working_state[15] += initial_state[15];
1333d3b0591SJens Wiklander
13432b31808SJens Wiklander for (i = 0U; i < 16; i++) {
1353d3b0591SJens Wiklander size_t offset = i * 4U;
1363d3b0591SJens Wiklander
137039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
1383d3b0591SJens Wiklander }
1393d3b0591SJens Wiklander
1403d3b0591SJens Wiklander mbedtls_platform_zeroize(working_state, sizeof(working_state));
1413d3b0591SJens Wiklander }
1423d3b0591SJens Wiklander
mbedtls_chacha20_init(mbedtls_chacha20_context * ctx)1433d3b0591SJens Wiklander void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
1443d3b0591SJens Wiklander {
1453d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
1463d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
1473d3b0591SJens Wiklander
1483d3b0591SJens Wiklander /* Initially, there's no keystream bytes available */
1493d3b0591SJens Wiklander ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
1503d3b0591SJens Wiklander }
1513d3b0591SJens Wiklander
mbedtls_chacha20_free(mbedtls_chacha20_context * ctx)1523d3b0591SJens Wiklander void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
1533d3b0591SJens Wiklander {
15432b31808SJens Wiklander if (ctx != NULL) {
1553d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
1563d3b0591SJens Wiklander }
1573d3b0591SJens Wiklander }
1583d3b0591SJens Wiklander
mbedtls_chacha20_setkey(mbedtls_chacha20_context * ctx,const unsigned char key[32])1593d3b0591SJens Wiklander int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
1603d3b0591SJens Wiklander const unsigned char key[32])
1613d3b0591SJens Wiklander {
1623d3b0591SJens Wiklander /* ChaCha20 constants - the string "expand 32-byte k" */
1633d3b0591SJens Wiklander ctx->state[0] = 0x61707865;
1643d3b0591SJens Wiklander ctx->state[1] = 0x3320646e;
1653d3b0591SJens Wiklander ctx->state[2] = 0x79622d32;
1663d3b0591SJens Wiklander ctx->state[3] = 0x6b206574;
1673d3b0591SJens Wiklander
1683d3b0591SJens Wiklander /* Set key */
169039e02dfSJerome Forissier ctx->state[4] = MBEDTLS_GET_UINT32_LE(key, 0);
170039e02dfSJerome Forissier ctx->state[5] = MBEDTLS_GET_UINT32_LE(key, 4);
171039e02dfSJerome Forissier ctx->state[6] = MBEDTLS_GET_UINT32_LE(key, 8);
172039e02dfSJerome Forissier ctx->state[7] = MBEDTLS_GET_UINT32_LE(key, 12);
173039e02dfSJerome Forissier ctx->state[8] = MBEDTLS_GET_UINT32_LE(key, 16);
174039e02dfSJerome Forissier ctx->state[9] = MBEDTLS_GET_UINT32_LE(key, 20);
175039e02dfSJerome Forissier ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24);
176039e02dfSJerome Forissier ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28);
1773d3b0591SJens Wiklander
17832b31808SJens Wiklander return 0;
1793d3b0591SJens Wiklander }
1803d3b0591SJens Wiklander
mbedtls_chacha20_starts(mbedtls_chacha20_context * ctx,const unsigned char nonce[12],uint32_t counter)1813d3b0591SJens Wiklander int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
1823d3b0591SJens Wiklander const unsigned char nonce[12],
1833d3b0591SJens Wiklander uint32_t counter)
1843d3b0591SJens Wiklander {
1853d3b0591SJens Wiklander /* Counter */
1863d3b0591SJens Wiklander ctx->state[12] = counter;
1873d3b0591SJens Wiklander
1883d3b0591SJens Wiklander /* Nonce */
189039e02dfSJerome Forissier ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0);
190039e02dfSJerome Forissier ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4);
191039e02dfSJerome Forissier ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8);
1923d3b0591SJens Wiklander
1933d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
1943d3b0591SJens Wiklander
1953d3b0591SJens Wiklander /* Initially, there's no keystream bytes available */
1963d3b0591SJens Wiklander ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
1973d3b0591SJens Wiklander
19832b31808SJens Wiklander return 0;
1993d3b0591SJens Wiklander }
2003d3b0591SJens Wiklander
mbedtls_chacha20_update(mbedtls_chacha20_context * ctx,size_t size,const unsigned char * input,unsigned char * output)2013d3b0591SJens Wiklander int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
2023d3b0591SJens Wiklander size_t size,
2033d3b0591SJens Wiklander const unsigned char *input,
2043d3b0591SJens Wiklander unsigned char *output)
2053d3b0591SJens Wiklander {
2063d3b0591SJens Wiklander size_t offset = 0U;
2073d3b0591SJens Wiklander
2083d3b0591SJens Wiklander /* Use leftover keystream bytes, if available */
20932b31808SJens Wiklander while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
2103d3b0591SJens Wiklander output[offset] = input[offset]
2113d3b0591SJens Wiklander ^ ctx->keystream8[ctx->keystream_bytes_used];
2123d3b0591SJens Wiklander
2133d3b0591SJens Wiklander ctx->keystream_bytes_used++;
2143d3b0591SJens Wiklander offset++;
2153d3b0591SJens Wiklander size--;
2163d3b0591SJens Wiklander }
2173d3b0591SJens Wiklander
2183d3b0591SJens Wiklander /* Process full blocks */
21932b31808SJens Wiklander while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
2203d3b0591SJens Wiklander /* Generate new keystream block and increment counter */
2213d3b0591SJens Wiklander chacha20_block(ctx->state, ctx->keystream8);
2223d3b0591SJens Wiklander ctx->state[CHACHA20_CTR_INDEX]++;
2233d3b0591SJens Wiklander
22432b31808SJens Wiklander mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U);
2253d3b0591SJens Wiklander
2263d3b0591SJens Wiklander offset += CHACHA20_BLOCK_SIZE_BYTES;
2273d3b0591SJens Wiklander size -= CHACHA20_BLOCK_SIZE_BYTES;
2283d3b0591SJens Wiklander }
2293d3b0591SJens Wiklander
2303d3b0591SJens Wiklander /* Last (partial) block */
23132b31808SJens Wiklander if (size > 0U) {
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
23632b31808SJens Wiklander mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);
2373d3b0591SJens Wiklander
2383d3b0591SJens Wiklander ctx->keystream_bytes_used = size;
2393d3b0591SJens Wiklander
2403d3b0591SJens Wiklander }
2413d3b0591SJens Wiklander
24232b31808SJens Wiklander return 0;
2433d3b0591SJens Wiklander }
2443d3b0591SJens Wiklander
mbedtls_chacha20_crypt(const unsigned char key[32],const unsigned char nonce[12],uint32_t counter,size_t data_len,const unsigned char * input,unsigned char * output)2453d3b0591SJens Wiklander int mbedtls_chacha20_crypt(const unsigned char key[32],
2463d3b0591SJens Wiklander const unsigned char nonce[12],
2473d3b0591SJens Wiklander uint32_t counter,
2483d3b0591SJens Wiklander size_t data_len,
2493d3b0591SJens Wiklander const unsigned char *input,
2503d3b0591SJens Wiklander unsigned char *output)
2513d3b0591SJens Wiklander {
2523d3b0591SJens Wiklander mbedtls_chacha20_context ctx;
25311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2543d3b0591SJens Wiklander
2553d3b0591SJens Wiklander mbedtls_chacha20_init(&ctx);
2563d3b0591SJens Wiklander
2573d3b0591SJens Wiklander ret = mbedtls_chacha20_setkey(&ctx, key);
25832b31808SJens Wiklander if (ret != 0) {
2593d3b0591SJens Wiklander goto cleanup;
26032b31808SJens Wiklander }
2613d3b0591SJens Wiklander
2623d3b0591SJens Wiklander ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
26332b31808SJens Wiklander if (ret != 0) {
2643d3b0591SJens Wiklander goto cleanup;
26532b31808SJens Wiklander }
2663d3b0591SJens Wiklander
2673d3b0591SJens Wiklander ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
2683d3b0591SJens Wiklander
2693d3b0591SJens Wiklander cleanup:
2703d3b0591SJens Wiklander mbedtls_chacha20_free(&ctx);
27132b31808SJens Wiklander return ret;
2723d3b0591SJens Wiklander }
2733d3b0591SJens Wiklander
2743d3b0591SJens Wiklander #endif /* !MBEDTLS_CHACHA20_ALT */
2753d3b0591SJens Wiklander
2763d3b0591SJens Wiklander #if defined(MBEDTLS_SELF_TEST)
2773d3b0591SJens Wiklander
2783d3b0591SJens Wiklander static const unsigned char test_keys[2][32] =
2793d3b0591SJens Wiklander {
2803d3b0591SJens Wiklander {
2813d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2823d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2833d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2843d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
2853d3b0591SJens Wiklander },
2863d3b0591SJens Wiklander {
2873d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2883d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2893d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2903d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
2913d3b0591SJens Wiklander }
2923d3b0591SJens Wiklander };
2933d3b0591SJens Wiklander
2943d3b0591SJens Wiklander static const unsigned char test_nonces[2][12] =
2953d3b0591SJens Wiklander {
2963d3b0591SJens Wiklander {
2973d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2983d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00
2993d3b0591SJens Wiklander },
3003d3b0591SJens Wiklander {
3013d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3023d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x02
3033d3b0591SJens Wiklander }
3043d3b0591SJens Wiklander };
3053d3b0591SJens Wiklander
3063d3b0591SJens Wiklander static const uint32_t test_counters[2] =
3073d3b0591SJens Wiklander {
3083d3b0591SJens Wiklander 0U,
3093d3b0591SJens Wiklander 1U
3103d3b0591SJens Wiklander };
3113d3b0591SJens Wiklander
3123d3b0591SJens Wiklander static const unsigned char test_input[2][375] =
3133d3b0591SJens Wiklander {
3143d3b0591SJens Wiklander {
3153d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3163d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3173d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3183d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3193d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3203d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3213d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3223d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3233d3b0591SJens Wiklander },
3243d3b0591SJens Wiklander {
3253d3b0591SJens Wiklander 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
3263d3b0591SJens Wiklander 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
3273d3b0591SJens Wiklander 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
3283d3b0591SJens Wiklander 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
3293d3b0591SJens Wiklander 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
3303d3b0591SJens Wiklander 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
3313d3b0591SJens Wiklander 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
3323d3b0591SJens Wiklander 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
3333d3b0591SJens Wiklander 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
3343d3b0591SJens Wiklander 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
3353d3b0591SJens Wiklander 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
3363d3b0591SJens Wiklander 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
3373d3b0591SJens Wiklander 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3383d3b0591SJens Wiklander 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
3393d3b0591SJens Wiklander 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
3403d3b0591SJens Wiklander 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
3413d3b0591SJens Wiklander 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
3423d3b0591SJens Wiklander 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
3433d3b0591SJens Wiklander 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
3443d3b0591SJens Wiklander 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
3453d3b0591SJens Wiklander 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
3463d3b0591SJens Wiklander 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
3473d3b0591SJens Wiklander 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
3483d3b0591SJens Wiklander 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
3493d3b0591SJens Wiklander 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
3503d3b0591SJens Wiklander 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
3513d3b0591SJens Wiklander 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
3523d3b0591SJens Wiklander 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
3533d3b0591SJens Wiklander 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
3543d3b0591SJens Wiklander 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
3553d3b0591SJens Wiklander 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
3563d3b0591SJens Wiklander 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
3573d3b0591SJens Wiklander 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
3583d3b0591SJens Wiklander 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
3593d3b0591SJens Wiklander 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
3603d3b0591SJens Wiklander 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
3613d3b0591SJens Wiklander 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
3623d3b0591SJens Wiklander 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
3633d3b0591SJens Wiklander 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
3643d3b0591SJens Wiklander 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
3653d3b0591SJens Wiklander 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
3663d3b0591SJens Wiklander 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
3673d3b0591SJens Wiklander 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
3683d3b0591SJens Wiklander 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
3693d3b0591SJens Wiklander 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
3703d3b0591SJens Wiklander 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
3713d3b0591SJens Wiklander 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
3723d3b0591SJens Wiklander }
3733d3b0591SJens Wiklander };
3743d3b0591SJens Wiklander
3753d3b0591SJens Wiklander static const unsigned char test_output[2][375] =
3763d3b0591SJens Wiklander {
3773d3b0591SJens Wiklander {
3783d3b0591SJens Wiklander 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
3793d3b0591SJens Wiklander 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
3803d3b0591SJens Wiklander 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
3813d3b0591SJens Wiklander 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
3823d3b0591SJens Wiklander 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
3833d3b0591SJens Wiklander 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
3843d3b0591SJens Wiklander 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
3853d3b0591SJens Wiklander 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
3863d3b0591SJens Wiklander },
3873d3b0591SJens Wiklander {
3883d3b0591SJens Wiklander 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
3893d3b0591SJens Wiklander 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
3903d3b0591SJens Wiklander 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
3913d3b0591SJens Wiklander 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
3923d3b0591SJens Wiklander 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
3933d3b0591SJens Wiklander 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
3943d3b0591SJens Wiklander 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
3953d3b0591SJens Wiklander 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
3963d3b0591SJens Wiklander 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
3973d3b0591SJens Wiklander 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
3983d3b0591SJens Wiklander 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
3993d3b0591SJens Wiklander 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
4003d3b0591SJens Wiklander 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
4013d3b0591SJens Wiklander 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
4023d3b0591SJens Wiklander 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
4033d3b0591SJens Wiklander 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
4043d3b0591SJens Wiklander 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
4053d3b0591SJens Wiklander 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
4063d3b0591SJens Wiklander 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
4073d3b0591SJens Wiklander 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
4083d3b0591SJens Wiklander 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
4093d3b0591SJens Wiklander 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
4103d3b0591SJens Wiklander 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
4113d3b0591SJens Wiklander 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
4123d3b0591SJens Wiklander 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
4133d3b0591SJens Wiklander 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
4143d3b0591SJens Wiklander 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
4153d3b0591SJens Wiklander 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
4163d3b0591SJens Wiklander 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
4173d3b0591SJens Wiklander 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
4183d3b0591SJens Wiklander 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
4193d3b0591SJens Wiklander 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
4203d3b0591SJens Wiklander 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
4213d3b0591SJens Wiklander 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
4223d3b0591SJens Wiklander 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
4233d3b0591SJens Wiklander 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
4243d3b0591SJens Wiklander 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
4253d3b0591SJens Wiklander 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
4263d3b0591SJens Wiklander 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
4273d3b0591SJens Wiklander 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
4283d3b0591SJens Wiklander 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
4293d3b0591SJens Wiklander 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
4303d3b0591SJens Wiklander 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
4313d3b0591SJens Wiklander 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
4323d3b0591SJens Wiklander 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
4333d3b0591SJens Wiklander 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
4343d3b0591SJens Wiklander 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
4353d3b0591SJens Wiklander }
4363d3b0591SJens Wiklander };
4373d3b0591SJens Wiklander
4383d3b0591SJens Wiklander static const size_t test_lengths[2] =
4393d3b0591SJens Wiklander {
4403d3b0591SJens Wiklander 64U,
4413d3b0591SJens Wiklander 375U
4423d3b0591SJens Wiklander };
4433d3b0591SJens Wiklander
4447901324dSJerome Forissier /* Make sure no other definition is already present. */
4457901324dSJerome Forissier #undef ASSERT
4467901324dSJerome Forissier
4473d3b0591SJens Wiklander #define ASSERT(cond, args) \
4483d3b0591SJens Wiklander do \
4493d3b0591SJens Wiklander { \
4503d3b0591SJens Wiklander if (!(cond)) \
4513d3b0591SJens Wiklander { \
4523d3b0591SJens Wiklander if (verbose != 0) \
4533d3b0591SJens Wiklander mbedtls_printf args; \
4543d3b0591SJens Wiklander \
45532b31808SJens Wiklander return -1; \
4563d3b0591SJens Wiklander } \
4573d3b0591SJens Wiklander } \
4583d3b0591SJens Wiklander while (0)
4593d3b0591SJens Wiklander
mbedtls_chacha20_self_test(int verbose)4603d3b0591SJens Wiklander int mbedtls_chacha20_self_test(int verbose)
4613d3b0591SJens Wiklander {
4623d3b0591SJens Wiklander unsigned char output[381];
4633d3b0591SJens Wiklander unsigned i;
46411fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4653d3b0591SJens Wiklander
46632b31808SJens Wiklander for (i = 0U; i < 2U; i++) {
46732b31808SJens Wiklander if (verbose != 0) {
4683d3b0591SJens Wiklander mbedtls_printf(" ChaCha20 test %u ", i);
46932b31808SJens Wiklander }
4703d3b0591SJens Wiklander
4713d3b0591SJens Wiklander ret = mbedtls_chacha20_crypt(test_keys[i],
4723d3b0591SJens Wiklander test_nonces[i],
4733d3b0591SJens Wiklander test_counters[i],
4743d3b0591SJens Wiklander test_lengths[i],
4753d3b0591SJens Wiklander test_input[i],
4763d3b0591SJens Wiklander output);
4773d3b0591SJens Wiklander
4783d3b0591SJens Wiklander ASSERT(0 == ret, ("error code: %i\n", ret));
4793d3b0591SJens Wiklander
4803d3b0591SJens Wiklander ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
4813d3b0591SJens Wiklander ("failed (output)\n"));
4823d3b0591SJens Wiklander
48332b31808SJens Wiklander if (verbose != 0) {
4843d3b0591SJens Wiklander mbedtls_printf("passed\n");
4853d3b0591SJens Wiklander }
48632b31808SJens Wiklander }
4873d3b0591SJens Wiklander
48832b31808SJens Wiklander if (verbose != 0) {
4893d3b0591SJens Wiklander mbedtls_printf("\n");
49032b31808SJens Wiklander }
4913d3b0591SJens Wiklander
49232b31808SJens Wiklander return 0;
4933d3b0591SJens Wiklander }
4943d3b0591SJens Wiklander
4953d3b0591SJens Wiklander #endif /* MBEDTLS_SELF_TEST */
4963d3b0591SJens Wiklander
4973d3b0591SJens Wiklander #endif /* !MBEDTLS_CHACHA20_C */
498