Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers chachapoly.c Source File

chachapoly.c

Go to the documentation of this file.
00001 /**
00002  * \file chachapoly.c
00003  *
00004  * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
00005  *
00006  *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
00007  *  SPDX-License-Identifier: Apache-2.0
00008  *
00009  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  *  not use this file except in compliance with the License.
00011  *  You may obtain a copy of the License at
00012  *
00013  *  http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  *  Unless required by applicable law or agreed to in writing, software
00016  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  *  See the License for the specific language governing permissions and
00019  *  limitations under the License.
00020  *
00021  *  This file is part of mbed TLS (https://tls.mbed.org)
00022  */
00023 #if !defined(MBEDTLS_CONFIG_FILE)
00024 #include "mbedtls/config.h"
00025 #else
00026 #include MBEDTLS_CONFIG_FILE
00027 #endif
00028 
00029 #if defined(MBEDTLS_CHACHAPOLY_C)
00030 
00031 #include "mbedtls/chachapoly.h"
00032 #include "mbedtls/platform_util.h"
00033 
00034 #include <string.h>
00035 
00036 #if defined(MBEDTLS_SELF_TEST)
00037 #if defined(MBEDTLS_PLATFORM_C)
00038 #include "mbedtls/platform.h"
00039 #else
00040 #include <stdio.h>
00041 #define mbedtls_printf printf
00042 #endif /* MBEDTLS_PLATFORM_C */
00043 #endif /* MBEDTLS_SELF_TEST */
00044 
00045 #if !defined(MBEDTLS_CHACHAPOLY_ALT)
00046 
00047 #define CHACHAPOLY_STATE_INIT       ( 0 )
00048 #define CHACHAPOLY_STATE_AAD        ( 1 )
00049 #define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
00050 #define CHACHAPOLY_STATE_FINISHED   ( 3 )
00051 
00052 /**
00053  * \brief           Adds nul bytes to pad the AAD for Poly1305.
00054  *
00055  * \param ctx       The ChaCha20-Poly1305 context.
00056  */
00057 static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
00058 {
00059     uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
00060     unsigned char zeroes[15];
00061 
00062     if( partial_block_len == 0U )
00063         return( 0 );
00064 
00065     memset( zeroes, 0, sizeof( zeroes ) );
00066 
00067     return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
00068                                      zeroes,
00069                                      16U - partial_block_len ) );
00070 }
00071 
00072 /**
00073  * \brief           Adds nul bytes to pad the ciphertext for Poly1305.
00074  *
00075  * \param ctx       The ChaCha20-Poly1305 context.
00076  */
00077 static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
00078 {
00079     uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
00080     unsigned char zeroes[15];
00081 
00082     if( partial_block_len == 0U )
00083         return( 0 );
00084 
00085     memset( zeroes, 0, sizeof( zeroes ) );
00086     return( mbedtls_poly1305_update( &ctx->poly1305_ctx,
00087                                      zeroes,
00088                                      16U - partial_block_len ) );
00089 }
00090 
00091 void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
00092 {
00093     if( ctx != NULL )
00094     {
00095         mbedtls_chacha20_init( &ctx->chacha20_ctx );
00096         mbedtls_poly1305_init( &ctx->poly1305_ctx );
00097         ctx->aad_len        = 0U;
00098         ctx->ciphertext_len = 0U;
00099         ctx->state          = CHACHAPOLY_STATE_INIT;
00100         ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
00101     }
00102 }
00103 
00104 void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
00105 {
00106     if( ctx != NULL )
00107     {
00108         mbedtls_chacha20_free( &ctx->chacha20_ctx );
00109         mbedtls_poly1305_free( &ctx->poly1305_ctx );
00110         ctx->aad_len        = 0U;
00111         ctx->ciphertext_len = 0U;
00112         ctx->state          = CHACHAPOLY_STATE_INIT;
00113         ctx->mode           = MBEDTLS_CHACHAPOLY_ENCRYPT;
00114     }
00115 }
00116 
00117 int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
00118                                const unsigned char key[32] )
00119 {
00120     int ret;
00121 
00122     if( ( ctx == NULL ) || ( key == NULL ) )
00123     {
00124         return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
00125     }
00126 
00127     ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
00128 
00129     return( ret );
00130 }
00131 
00132 int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
00133                                const unsigned char nonce[12],
00134                                mbedtls_chachapoly_mode_t  mode  )
00135 {
00136     int ret;
00137     unsigned char poly1305_key[64];
00138 
00139     if( ( ctx == NULL ) || ( nonce == NULL ) )
00140     {
00141         return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
00142     }
00143 
00144     /* Set counter = 0, will be update to 1 when generating Poly1305 key */
00145     ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
00146     if( ret != 0 )
00147         goto cleanup;
00148 
00149     /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
00150      * counter = 0.  This is the same as encrypting a buffer of zeroes.
00151      * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
00152      * The other 256 bits are discarded.
00153      */
00154     memset( poly1305_key, 0, sizeof( poly1305_key ) );
00155     ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
00156                                       poly1305_key, poly1305_key );
00157     if( ret != 0 )
00158         goto cleanup;
00159 
00160     ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
00161 
00162     if( ret == 0 )
00163     {
00164         ctx->aad_len        = 0U;
00165         ctx->ciphertext_len = 0U;
00166         ctx->state          = CHACHAPOLY_STATE_AAD;
00167         ctx->mode           = mode;
00168     }
00169 
00170 cleanup:
00171     mbedtls_platform_zeroize( poly1305_key, 64U );
00172     return( ret );
00173 }
00174 
00175 int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
00176                                    const unsigned char *aad,
00177                                    size_t aad_len )
00178 {
00179     if( ctx == NULL )
00180     {
00181         return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
00182     }
00183     else if( ( aad_len > 0U ) && ( aad == NULL ) )
00184     {
00185         /* aad pointer is allowed to be NULL if aad_len == 0 */
00186         return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
00187     }
00188     else if( ctx->state != CHACHAPOLY_STATE_AAD )
00189     {
00190         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
00191     }
00192 
00193     ctx->aad_len += aad_len;
00194 
00195     return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
00196 }
00197 
00198 int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
00199                                size_t len,
00200                                const unsigned char *input,
00201                                unsigned char *output )
00202 {
00203     int ret;
00204 
00205     if( ctx == NULL )
00206     {
00207         return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
00208     }
00209     else if( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) )
00210     {
00211         /* input and output pointers are allowed to be NULL if len == 0 */
00212         return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
00213     }
00214     else if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
00215               ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
00216     {
00217         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
00218     }
00219 
00220     if( ctx->state == CHACHAPOLY_STATE_AAD )
00221     {
00222         ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
00223 
00224         ret = chachapoly_pad_aad( ctx );
00225         if( ret != 0 )
00226             return( ret );
00227     }
00228 
00229     ctx->ciphertext_len += len;
00230 
00231     if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
00232     {
00233         ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
00234         if( ret != 0 )
00235             return( ret );
00236 
00237         ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len );
00238         if( ret != 0 )
00239             return( ret );
00240     }
00241     else /* DECRYPT */
00242     {
00243         ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len );
00244         if( ret != 0 )
00245             return( ret );
00246 
00247         ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output );
00248         if( ret != 0 )
00249             return( ret );
00250     }
00251 
00252     return( 0 );
00253 }
00254 
00255 int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
00256                                unsigned char mac[16] )
00257 {
00258     int ret;
00259     unsigned char len_block[16];
00260 
00261     if( ( ctx == NULL ) || ( mac == NULL ) )
00262     {
00263         return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
00264     }
00265     else if( ctx->state == CHACHAPOLY_STATE_INIT )
00266     {
00267         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
00268     }
00269 
00270     if( ctx->state == CHACHAPOLY_STATE_AAD )
00271     {
00272         ret = chachapoly_pad_aad( ctx );
00273         if( ret != 0 )
00274             return( ret );
00275     }
00276     else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
00277     {
00278         ret = chachapoly_pad_ciphertext( ctx );
00279         if( ret != 0 )
00280             return( ret );
00281     }
00282 
00283     ctx->state = CHACHAPOLY_STATE_FINISHED;
00284 
00285     /* The lengths of the AAD and ciphertext are processed by
00286      * Poly1305 as the final 128-bit block, encoded as little-endian integers.
00287      */
00288     len_block[ 0] = (unsigned char)( ctx->aad_len       );
00289     len_block[ 1] = (unsigned char)( ctx->aad_len >>  8 );
00290     len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
00291     len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
00292     len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
00293     len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
00294     len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
00295     len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
00296     len_block[ 8] = (unsigned char)( ctx->ciphertext_len       );
00297     len_block[ 9] = (unsigned char)( ctx->ciphertext_len >>  8 );
00298     len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
00299     len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
00300     len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
00301     len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
00302     len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
00303     len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
00304 
00305     ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
00306     if( ret != 0 )
00307         return( ret );
00308 
00309     ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
00310 
00311     return( ret );
00312 }
00313 
00314 static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
00315                                      mbedtls_chachapoly_mode_t  mode,
00316                                      size_t length,
00317                                      const unsigned char nonce[12],
00318                                      const unsigned char *aad,
00319                                      size_t aad_len,
00320                                      const unsigned char *input,
00321                                      unsigned char *output,
00322                                      unsigned char tag[16] )
00323 {
00324     int ret;
00325 
00326     ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
00327     if( ret != 0 )
00328         goto cleanup;
00329 
00330     ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
00331     if( ret != 0 )
00332         goto cleanup;
00333 
00334     ret = mbedtls_chachapoly_update( ctx, length, input, output );
00335     if( ret != 0 )
00336         goto cleanup;
00337 
00338     ret = mbedtls_chachapoly_finish( ctx, tag );
00339 
00340 cleanup:
00341     return( ret );
00342 }
00343 
00344 int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
00345                                         size_t length,
00346                                         const unsigned char nonce[12],
00347                                         const unsigned char *aad,
00348                                         size_t aad_len,
00349                                         const unsigned char *input,
00350                                         unsigned char *output,
00351                                         unsigned char tag[16] )
00352 {
00353     return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
00354                                       length, nonce, aad, aad_len,
00355                                       input, output, tag ) );
00356 }
00357 
00358 int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
00359                                      size_t length,
00360                                      const unsigned char nonce[12],
00361                                      const unsigned char *aad,
00362                                      size_t aad_len,
00363                                      const unsigned char tag[16],
00364                                      const unsigned char *input,
00365                                      unsigned char *output )
00366 {
00367     int ret;
00368     unsigned char check_tag[16];
00369     size_t i;
00370     int diff;
00371 
00372     if( tag == NULL )
00373         return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA );
00374 
00375     if( ( ret = chachapoly_crypt_and_tag( ctx,
00376                         MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
00377                         aad, aad_len, input, output, check_tag ) ) != 0 )
00378     {
00379         return( ret );
00380     }
00381 
00382     /* Check tag in "constant-time" */
00383     for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
00384         diff |= tag[i] ^ check_tag[i];
00385 
00386     if( diff != 0 )
00387     {
00388         mbedtls_platform_zeroize( output, length );
00389         return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
00390     }
00391 
00392     return( 0 );
00393 }
00394 
00395 #endif /* MBEDTLS_CHACHAPOLY_ALT */
00396 
00397 #if defined(MBEDTLS_SELF_TEST)
00398 
00399 static const unsigned char test_key[1][32] =
00400 {
00401     {
00402         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
00403         0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
00404         0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
00405         0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
00406     }
00407 };
00408 
00409 static const unsigned char test_nonce[1][12] =
00410 {
00411     {
00412         0x07, 0x00, 0x00, 0x00,                         /* 32-bit common part */
00413         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47  /* 64-bit IV */
00414     }
00415 };
00416 
00417 static const unsigned char test_aad[1][12] =
00418 {
00419     {
00420         0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
00421         0xc4, 0xc5, 0xc6, 0xc7
00422     }
00423 };
00424 
00425 static const size_t test_aad_len[1] =
00426 {
00427     12U
00428 };
00429 
00430 static const unsigned char test_input[1][114] =
00431 {
00432     {
00433         0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
00434         0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
00435         0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
00436         0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
00437         0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
00438         0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
00439         0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
00440         0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
00441         0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
00442         0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
00443         0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
00444         0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
00445         0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
00446         0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
00447         0x74, 0x2e
00448     }
00449 };
00450 
00451 static const unsigned char test_output[1][114] =
00452 {
00453     {
00454         0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
00455         0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
00456         0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
00457         0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
00458         0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
00459         0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
00460         0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
00461         0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
00462         0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
00463         0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
00464         0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
00465         0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
00466         0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
00467         0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
00468         0x61, 0x16
00469     }
00470 };
00471 
00472 static const size_t test_input_len[1] =
00473 {
00474     114U
00475 };
00476 
00477 static const unsigned char test_mac[1][16] =
00478 {
00479     {
00480         0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
00481         0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
00482     }
00483 };
00484 
00485 #define ASSERT( cond, args )            \
00486     do                                  \
00487     {                                   \
00488         if( ! ( cond ) )                \
00489         {                               \
00490             if( verbose != 0 )          \
00491                 mbedtls_printf args;    \
00492                                         \
00493             return( -1 );               \
00494         }                               \
00495     }                                   \
00496     while( 0 )
00497 
00498 int mbedtls_chachapoly_self_test( int verbose )
00499 {
00500     mbedtls_chachapoly_context ctx;
00501     unsigned i;
00502     int ret;
00503     unsigned char output[200];
00504     unsigned char mac[16];
00505 
00506     for( i = 0U; i < 1U; i++ )
00507     {
00508         if( verbose != 0 )
00509             mbedtls_printf( "  ChaCha20-Poly1305 test %u ", i );
00510 
00511         mbedtls_chachapoly_init( &ctx );
00512 
00513         ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
00514         ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
00515 
00516         ret = mbedtls_chachapoly_encrypt_and_tag( &ctx,
00517                                                   test_input_len[i],
00518                                                   test_nonce[i],
00519                                                   test_aad[i],
00520                                                   test_aad_len[i],
00521                                                   test_input[i],
00522                                                   output,
00523                                                   mac );
00524 
00525         ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
00526 
00527         ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ),
00528                 ( "failure (wrong output)\n" ) );
00529 
00530         ASSERT( 0 == memcmp( mac, test_mac[i], 16U ),
00531                 ( "failure (wrong MAC)\n" ) );
00532 
00533         mbedtls_chachapoly_free( &ctx );
00534 
00535         if( verbose != 0 )
00536             mbedtls_printf( "passed\n" );
00537     }
00538 
00539     if( verbose != 0 )
00540         mbedtls_printf( "\n" );
00541 
00542     return( 0 );
00543 }
00544 
00545 #endif /* MBEDTLS_SELF_TEST */
00546 
00547 #endif /* MBEDTLS_CHACHAPOLY_C */