1*3d3b0591SJens Wiklander /* SPDX-License-Identifier: Apache-2.0 */ 2*3d3b0591SJens Wiklander /** 3*3d3b0591SJens Wiklander * \file chacha20.c 4*3d3b0591SJens Wiklander * 5*3d3b0591SJens Wiklander * \brief ChaCha20 cipher. 6*3d3b0591SJens Wiklander * 7*3d3b0591SJens Wiklander * \author Daniel King <damaki.gh@gmail.com> 8*3d3b0591SJens Wiklander * 9*3d3b0591SJens Wiklander * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved 10*3d3b0591SJens Wiklander * 11*3d3b0591SJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 12*3d3b0591SJens Wiklander * not use this file except in compliance with the License. 13*3d3b0591SJens Wiklander * You may obtain a copy of the License at 14*3d3b0591SJens Wiklander * 15*3d3b0591SJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 16*3d3b0591SJens Wiklander * 17*3d3b0591SJens Wiklander * Unless required by applicable law or agreed to in writing, software 18*3d3b0591SJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 19*3d3b0591SJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20*3d3b0591SJens Wiklander * See the License for the specific language governing permissions and 21*3d3b0591SJens Wiklander * limitations under the License. 22*3d3b0591SJens Wiklander * 23*3d3b0591SJens Wiklander * This file is part of mbed TLS (https://tls.mbed.org) 24*3d3b0591SJens Wiklander */ 25*3d3b0591SJens Wiklander 26*3d3b0591SJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE) 27*3d3b0591SJens Wiklander #include "mbedtls/config.h" 28*3d3b0591SJens Wiklander #else 29*3d3b0591SJens Wiklander #include MBEDTLS_CONFIG_FILE 30*3d3b0591SJens Wiklander #endif 31*3d3b0591SJens Wiklander 32*3d3b0591SJens Wiklander #if defined(MBEDTLS_CHACHA20_C) 33*3d3b0591SJens Wiklander 34*3d3b0591SJens Wiklander #include "mbedtls/chacha20.h" 35*3d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 36*3d3b0591SJens Wiklander 37*3d3b0591SJens Wiklander #include <stddef.h> 38*3d3b0591SJens Wiklander #include <string.h> 39*3d3b0591SJens Wiklander 40*3d3b0591SJens Wiklander #if defined(MBEDTLS_SELF_TEST) 41*3d3b0591SJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 42*3d3b0591SJens Wiklander #include "mbedtls/platform.h" 43*3d3b0591SJens Wiklander #else 44*3d3b0591SJens Wiklander #include <stdio.h> 45*3d3b0591SJens Wiklander #define mbedtls_printf printf 46*3d3b0591SJens Wiklander #endif /* MBEDTLS_PLATFORM_C */ 47*3d3b0591SJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 48*3d3b0591SJens Wiklander 49*3d3b0591SJens Wiklander #if !defined(MBEDTLS_CHACHA20_ALT) 50*3d3b0591SJens Wiklander 51*3d3b0591SJens Wiklander #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ 52*3d3b0591SJens Wiklander !defined(inline) && !defined(__cplusplus) 53*3d3b0591SJens Wiklander #define inline __inline 54*3d3b0591SJens Wiklander #endif 55*3d3b0591SJens Wiklander 56*3d3b0591SJens Wiklander /* Parameter validation macros */ 57*3d3b0591SJens Wiklander #define CHACHA20_VALIDATE_RET( cond ) \ 58*3d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) 59*3d3b0591SJens Wiklander #define CHACHA20_VALIDATE( cond ) \ 60*3d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE( cond ) 61*3d3b0591SJens Wiklander 62*3d3b0591SJens Wiklander #define BYTES_TO_U32_LE( data, offset ) \ 63*3d3b0591SJens Wiklander ( (uint32_t) data[offset] \ 64*3d3b0591SJens Wiklander | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \ 65*3d3b0591SJens Wiklander | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \ 66*3d3b0591SJens Wiklander | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \ 67*3d3b0591SJens Wiklander ) 68*3d3b0591SJens Wiklander 69*3d3b0591SJens Wiklander #define ROTL32( value, amount ) \ 70*3d3b0591SJens Wiklander ( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) ) 71*3d3b0591SJens Wiklander 72*3d3b0591SJens Wiklander #define CHACHA20_CTR_INDEX ( 12U ) 73*3d3b0591SJens Wiklander 74*3d3b0591SJens Wiklander #define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U ) 75*3d3b0591SJens Wiklander 76*3d3b0591SJens Wiklander /** 77*3d3b0591SJens Wiklander * \brief ChaCha20 quarter round operation. 78*3d3b0591SJens Wiklander * 79*3d3b0591SJens Wiklander * The quarter round is defined as follows (from RFC 7539): 80*3d3b0591SJens Wiklander * 1. a += b; d ^= a; d <<<= 16; 81*3d3b0591SJens Wiklander * 2. c += d; b ^= c; b <<<= 12; 82*3d3b0591SJens Wiklander * 3. a += b; d ^= a; d <<<= 8; 83*3d3b0591SJens Wiklander * 4. c += d; b ^= c; b <<<= 7; 84*3d3b0591SJens Wiklander * 85*3d3b0591SJens Wiklander * \param state ChaCha20 state to modify. 86*3d3b0591SJens Wiklander * \param a The index of 'a' in the state. 87*3d3b0591SJens Wiklander * \param b The index of 'b' in the state. 88*3d3b0591SJens Wiklander * \param c The index of 'c' in the state. 89*3d3b0591SJens Wiklander * \param d The index of 'd' in the state. 90*3d3b0591SJens Wiklander */ 91*3d3b0591SJens Wiklander static inline void chacha20_quarter_round( uint32_t state[16], 92*3d3b0591SJens Wiklander size_t a, 93*3d3b0591SJens Wiklander size_t b, 94*3d3b0591SJens Wiklander size_t c, 95*3d3b0591SJens Wiklander size_t d ) 96*3d3b0591SJens Wiklander { 97*3d3b0591SJens Wiklander /* a += b; d ^= a; d <<<= 16; */ 98*3d3b0591SJens Wiklander state[a] += state[b]; 99*3d3b0591SJens Wiklander state[d] ^= state[a]; 100*3d3b0591SJens Wiklander state[d] = ROTL32( state[d], 16 ); 101*3d3b0591SJens Wiklander 102*3d3b0591SJens Wiklander /* c += d; b ^= c; b <<<= 12 */ 103*3d3b0591SJens Wiklander state[c] += state[d]; 104*3d3b0591SJens Wiklander state[b] ^= state[c]; 105*3d3b0591SJens Wiklander state[b] = ROTL32( state[b], 12 ); 106*3d3b0591SJens Wiklander 107*3d3b0591SJens Wiklander /* a += b; d ^= a; d <<<= 8; */ 108*3d3b0591SJens Wiklander state[a] += state[b]; 109*3d3b0591SJens Wiklander state[d] ^= state[a]; 110*3d3b0591SJens Wiklander state[d] = ROTL32( state[d], 8 ); 111*3d3b0591SJens Wiklander 112*3d3b0591SJens Wiklander /* c += d; b ^= c; b <<<= 7; */ 113*3d3b0591SJens Wiklander state[c] += state[d]; 114*3d3b0591SJens Wiklander state[b] ^= state[c]; 115*3d3b0591SJens Wiklander state[b] = ROTL32( state[b], 7 ); 116*3d3b0591SJens Wiklander } 117*3d3b0591SJens Wiklander 118*3d3b0591SJens Wiklander /** 119*3d3b0591SJens Wiklander * \brief Perform the ChaCha20 inner block operation. 120*3d3b0591SJens Wiklander * 121*3d3b0591SJens Wiklander * This function performs two rounds: the column round and the 122*3d3b0591SJens Wiklander * diagonal round. 123*3d3b0591SJens Wiklander * 124*3d3b0591SJens Wiklander * \param state The ChaCha20 state to update. 125*3d3b0591SJens Wiklander */ 126*3d3b0591SJens Wiklander static void chacha20_inner_block( uint32_t state[16] ) 127*3d3b0591SJens Wiklander { 128*3d3b0591SJens Wiklander chacha20_quarter_round( state, 0, 4, 8, 12 ); 129*3d3b0591SJens Wiklander chacha20_quarter_round( state, 1, 5, 9, 13 ); 130*3d3b0591SJens Wiklander chacha20_quarter_round( state, 2, 6, 10, 14 ); 131*3d3b0591SJens Wiklander chacha20_quarter_round( state, 3, 7, 11, 15 ); 132*3d3b0591SJens Wiklander 133*3d3b0591SJens Wiklander chacha20_quarter_round( state, 0, 5, 10, 15 ); 134*3d3b0591SJens Wiklander chacha20_quarter_round( state, 1, 6, 11, 12 ); 135*3d3b0591SJens Wiklander chacha20_quarter_round( state, 2, 7, 8, 13 ); 136*3d3b0591SJens Wiklander chacha20_quarter_round( state, 3, 4, 9, 14 ); 137*3d3b0591SJens Wiklander } 138*3d3b0591SJens Wiklander 139*3d3b0591SJens Wiklander /** 140*3d3b0591SJens Wiklander * \brief Generates a keystream block. 141*3d3b0591SJens Wiklander * 142*3d3b0591SJens Wiklander * \param initial_state The initial ChaCha20 state (key, nonce, counter). 143*3d3b0591SJens Wiklander * \param keystream Generated keystream bytes are written to this buffer. 144*3d3b0591SJens Wiklander */ 145*3d3b0591SJens Wiklander static void chacha20_block( const uint32_t initial_state[16], 146*3d3b0591SJens Wiklander unsigned char keystream[64] ) 147*3d3b0591SJens Wiklander { 148*3d3b0591SJens Wiklander uint32_t working_state[16]; 149*3d3b0591SJens Wiklander size_t i; 150*3d3b0591SJens Wiklander 151*3d3b0591SJens Wiklander memcpy( working_state, 152*3d3b0591SJens Wiklander initial_state, 153*3d3b0591SJens Wiklander CHACHA20_BLOCK_SIZE_BYTES ); 154*3d3b0591SJens Wiklander 155*3d3b0591SJens Wiklander for( i = 0U; i < 10U; i++ ) 156*3d3b0591SJens Wiklander chacha20_inner_block( working_state ); 157*3d3b0591SJens Wiklander 158*3d3b0591SJens Wiklander working_state[ 0] += initial_state[ 0]; 159*3d3b0591SJens Wiklander working_state[ 1] += initial_state[ 1]; 160*3d3b0591SJens Wiklander working_state[ 2] += initial_state[ 2]; 161*3d3b0591SJens Wiklander working_state[ 3] += initial_state[ 3]; 162*3d3b0591SJens Wiklander working_state[ 4] += initial_state[ 4]; 163*3d3b0591SJens Wiklander working_state[ 5] += initial_state[ 5]; 164*3d3b0591SJens Wiklander working_state[ 6] += initial_state[ 6]; 165*3d3b0591SJens Wiklander working_state[ 7] += initial_state[ 7]; 166*3d3b0591SJens Wiklander working_state[ 8] += initial_state[ 8]; 167*3d3b0591SJens Wiklander working_state[ 9] += initial_state[ 9]; 168*3d3b0591SJens Wiklander working_state[10] += initial_state[10]; 169*3d3b0591SJens Wiklander working_state[11] += initial_state[11]; 170*3d3b0591SJens Wiklander working_state[12] += initial_state[12]; 171*3d3b0591SJens Wiklander working_state[13] += initial_state[13]; 172*3d3b0591SJens Wiklander working_state[14] += initial_state[14]; 173*3d3b0591SJens Wiklander working_state[15] += initial_state[15]; 174*3d3b0591SJens Wiklander 175*3d3b0591SJens Wiklander for( i = 0U; i < 16; i++ ) 176*3d3b0591SJens Wiklander { 177*3d3b0591SJens Wiklander size_t offset = i * 4U; 178*3d3b0591SJens Wiklander 179*3d3b0591SJens Wiklander keystream[offset ] = (unsigned char)( working_state[i] ); 180*3d3b0591SJens Wiklander keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 ); 181*3d3b0591SJens Wiklander keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 ); 182*3d3b0591SJens Wiklander keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 ); 183*3d3b0591SJens Wiklander } 184*3d3b0591SJens Wiklander 185*3d3b0591SJens Wiklander mbedtls_platform_zeroize( working_state, sizeof( working_state ) ); 186*3d3b0591SJens Wiklander } 187*3d3b0591SJens Wiklander 188*3d3b0591SJens Wiklander void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ) 189*3d3b0591SJens Wiklander { 190*3d3b0591SJens Wiklander CHACHA20_VALIDATE( ctx != NULL ); 191*3d3b0591SJens Wiklander 192*3d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) ); 193*3d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); 194*3d3b0591SJens Wiklander 195*3d3b0591SJens Wiklander /* Initially, there's no keystream bytes available */ 196*3d3b0591SJens Wiklander ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; 197*3d3b0591SJens Wiklander } 198*3d3b0591SJens Wiklander 199*3d3b0591SJens Wiklander void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ) 200*3d3b0591SJens Wiklander { 201*3d3b0591SJens Wiklander if( ctx != NULL ) 202*3d3b0591SJens Wiklander { 203*3d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) ); 204*3d3b0591SJens Wiklander } 205*3d3b0591SJens Wiklander } 206*3d3b0591SJens Wiklander 207*3d3b0591SJens Wiklander int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, 208*3d3b0591SJens Wiklander const unsigned char key[32] ) 209*3d3b0591SJens Wiklander { 210*3d3b0591SJens Wiklander CHACHA20_VALIDATE_RET( ctx != NULL ); 211*3d3b0591SJens Wiklander CHACHA20_VALIDATE_RET( key != NULL ); 212*3d3b0591SJens Wiklander 213*3d3b0591SJens Wiklander /* ChaCha20 constants - the string "expand 32-byte k" */ 214*3d3b0591SJens Wiklander ctx->state[0] = 0x61707865; 215*3d3b0591SJens Wiklander ctx->state[1] = 0x3320646e; 216*3d3b0591SJens Wiklander ctx->state[2] = 0x79622d32; 217*3d3b0591SJens Wiklander ctx->state[3] = 0x6b206574; 218*3d3b0591SJens Wiklander 219*3d3b0591SJens Wiklander /* Set key */ 220*3d3b0591SJens Wiklander ctx->state[4] = BYTES_TO_U32_LE( key, 0 ); 221*3d3b0591SJens Wiklander ctx->state[5] = BYTES_TO_U32_LE( key, 4 ); 222*3d3b0591SJens Wiklander ctx->state[6] = BYTES_TO_U32_LE( key, 8 ); 223*3d3b0591SJens Wiklander ctx->state[7] = BYTES_TO_U32_LE( key, 12 ); 224*3d3b0591SJens Wiklander ctx->state[8] = BYTES_TO_U32_LE( key, 16 ); 225*3d3b0591SJens Wiklander ctx->state[9] = BYTES_TO_U32_LE( key, 20 ); 226*3d3b0591SJens Wiklander ctx->state[10] = BYTES_TO_U32_LE( key, 24 ); 227*3d3b0591SJens Wiklander ctx->state[11] = BYTES_TO_U32_LE( key, 28 ); 228*3d3b0591SJens Wiklander 229*3d3b0591SJens Wiklander return( 0 ); 230*3d3b0591SJens Wiklander } 231*3d3b0591SJens Wiklander 232*3d3b0591SJens Wiklander int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, 233*3d3b0591SJens Wiklander const unsigned char nonce[12], 234*3d3b0591SJens Wiklander uint32_t counter ) 235*3d3b0591SJens Wiklander { 236*3d3b0591SJens Wiklander CHACHA20_VALIDATE_RET( ctx != NULL ); 237*3d3b0591SJens Wiklander CHACHA20_VALIDATE_RET( nonce != NULL ); 238*3d3b0591SJens Wiklander 239*3d3b0591SJens Wiklander /* Counter */ 240*3d3b0591SJens Wiklander ctx->state[12] = counter; 241*3d3b0591SJens Wiklander 242*3d3b0591SJens Wiklander /* Nonce */ 243*3d3b0591SJens Wiklander ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 ); 244*3d3b0591SJens Wiklander ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 ); 245*3d3b0591SJens Wiklander ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 ); 246*3d3b0591SJens Wiklander 247*3d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); 248*3d3b0591SJens Wiklander 249*3d3b0591SJens Wiklander /* Initially, there's no keystream bytes available */ 250*3d3b0591SJens Wiklander ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; 251*3d3b0591SJens Wiklander 252*3d3b0591SJens Wiklander return( 0 ); 253*3d3b0591SJens Wiklander } 254*3d3b0591SJens Wiklander 255*3d3b0591SJens Wiklander int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, 256*3d3b0591SJens Wiklander size_t size, 257*3d3b0591SJens Wiklander const unsigned char *input, 258*3d3b0591SJens Wiklander unsigned char *output ) 259*3d3b0591SJens Wiklander { 260*3d3b0591SJens Wiklander size_t offset = 0U; 261*3d3b0591SJens Wiklander size_t i; 262*3d3b0591SJens Wiklander 263*3d3b0591SJens Wiklander CHACHA20_VALIDATE_RET( ctx != NULL ); 264*3d3b0591SJens Wiklander CHACHA20_VALIDATE_RET( size == 0 || input != NULL ); 265*3d3b0591SJens Wiklander CHACHA20_VALIDATE_RET( size == 0 || output != NULL ); 266*3d3b0591SJens Wiklander 267*3d3b0591SJens Wiklander /* Use leftover keystream bytes, if available */ 268*3d3b0591SJens Wiklander while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) 269*3d3b0591SJens Wiklander { 270*3d3b0591SJens Wiklander output[offset] = input[offset] 271*3d3b0591SJens Wiklander ^ ctx->keystream8[ctx->keystream_bytes_used]; 272*3d3b0591SJens Wiklander 273*3d3b0591SJens Wiklander ctx->keystream_bytes_used++; 274*3d3b0591SJens Wiklander offset++; 275*3d3b0591SJens Wiklander size--; 276*3d3b0591SJens Wiklander } 277*3d3b0591SJens Wiklander 278*3d3b0591SJens Wiklander /* Process full blocks */ 279*3d3b0591SJens Wiklander while( size >= CHACHA20_BLOCK_SIZE_BYTES ) 280*3d3b0591SJens Wiklander { 281*3d3b0591SJens Wiklander /* Generate new keystream block and increment counter */ 282*3d3b0591SJens Wiklander chacha20_block( ctx->state, ctx->keystream8 ); 283*3d3b0591SJens Wiklander ctx->state[CHACHA20_CTR_INDEX]++; 284*3d3b0591SJens Wiklander 285*3d3b0591SJens Wiklander for( i = 0U; i < 64U; i += 8U ) 286*3d3b0591SJens Wiklander { 287*3d3b0591SJens Wiklander output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ]; 288*3d3b0591SJens Wiklander output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1]; 289*3d3b0591SJens Wiklander output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2]; 290*3d3b0591SJens Wiklander output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3]; 291*3d3b0591SJens Wiklander output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4]; 292*3d3b0591SJens Wiklander output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5]; 293*3d3b0591SJens Wiklander output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6]; 294*3d3b0591SJens Wiklander output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7]; 295*3d3b0591SJens Wiklander } 296*3d3b0591SJens Wiklander 297*3d3b0591SJens Wiklander offset += CHACHA20_BLOCK_SIZE_BYTES; 298*3d3b0591SJens Wiklander size -= CHACHA20_BLOCK_SIZE_BYTES; 299*3d3b0591SJens Wiklander } 300*3d3b0591SJens Wiklander 301*3d3b0591SJens Wiklander /* Last (partial) block */ 302*3d3b0591SJens Wiklander if( size > 0U ) 303*3d3b0591SJens Wiklander { 304*3d3b0591SJens Wiklander /* Generate new keystream block and increment counter */ 305*3d3b0591SJens Wiklander chacha20_block( ctx->state, ctx->keystream8 ); 306*3d3b0591SJens Wiklander ctx->state[CHACHA20_CTR_INDEX]++; 307*3d3b0591SJens Wiklander 308*3d3b0591SJens Wiklander for( i = 0U; i < size; i++) 309*3d3b0591SJens Wiklander { 310*3d3b0591SJens Wiklander output[offset + i] = input[offset + i] ^ ctx->keystream8[i]; 311*3d3b0591SJens Wiklander } 312*3d3b0591SJens Wiklander 313*3d3b0591SJens Wiklander ctx->keystream_bytes_used = size; 314*3d3b0591SJens Wiklander 315*3d3b0591SJens Wiklander } 316*3d3b0591SJens Wiklander 317*3d3b0591SJens Wiklander return( 0 ); 318*3d3b0591SJens Wiklander } 319*3d3b0591SJens Wiklander 320*3d3b0591SJens Wiklander int mbedtls_chacha20_crypt( const unsigned char key[32], 321*3d3b0591SJens Wiklander const unsigned char nonce[12], 322*3d3b0591SJens Wiklander uint32_t counter, 323*3d3b0591SJens Wiklander size_t data_len, 324*3d3b0591SJens Wiklander const unsigned char* input, 325*3d3b0591SJens Wiklander unsigned char* output ) 326*3d3b0591SJens Wiklander { 327*3d3b0591SJens Wiklander mbedtls_chacha20_context ctx; 328*3d3b0591SJens Wiklander int ret; 329*3d3b0591SJens Wiklander 330*3d3b0591SJens Wiklander CHACHA20_VALIDATE_RET( key != NULL ); 331*3d3b0591SJens Wiklander CHACHA20_VALIDATE_RET( nonce != NULL ); 332*3d3b0591SJens Wiklander CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL ); 333*3d3b0591SJens Wiklander CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL ); 334*3d3b0591SJens Wiklander 335*3d3b0591SJens Wiklander mbedtls_chacha20_init( &ctx ); 336*3d3b0591SJens Wiklander 337*3d3b0591SJens Wiklander ret = mbedtls_chacha20_setkey( &ctx, key ); 338*3d3b0591SJens Wiklander if( ret != 0 ) 339*3d3b0591SJens Wiklander goto cleanup; 340*3d3b0591SJens Wiklander 341*3d3b0591SJens Wiklander ret = mbedtls_chacha20_starts( &ctx, nonce, counter ); 342*3d3b0591SJens Wiklander if( ret != 0 ) 343*3d3b0591SJens Wiklander goto cleanup; 344*3d3b0591SJens Wiklander 345*3d3b0591SJens Wiklander ret = mbedtls_chacha20_update( &ctx, data_len, input, output ); 346*3d3b0591SJens Wiklander 347*3d3b0591SJens Wiklander cleanup: 348*3d3b0591SJens Wiklander mbedtls_chacha20_free( &ctx ); 349*3d3b0591SJens Wiklander return( ret ); 350*3d3b0591SJens Wiklander } 351*3d3b0591SJens Wiklander 352*3d3b0591SJens Wiklander #endif /* !MBEDTLS_CHACHA20_ALT */ 353*3d3b0591SJens Wiklander 354*3d3b0591SJens Wiklander #if defined(MBEDTLS_SELF_TEST) 355*3d3b0591SJens Wiklander 356*3d3b0591SJens Wiklander static const unsigned char test_keys[2][32] = 357*3d3b0591SJens Wiklander { 358*3d3b0591SJens Wiklander { 359*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 360*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 361*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 362*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 363*3d3b0591SJens Wiklander }, 364*3d3b0591SJens Wiklander { 365*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 366*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 367*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 368*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 369*3d3b0591SJens Wiklander } 370*3d3b0591SJens Wiklander }; 371*3d3b0591SJens Wiklander 372*3d3b0591SJens Wiklander static const unsigned char test_nonces[2][12] = 373*3d3b0591SJens Wiklander { 374*3d3b0591SJens Wiklander { 375*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 376*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00 377*3d3b0591SJens Wiklander }, 378*3d3b0591SJens Wiklander { 379*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 380*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x02 381*3d3b0591SJens Wiklander } 382*3d3b0591SJens Wiklander }; 383*3d3b0591SJens Wiklander 384*3d3b0591SJens Wiklander static const uint32_t test_counters[2] = 385*3d3b0591SJens Wiklander { 386*3d3b0591SJens Wiklander 0U, 387*3d3b0591SJens Wiklander 1U 388*3d3b0591SJens Wiklander }; 389*3d3b0591SJens Wiklander 390*3d3b0591SJens Wiklander static const unsigned char test_input[2][375] = 391*3d3b0591SJens Wiklander { 392*3d3b0591SJens Wiklander { 393*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 394*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 395*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 396*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 397*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 398*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 399*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 400*3d3b0591SJens Wiklander 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 401*3d3b0591SJens Wiklander }, 402*3d3b0591SJens Wiklander { 403*3d3b0591SJens Wiklander 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, 404*3d3b0591SJens Wiklander 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 405*3d3b0591SJens Wiklander 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, 406*3d3b0591SJens Wiklander 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 407*3d3b0591SJens Wiklander 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 408*3d3b0591SJens Wiklander 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 409*3d3b0591SJens Wiklander 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, 410*3d3b0591SJens Wiklander 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 411*3d3b0591SJens Wiklander 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 412*3d3b0591SJens Wiklander 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, 413*3d3b0591SJens Wiklander 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 414*3d3b0591SJens Wiklander 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, 415*3d3b0591SJens Wiklander 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 416*3d3b0591SJens Wiklander 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, 417*3d3b0591SJens Wiklander 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, 418*3d3b0591SJens Wiklander 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, 419*3d3b0591SJens Wiklander 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 420*3d3b0591SJens Wiklander 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, 421*3d3b0591SJens Wiklander 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 422*3d3b0591SJens Wiklander 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 423*3d3b0591SJens Wiklander 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, 424*3d3b0591SJens Wiklander 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, 425*3d3b0591SJens Wiklander 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 426*3d3b0591SJens Wiklander 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 427*3d3b0591SJens Wiklander 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, 428*3d3b0591SJens Wiklander 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, 429*3d3b0591SJens Wiklander 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 430*3d3b0591SJens Wiklander 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, 431*3d3b0591SJens Wiklander 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 432*3d3b0591SJens Wiklander 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 433*3d3b0591SJens Wiklander 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, 434*3d3b0591SJens Wiklander 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 435*3d3b0591SJens Wiklander 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 436*3d3b0591SJens Wiklander 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, 437*3d3b0591SJens Wiklander 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 438*3d3b0591SJens Wiklander 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, 439*3d3b0591SJens Wiklander 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 440*3d3b0591SJens Wiklander 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, 441*3d3b0591SJens Wiklander 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, 442*3d3b0591SJens Wiklander 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 443*3d3b0591SJens Wiklander 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, 444*3d3b0591SJens Wiklander 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, 445*3d3b0591SJens Wiklander 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 446*3d3b0591SJens Wiklander 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, 447*3d3b0591SJens Wiklander 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 448*3d3b0591SJens Wiklander 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 449*3d3b0591SJens Wiklander 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f 450*3d3b0591SJens Wiklander } 451*3d3b0591SJens Wiklander }; 452*3d3b0591SJens Wiklander 453*3d3b0591SJens Wiklander static const unsigned char test_output[2][375] = 454*3d3b0591SJens Wiklander { 455*3d3b0591SJens Wiklander { 456*3d3b0591SJens Wiklander 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 457*3d3b0591SJens Wiklander 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, 458*3d3b0591SJens Wiklander 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 459*3d3b0591SJens Wiklander 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, 460*3d3b0591SJens Wiklander 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, 461*3d3b0591SJens Wiklander 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, 462*3d3b0591SJens Wiklander 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, 463*3d3b0591SJens Wiklander 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 464*3d3b0591SJens Wiklander }, 465*3d3b0591SJens Wiklander { 466*3d3b0591SJens Wiklander 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, 467*3d3b0591SJens Wiklander 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, 468*3d3b0591SJens Wiklander 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, 469*3d3b0591SJens Wiklander 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, 470*3d3b0591SJens Wiklander 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, 471*3d3b0591SJens Wiklander 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, 472*3d3b0591SJens Wiklander 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, 473*3d3b0591SJens Wiklander 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, 474*3d3b0591SJens Wiklander 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, 475*3d3b0591SJens Wiklander 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, 476*3d3b0591SJens Wiklander 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, 477*3d3b0591SJens Wiklander 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, 478*3d3b0591SJens Wiklander 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, 479*3d3b0591SJens Wiklander 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, 480*3d3b0591SJens Wiklander 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, 481*3d3b0591SJens Wiklander 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, 482*3d3b0591SJens Wiklander 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, 483*3d3b0591SJens Wiklander 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, 484*3d3b0591SJens Wiklander 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, 485*3d3b0591SJens Wiklander 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, 486*3d3b0591SJens Wiklander 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, 487*3d3b0591SJens Wiklander 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, 488*3d3b0591SJens Wiklander 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, 489*3d3b0591SJens Wiklander 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, 490*3d3b0591SJens Wiklander 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, 491*3d3b0591SJens Wiklander 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, 492*3d3b0591SJens Wiklander 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, 493*3d3b0591SJens Wiklander 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, 494*3d3b0591SJens Wiklander 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, 495*3d3b0591SJens Wiklander 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, 496*3d3b0591SJens Wiklander 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, 497*3d3b0591SJens Wiklander 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, 498*3d3b0591SJens Wiklander 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, 499*3d3b0591SJens Wiklander 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, 500*3d3b0591SJens Wiklander 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, 501*3d3b0591SJens Wiklander 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, 502*3d3b0591SJens Wiklander 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, 503*3d3b0591SJens Wiklander 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, 504*3d3b0591SJens Wiklander 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, 505*3d3b0591SJens Wiklander 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, 506*3d3b0591SJens Wiklander 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, 507*3d3b0591SJens Wiklander 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, 508*3d3b0591SJens Wiklander 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, 509*3d3b0591SJens Wiklander 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, 510*3d3b0591SJens Wiklander 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, 511*3d3b0591SJens Wiklander 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, 512*3d3b0591SJens Wiklander 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 513*3d3b0591SJens Wiklander } 514*3d3b0591SJens Wiklander }; 515*3d3b0591SJens Wiklander 516*3d3b0591SJens Wiklander static const size_t test_lengths[2] = 517*3d3b0591SJens Wiklander { 518*3d3b0591SJens Wiklander 64U, 519*3d3b0591SJens Wiklander 375U 520*3d3b0591SJens Wiklander }; 521*3d3b0591SJens Wiklander 522*3d3b0591SJens Wiklander #define ASSERT( cond, args ) \ 523*3d3b0591SJens Wiklander do \ 524*3d3b0591SJens Wiklander { \ 525*3d3b0591SJens Wiklander if( ! ( cond ) ) \ 526*3d3b0591SJens Wiklander { \ 527*3d3b0591SJens Wiklander if( verbose != 0 ) \ 528*3d3b0591SJens Wiklander mbedtls_printf args; \ 529*3d3b0591SJens Wiklander \ 530*3d3b0591SJens Wiklander return( -1 ); \ 531*3d3b0591SJens Wiklander } \ 532*3d3b0591SJens Wiklander } \ 533*3d3b0591SJens Wiklander while( 0 ) 534*3d3b0591SJens Wiklander 535*3d3b0591SJens Wiklander int mbedtls_chacha20_self_test( int verbose ) 536*3d3b0591SJens Wiklander { 537*3d3b0591SJens Wiklander unsigned char output[381]; 538*3d3b0591SJens Wiklander unsigned i; 539*3d3b0591SJens Wiklander int ret; 540*3d3b0591SJens Wiklander 541*3d3b0591SJens Wiklander for( i = 0U; i < 2U; i++ ) 542*3d3b0591SJens Wiklander { 543*3d3b0591SJens Wiklander if( verbose != 0 ) 544*3d3b0591SJens Wiklander mbedtls_printf( " ChaCha20 test %u ", i ); 545*3d3b0591SJens Wiklander 546*3d3b0591SJens Wiklander ret = mbedtls_chacha20_crypt( test_keys[i], 547*3d3b0591SJens Wiklander test_nonces[i], 548*3d3b0591SJens Wiklander test_counters[i], 549*3d3b0591SJens Wiklander test_lengths[i], 550*3d3b0591SJens Wiklander test_input[i], 551*3d3b0591SJens Wiklander output ); 552*3d3b0591SJens Wiklander 553*3d3b0591SJens Wiklander ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); 554*3d3b0591SJens Wiklander 555*3d3b0591SJens Wiklander ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ), 556*3d3b0591SJens Wiklander ( "failed (output)\n" ) ); 557*3d3b0591SJens Wiklander 558*3d3b0591SJens Wiklander if( verbose != 0 ) 559*3d3b0591SJens Wiklander mbedtls_printf( "passed\n" ); 560*3d3b0591SJens Wiklander } 561*3d3b0591SJens Wiklander 562*3d3b0591SJens Wiklander if( verbose != 0 ) 563*3d3b0591SJens Wiklander mbedtls_printf( "\n" ); 564*3d3b0591SJens Wiklander 565*3d3b0591SJens Wiklander return( 0 ); 566*3d3b0591SJens Wiklander } 567*3d3b0591SJens Wiklander 568*3d3b0591SJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 569*3d3b0591SJens Wiklander 570*3d3b0591SJens Wiklander #endif /* !MBEDTLS_CHACHA20_C */ 571