Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers chacha20.c Source File

chacha20.c

Go to the documentation of this file.
00001 /**
00002  * \file chacha20.c
00003  *
00004  * \brief ChaCha20 cipher.
00005  *
00006  * \author Daniel King <damaki.gh@gmail.com>
00007  *
00008  *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
00009  *  SPDX-License-Identifier: Apache-2.0
00010  *
00011  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00012  *  not use this file except in compliance with the License.
00013  *  You may obtain a copy of the License at
00014  *
00015  *  http://www.apache.org/licenses/LICENSE-2.0
00016  *
00017  *  Unless required by applicable law or agreed to in writing, software
00018  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00019  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020  *  See the License for the specific language governing permissions and
00021  *  limitations under the License.
00022  *
00023  *  This file is part of mbed TLS (https://tls.mbed.org)
00024  */
00025 
00026 #if !defined(MBEDTLS_CONFIG_FILE)
00027 #include "mbedtls/config.h"
00028 #else
00029 #include MBEDTLS_CONFIG_FILE
00030 #endif
00031 
00032 #if defined(MBEDTLS_CHACHA20_C)
00033 
00034 #include "mbedtls/chacha20.h"
00035 #include "mbedtls/platform_util.h"
00036 
00037 #include <stddef.h>
00038 #include <string.h>
00039 
00040 #if defined(MBEDTLS_SELF_TEST)
00041 #if defined(MBEDTLS_PLATFORM_C)
00042 #include "mbedtls/platform.h"
00043 #else
00044 #include <stdio.h>
00045 #define mbedtls_printf printf
00046 #endif /* MBEDTLS_PLATFORM_C */
00047 #endif /* MBEDTLS_SELF_TEST */
00048 
00049 #if !defined(MBEDTLS_CHACHA20_ALT)
00050 
00051 #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
00052     !defined(inline) && !defined(__cplusplus)
00053 #define inline __inline
00054 #endif
00055 
00056 /* Parameter validation macros */
00057 #define CHACHA20_VALIDATE_RET( cond )                                       \
00058     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
00059 #define CHACHA20_VALIDATE( cond )                                           \
00060     MBEDTLS_INTERNAL_VALIDATE( cond )
00061 
00062 #define BYTES_TO_U32_LE( data, offset )                           \
00063     ( (uint32_t) (data)[offset]                                   \
00064       | (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 )     \
00065       | (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 )    \
00066       | (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 )    \
00067     )
00068 
00069 #define ROTL32( value, amount ) \
00070     ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
00071 
00072 #define CHACHA20_CTR_INDEX ( 12U )
00073 
00074 #define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U )
00075 
00076 /**
00077  * \brief           ChaCha20 quarter round operation.
00078  *
00079  *                  The quarter round is defined as follows (from RFC 7539):
00080  *                      1.  a += b; d ^= a; d <<<= 16;
00081  *                      2.  c += d; b ^= c; b <<<= 12;
00082  *                      3.  a += b; d ^= a; d <<<= 8;
00083  *                      4.  c += d; b ^= c; b <<<= 7;
00084  *
00085  * \param state     ChaCha20 state to modify.
00086  * \param a         The index of 'a' in the state.
00087  * \param b         The index of 'b' in the state.
00088  * \param c         The index of 'c' in the state.
00089  * \param d         The index of 'd' in the state.
00090  */
00091 static inline void chacha20_quarter_round( uint32_t state[16],
00092                                            size_t a,
00093                                            size_t b,
00094                                            size_t c,
00095                                            size_t d )
00096 {
00097     /* a += b; d ^= a; d <<<= 16; */
00098     state[a] += state[b];
00099     state[d] ^= state[a];
00100     state[d] = ROTL32( state[d], 16 );
00101 
00102     /* c += d; b ^= c; b <<<= 12 */
00103     state[c] += state[d];
00104     state[b] ^= state[c];
00105     state[b] = ROTL32( state[b], 12 );
00106 
00107     /* a += b; d ^= a; d <<<= 8; */
00108     state[a] += state[b];
00109     state[d] ^= state[a];
00110     state[d] = ROTL32( state[d], 8 );
00111 
00112     /* c += d; b ^= c; b <<<= 7; */
00113     state[c] += state[d];
00114     state[b] ^= state[c];
00115     state[b] = ROTL32( state[b], 7 );
00116 }
00117 
00118 /**
00119  * \brief           Perform the ChaCha20 inner block operation.
00120  *
00121  *                  This function performs two rounds: the column round and the
00122  *                  diagonal round.
00123  *
00124  * \param state     The ChaCha20 state to update.
00125  */
00126 static void chacha20_inner_block( uint32_t state[16] )
00127 {
00128     chacha20_quarter_round( state, 0, 4, 8,  12 );
00129     chacha20_quarter_round( state, 1, 5, 9,  13 );
00130     chacha20_quarter_round( state, 2, 6, 10, 14 );
00131     chacha20_quarter_round( state, 3, 7, 11, 15 );
00132 
00133     chacha20_quarter_round( state, 0, 5, 10, 15 );
00134     chacha20_quarter_round( state, 1, 6, 11, 12 );
00135     chacha20_quarter_round( state, 2, 7, 8,  13 );
00136     chacha20_quarter_round( state, 3, 4, 9,  14 );
00137 }
00138 
00139 /**
00140  * \brief               Generates a keystream block.
00141  *
00142  * \param initial_state The initial ChaCha20 state (key, nonce, counter).
00143  * \param keystream     Generated keystream bytes are written to this buffer.
00144  */
00145 static void chacha20_block( const uint32_t initial_state[16],
00146                             unsigned char keystream[64] )
00147 {
00148     uint32_t working_state[16];
00149     size_t i;
00150 
00151     memcpy( working_state,
00152             initial_state,
00153             CHACHA20_BLOCK_SIZE_BYTES );
00154 
00155     for( i = 0U; i < 10U; i++ )
00156         chacha20_inner_block( working_state );
00157 
00158     working_state[ 0] += initial_state[ 0];
00159     working_state[ 1] += initial_state[ 1];
00160     working_state[ 2] += initial_state[ 2];
00161     working_state[ 3] += initial_state[ 3];
00162     working_state[ 4] += initial_state[ 4];
00163     working_state[ 5] += initial_state[ 5];
00164     working_state[ 6] += initial_state[ 6];
00165     working_state[ 7] += initial_state[ 7];
00166     working_state[ 8] += initial_state[ 8];
00167     working_state[ 9] += initial_state[ 9];
00168     working_state[10] += initial_state[10];
00169     working_state[11] += initial_state[11];
00170     working_state[12] += initial_state[12];
00171     working_state[13] += initial_state[13];
00172     working_state[14] += initial_state[14];
00173     working_state[15] += initial_state[15];
00174 
00175     for( i = 0U; i < 16; i++ )
00176     {
00177         size_t offset = i * 4U;
00178 
00179         keystream[offset     ] = (unsigned char)( working_state[i]       );
00180         keystream[offset + 1U] = (unsigned char)( working_state[i] >>  8 );
00181         keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 );
00182         keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 );
00183     }
00184 
00185     mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
00186 }
00187 
00188 void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
00189 {
00190     CHACHA20_VALIDATE( ctx != NULL );
00191 
00192     mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
00193     mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
00194 
00195     /* Initially, there's no keystream bytes available */
00196     ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
00197 }
00198 
00199 void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
00200 {
00201     if( ctx != NULL )
00202     {
00203         mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) );
00204     }
00205 }
00206 
00207 int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
00208                             const unsigned char key[32] )
00209 {
00210     CHACHA20_VALIDATE_RET( ctx != NULL );
00211     CHACHA20_VALIDATE_RET( key != NULL );
00212 
00213     /* ChaCha20 constants - the string "expand 32-byte k" */
00214     ctx->state[0] = 0x61707865;
00215     ctx->state[1] = 0x3320646e;
00216     ctx->state[2] = 0x79622d32;
00217     ctx->state[3] = 0x6b206574;
00218 
00219     /* Set key */
00220     ctx->state[4]  = BYTES_TO_U32_LE( key, 0 );
00221     ctx->state[5]  = BYTES_TO_U32_LE( key, 4 );
00222     ctx->state[6]  = BYTES_TO_U32_LE( key, 8 );
00223     ctx->state[7]  = BYTES_TO_U32_LE( key, 12 );
00224     ctx->state[8]  = BYTES_TO_U32_LE( key, 16 );
00225     ctx->state[9]  = BYTES_TO_U32_LE( key, 20 );
00226     ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
00227     ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
00228 
00229     return( 0 );
00230 }
00231 
00232 int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
00233                              const unsigned char nonce[12],
00234                              uint32_t counter )
00235 {
00236     CHACHA20_VALIDATE_RET( ctx != NULL );
00237     CHACHA20_VALIDATE_RET( nonce != NULL );
00238 
00239     /* Counter */
00240     ctx->state[12] = counter;
00241 
00242     /* Nonce */
00243     ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
00244     ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
00245     ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 );
00246 
00247     mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
00248 
00249     /* Initially, there's no keystream bytes available */
00250     ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
00251 
00252     return( 0 );
00253 }
00254 
00255 int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
00256                               size_t size,
00257                               const unsigned char *input,
00258                               unsigned char *output )
00259 {
00260     size_t offset = 0U;
00261     size_t i;
00262 
00263     CHACHA20_VALIDATE_RET( ctx != NULL );
00264     CHACHA20_VALIDATE_RET( size == 0 || input  != NULL );
00265     CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
00266 
00267     /* Use leftover keystream bytes, if available */
00268     while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
00269     {
00270         output[offset] = input[offset]
00271                        ^ ctx->keystream8[ctx->keystream_bytes_used];
00272 
00273         ctx->keystream_bytes_used++;
00274         offset++;
00275         size--;
00276     }
00277 
00278     /* Process full blocks */
00279     while( size >= CHACHA20_BLOCK_SIZE_BYTES )
00280     {
00281         /* Generate new keystream block and increment counter */
00282         chacha20_block( ctx->state, ctx->keystream8 );
00283         ctx->state[CHACHA20_CTR_INDEX]++;
00284 
00285         for( i = 0U; i < 64U; i += 8U )
00286         {
00287             output[offset + i  ] = input[offset + i  ] ^ ctx->keystream8[i  ];
00288             output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
00289             output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
00290             output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
00291             output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
00292             output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
00293             output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
00294             output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
00295         }
00296 
00297         offset += CHACHA20_BLOCK_SIZE_BYTES;
00298         size   -= CHACHA20_BLOCK_SIZE_BYTES;
00299     }
00300 
00301     /* Last (partial) block */
00302     if( size > 0U )
00303     {
00304         /* Generate new keystream block and increment counter */
00305         chacha20_block( ctx->state, ctx->keystream8 );
00306         ctx->state[CHACHA20_CTR_INDEX]++;
00307 
00308         for( i = 0U; i < size; i++)
00309         {
00310             output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
00311         }
00312 
00313         ctx->keystream_bytes_used = size;
00314 
00315     }
00316 
00317     return( 0 );
00318 }
00319 
00320 int mbedtls_chacha20_crypt( const unsigned char key[32],
00321                             const unsigned char nonce[12],
00322                             uint32_t counter,
00323                             size_t data_len,
00324                             const unsigned char* input,
00325                             unsigned char* output )
00326 {
00327     mbedtls_chacha20_context ctx;
00328     int ret;
00329 
00330     CHACHA20_VALIDATE_RET( key != NULL );
00331     CHACHA20_VALIDATE_RET( nonce != NULL );
00332     CHACHA20_VALIDATE_RET( data_len == 0 || input  != NULL );
00333     CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
00334 
00335     mbedtls_chacha20_init( &ctx );
00336 
00337     ret = mbedtls_chacha20_setkey( &ctx, key );
00338     if( ret != 0 )
00339         goto cleanup;
00340 
00341     ret = mbedtls_chacha20_starts( &ctx, nonce, counter );
00342     if( ret != 0 )
00343         goto cleanup;
00344 
00345     ret = mbedtls_chacha20_update( &ctx, data_len, input, output );
00346 
00347 cleanup:
00348     mbedtls_chacha20_free( &ctx );
00349     return( ret );
00350 }
00351 
00352 #endif /* !MBEDTLS_CHACHA20_ALT */
00353 
00354 #if defined(MBEDTLS_SELF_TEST)
00355 
00356 static const unsigned char test_keys[2][32] =
00357 {
00358     {
00359         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00360         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00361         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00362         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00363     },
00364     {
00365         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00366         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00367         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00368         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
00369     }
00370 };
00371 
00372 static const unsigned char test_nonces[2][12] =
00373 {
00374     {
00375         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00376         0x00, 0x00, 0x00, 0x00
00377     },
00378     {
00379         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00380         0x00, 0x00, 0x00, 0x02
00381     }
00382 };
00383 
00384 static const uint32_t test_counters[2] =
00385 {
00386     0U,
00387     1U
00388 };
00389 
00390 static const unsigned char test_input[2][375] =
00391 {
00392     {
00393         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00394         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00395         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00396         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00397         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00398         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00399         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00400         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00401     },
00402     {
00403         0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
00404         0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
00405         0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
00406         0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
00407         0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
00408         0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
00409         0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
00410         0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
00411         0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
00412         0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
00413         0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
00414         0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
00415         0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
00416         0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
00417         0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
00418         0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
00419         0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
00420         0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
00421         0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
00422         0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
00423         0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
00424         0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
00425         0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
00426         0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
00427         0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
00428         0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
00429         0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
00430         0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
00431         0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
00432         0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
00433         0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
00434         0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
00435         0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
00436         0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
00437         0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
00438         0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
00439         0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
00440         0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
00441         0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
00442         0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
00443         0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
00444         0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
00445         0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
00446         0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
00447         0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
00448         0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
00449         0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
00450     }
00451 };
00452 
00453 static const unsigned char test_output[2][375] =
00454 {
00455     {
00456         0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
00457         0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
00458         0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
00459         0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
00460         0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
00461         0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
00462         0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
00463         0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
00464     },
00465     {
00466         0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
00467         0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
00468         0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
00469         0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
00470         0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
00471         0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
00472         0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
00473         0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
00474         0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
00475         0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
00476         0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
00477         0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
00478         0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
00479         0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
00480         0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
00481         0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
00482         0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
00483         0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
00484         0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
00485         0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
00486         0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
00487         0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
00488         0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
00489         0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
00490         0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
00491         0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
00492         0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
00493         0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
00494         0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
00495         0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
00496         0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
00497         0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
00498         0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
00499         0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
00500         0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
00501         0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
00502         0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
00503         0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
00504         0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
00505         0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
00506         0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
00507         0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
00508         0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
00509         0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
00510         0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
00511         0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
00512         0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
00513     }
00514 };
00515 
00516 static const size_t test_lengths[2] =
00517 {
00518     64U,
00519     375U
00520 };
00521 
00522 #define ASSERT( cond, args )            \
00523     do                                  \
00524     {                                   \
00525         if( ! ( cond ) )                \
00526         {                               \
00527             if( verbose != 0 )          \
00528                 mbedtls_printf args;    \
00529                                         \
00530             return( -1 );               \
00531         }                               \
00532     }                                   \
00533     while( 0 )
00534 
00535 int mbedtls_chacha20_self_test( int verbose )
00536 {
00537     unsigned char output[381];
00538     unsigned i;
00539     int ret;
00540 
00541     for( i = 0U; i < 2U; i++ )
00542     {
00543         if( verbose != 0 )
00544             mbedtls_printf( "  ChaCha20 test %u ", i );
00545 
00546         ret = mbedtls_chacha20_crypt( test_keys[i],
00547                                       test_nonces[i],
00548                                       test_counters[i],
00549                                       test_lengths[i],
00550                                       test_input[i],
00551                                       output );
00552 
00553         ASSERT( 0 == ret, ( "error code: %i\n", ret ) );
00554 
00555         ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ),
00556                 ( "failed (output)\n" ) );
00557 
00558         if( verbose != 0 )
00559             mbedtls_printf( "passed\n" );
00560     }
00561 
00562     if( verbose != 0 )
00563         mbedtls_printf( "\n" );
00564 
00565     return( 0 );
00566 }
00567 
00568 #endif /* MBEDTLS_SELF_TEST */
00569 
00570 #endif /* !MBEDTLS_CHACHA20_C */