Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cipher.c Source File

cipher.c

Go to the documentation of this file.
00001 /**
00002  * \file cipher.c
00003  *
00004  * \brief Generic cipher wrapper for mbed TLS
00005  *
00006  * \author Adriaan de Jong <dejong@fox-it.com>
00007  *
00008  *  Copyright (C) 2006-2015, 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_CIPHER_C)
00033 
00034 #include "mbedtls/cipher.h"
00035 #include "mbedtls/cipher_internal.h"
00036 #include "mbedtls/platform_util.h"
00037 
00038 #include <stdlib.h>
00039 #include <string.h>
00040 
00041 #if defined(MBEDTLS_GCM_C)
00042 #include "mbedtls/gcm.h"
00043 #endif
00044 
00045 #if defined(MBEDTLS_CCM_C)
00046 #include "mbedtls/ccm.h"
00047 #endif
00048 
00049 #if defined(MBEDTLS_CMAC_C)
00050 #include "mbedtls/cmac.h"
00051 #endif
00052 
00053 #if defined(MBEDTLS_PLATFORM_C)
00054 #include "mbedtls/platform.h"
00055 #else
00056 #define mbedtls_calloc calloc
00057 #define mbedtls_free   free
00058 #endif
00059 
00060 #if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
00061 #define MBEDTLS_CIPHER_MODE_STREAM
00062 #endif
00063 
00064 static int supported_init = 0;
00065 
00066 const int *mbedtls_cipher_list( void )
00067 {
00068     const mbedtls_cipher_definition_t *def;
00069     int *type;
00070 
00071     if( ! supported_init )
00072     {
00073         def = mbedtls_cipher_definitions;
00074         type = mbedtls_cipher_supported;
00075 
00076         while( def->type != 0 )
00077             *type++ = (*def++).type;
00078 
00079         *type = 0;
00080 
00081         supported_init = 1;
00082     }
00083 
00084     return( mbedtls_cipher_supported );
00085 }
00086 
00087 const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type )
00088 {
00089     const mbedtls_cipher_definition_t *def;
00090 
00091     for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
00092         if( def->type == cipher_type )
00093             return( def->info );
00094 
00095     return( NULL );
00096 }
00097 
00098 const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name )
00099 {
00100     const mbedtls_cipher_definition_t *def;
00101 
00102     if( NULL == cipher_name )
00103         return( NULL );
00104 
00105     for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
00106         if( !  strcmp( def->info->name, cipher_name ) )
00107             return( def->info );
00108 
00109     return( NULL );
00110 }
00111 
00112 const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id,
00113                                               int key_bitlen,
00114                                               const mbedtls_cipher_mode_t mode )
00115 {
00116     const mbedtls_cipher_definition_t *def;
00117 
00118     for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
00119         if( def->info->base->cipher == cipher_id &&
00120             def->info->key_bitlen == (unsigned) key_bitlen &&
00121             def->info->mode == mode )
00122             return( def->info );
00123 
00124     return( NULL );
00125 }
00126 
00127 void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx )
00128 {
00129     memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
00130 }
00131 
00132 void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx )
00133 {
00134     if( ctx == NULL )
00135         return;
00136 
00137 #if defined(MBEDTLS_CMAC_C)
00138     if( ctx->cmac_ctx )
00139     {
00140        mbedtls_platform_zeroize( ctx->cmac_ctx,
00141                                  sizeof( mbedtls_cmac_context_t ) );
00142        mbedtls_free( ctx->cmac_ctx );
00143     }
00144 #endif
00145 
00146     if( ctx->cipher_ctx )
00147         ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
00148 
00149     mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
00150 }
00151 
00152 int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info )
00153 {
00154     if( NULL == cipher_info || NULL == ctx )
00155         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00156 
00157     memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
00158 
00159     if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
00160         return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
00161 
00162     ctx->cipher_info = cipher_info;
00163 
00164 #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
00165     /*
00166      * Ignore possible errors caused by a cipher mode that doesn't use padding
00167      */
00168 #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
00169     (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 );
00170 #else
00171     (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE );
00172 #endif
00173 #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
00174 
00175     return( 0 );
00176 }
00177 
00178 int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key,
00179         int key_bitlen, const mbedtls_operation_t operation )
00180 {
00181     if( NULL == ctx || NULL == ctx->cipher_info )
00182         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00183 
00184     if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
00185         (int) ctx->cipher_info->key_bitlen != key_bitlen )
00186     {
00187         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00188     }
00189 
00190     ctx->key_bitlen = key_bitlen;
00191     ctx->operation = operation;
00192 
00193     /*
00194      * For CFB and CTR mode always use the encryption key schedule
00195      */
00196     if( MBEDTLS_ENCRYPT == operation ||
00197         MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
00198         MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
00199     {
00200         return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
00201                 ctx->key_bitlen );
00202     }
00203 
00204     if( MBEDTLS_DECRYPT == operation )
00205         return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
00206                 ctx->key_bitlen );
00207 
00208     return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00209 }
00210 
00211 int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
00212                    const unsigned char *iv, size_t iv_len )
00213 {
00214     size_t actual_iv_size;
00215 
00216     if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
00217         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00218 
00219     /* avoid buffer overflow in ctx->iv */
00220     if( iv_len > MBEDTLS_MAX_IV_LENGTH )
00221         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
00222 
00223     if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 )
00224         actual_iv_size = iv_len;
00225     else
00226     {
00227         actual_iv_size = ctx->cipher_info->iv_size;
00228 
00229         /* avoid reading past the end of input buffer */
00230         if( actual_iv_size > iv_len )
00231             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00232     }
00233 
00234     memcpy( ctx->iv, iv, actual_iv_size );
00235     ctx->iv_size = actual_iv_size;
00236 
00237     return( 0 );
00238 }
00239 
00240 int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
00241 {
00242     if( NULL == ctx || NULL == ctx->cipher_info )
00243         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00244 
00245     ctx->unprocessed_len = 0;
00246 
00247     return( 0 );
00248 }
00249 
00250 #if defined(MBEDTLS_GCM_C)
00251 int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
00252                       const unsigned char *ad, size_t ad_len )
00253 {
00254     if( NULL == ctx || NULL == ctx->cipher_info )
00255         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00256 
00257     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
00258     {
00259         return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
00260                            ctx->iv, ctx->iv_size, ad, ad_len );
00261     }
00262 
00263     return( 0 );
00264 }
00265 #endif /* MBEDTLS_GCM_C */
00266 
00267 int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
00268                    size_t ilen, unsigned char *output, size_t *olen )
00269 {
00270     int ret;
00271     size_t block_size = 0;
00272 
00273     if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
00274     {
00275         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00276     }
00277 
00278     *olen = 0;
00279     block_size = mbedtls_cipher_get_block_size( ctx );
00280 
00281     if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB )
00282     {
00283         if( ilen != block_size )
00284             return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
00285 
00286         *olen = ilen;
00287 
00288         if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
00289                     ctx->operation, input, output ) ) )
00290         {
00291             return( ret );
00292         }
00293 
00294         return( 0 );
00295     }
00296 
00297 #if defined(MBEDTLS_GCM_C)
00298     if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM )
00299     {
00300         *olen = ilen;
00301         return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input,
00302                            output );
00303     }
00304 #endif
00305 
00306     if ( 0 == block_size )
00307     {
00308         return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
00309     }
00310 
00311     if( input == output &&
00312        ( ctx->unprocessed_len != 0 || ilen % block_size ) )
00313     {
00314         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00315     }
00316 
00317 #if defined(MBEDTLS_CIPHER_MODE_CBC)
00318     if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC )
00319     {
00320         size_t copy_len = 0;
00321 
00322         /*
00323          * If there is not enough data for a full block, cache it.
00324          */
00325         if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding &&
00326                 ilen <= block_size - ctx->unprocessed_len ) ||
00327             ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding &&
00328                 ilen < block_size - ctx->unprocessed_len ) ||
00329              ( ctx->operation == MBEDTLS_ENCRYPT &&
00330                 ilen < block_size - ctx->unprocessed_len ) )
00331         {
00332             memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
00333                     ilen );
00334 
00335             ctx->unprocessed_len += ilen;
00336             return( 0 );
00337         }
00338 
00339         /*
00340          * Process cached data first
00341          */
00342         if( 0 != ctx->unprocessed_len )
00343         {
00344             copy_len = block_size - ctx->unprocessed_len;
00345 
00346             memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
00347                     copy_len );
00348 
00349             if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
00350                     ctx->operation, block_size, ctx->iv,
00351                     ctx->unprocessed_data, output ) ) )
00352             {
00353                 return( ret );
00354             }
00355 
00356             *olen += block_size;
00357             output += block_size;
00358             ctx->unprocessed_len = 0;
00359 
00360             input += copy_len;
00361             ilen -= copy_len;
00362         }
00363 
00364         /*
00365          * Cache final, incomplete block
00366          */
00367         if( 0 != ilen )
00368         {
00369             if( 0 == block_size )
00370             {
00371                 return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
00372             }
00373 
00374             /* Encryption: only cache partial blocks
00375              * Decryption w/ padding: always keep at least one whole block
00376              * Decryption w/o padding: only cache partial blocks
00377              */
00378             copy_len = ilen % block_size;
00379             if( copy_len == 0 &&
00380                 ctx->operation == MBEDTLS_DECRYPT &&
00381                 NULL != ctx->add_padding)
00382             {
00383                 copy_len = block_size;
00384             }
00385 
00386             memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
00387                     copy_len );
00388 
00389             ctx->unprocessed_len += copy_len;
00390             ilen -= copy_len;
00391         }
00392 
00393         /*
00394          * Process remaining full blocks
00395          */
00396         if( ilen )
00397         {
00398             if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
00399                     ctx->operation, ilen, ctx->iv, input, output ) ) )
00400             {
00401                 return( ret );
00402             }
00403 
00404             *olen += ilen;
00405         }
00406 
00407         return( 0 );
00408     }
00409 #endif /* MBEDTLS_CIPHER_MODE_CBC */
00410 
00411 #if defined(MBEDTLS_CIPHER_MODE_CFB)
00412     if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB )
00413     {
00414         if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
00415                 ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
00416                 input, output ) ) )
00417         {
00418             return( ret );
00419         }
00420 
00421         *olen = ilen;
00422 
00423         return( 0 );
00424     }
00425 #endif /* MBEDTLS_CIPHER_MODE_CFB */
00426 
00427 #if defined(MBEDTLS_CIPHER_MODE_CTR)
00428     if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
00429     {
00430         if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
00431                 ilen, &ctx->unprocessed_len, ctx->iv,
00432                 ctx->unprocessed_data, input, output ) ) )
00433         {
00434             return( ret );
00435         }
00436 
00437         *olen = ilen;
00438 
00439         return( 0 );
00440     }
00441 #endif /* MBEDTLS_CIPHER_MODE_CTR */
00442 
00443 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
00444     if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
00445     {
00446         if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx,
00447                                                     ilen, input, output ) ) )
00448         {
00449             return( ret );
00450         }
00451 
00452         *olen = ilen;
00453 
00454         return( 0 );
00455     }
00456 #endif /* MBEDTLS_CIPHER_MODE_STREAM */
00457 
00458     return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
00459 }
00460 
00461 #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
00462 #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
00463 /*
00464  * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
00465  */
00466 static void add_pkcs_padding( unsigned char *output, size_t output_len,
00467         size_t data_len )
00468 {
00469     size_t padding_len = output_len - data_len;
00470     unsigned char i;
00471 
00472     for( i = 0; i < padding_len; i++ )
00473         output[data_len + i] = (unsigned char) padding_len;
00474 }
00475 
00476 static int get_pkcs_padding( unsigned char *input, size_t input_len,
00477         size_t *data_len )
00478 {
00479     size_t i, pad_idx;
00480     unsigned char padding_len, bad = 0;
00481 
00482     if( NULL == input || NULL == data_len )
00483         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00484 
00485     padding_len = input[input_len - 1];
00486     *data_len = input_len - padding_len;
00487 
00488     /* Avoid logical || since it results in a branch */
00489     bad |= padding_len > input_len;
00490     bad |= padding_len == 0;
00491 
00492     /* The number of bytes checked must be independent of padding_len,
00493      * so pick input_len, which is usually 8 or 16 (one block) */
00494     pad_idx = input_len - padding_len;
00495     for( i = 0; i < input_len; i++ )
00496         bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
00497 
00498     return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
00499 }
00500 #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
00501 
00502 #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
00503 /*
00504  * One and zeros padding: fill with 80 00 ... 00
00505  */
00506 static void add_one_and_zeros_padding( unsigned char *output,
00507                                        size_t output_len, size_t data_len )
00508 {
00509     size_t padding_len = output_len - data_len;
00510     unsigned char i = 0;
00511 
00512     output[data_len] = 0x80;
00513     for( i = 1; i < padding_len; i++ )
00514         output[data_len + i] = 0x00;
00515 }
00516 
00517 static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
00518                                       size_t *data_len )
00519 {
00520     size_t i;
00521     unsigned char done = 0, prev_done, bad;
00522 
00523     if( NULL == input || NULL == data_len )
00524         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00525 
00526     bad = 0x80;
00527     *data_len = 0;
00528     for( i = input_len; i > 0; i-- )
00529     {
00530         prev_done = done;
00531         done |= ( input[i - 1] != 0 );
00532         *data_len |= ( i - 1 ) * ( done != prev_done );
00533         bad ^= input[i - 1] * ( done != prev_done );
00534     }
00535 
00536     return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
00537 
00538 }
00539 #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
00540 
00541 #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
00542 /*
00543  * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length
00544  */
00545 static void add_zeros_and_len_padding( unsigned char *output,
00546                                        size_t output_len, size_t data_len )
00547 {
00548     size_t padding_len = output_len - data_len;
00549     unsigned char i = 0;
00550 
00551     for( i = 1; i < padding_len; i++ )
00552         output[data_len + i - 1] = 0x00;
00553     output[output_len - 1] = (unsigned char) padding_len;
00554 }
00555 
00556 static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
00557                                       size_t *data_len )
00558 {
00559     size_t i, pad_idx;
00560     unsigned char padding_len, bad = 0;
00561 
00562     if( NULL == input || NULL == data_len )
00563         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00564 
00565     padding_len = input[input_len - 1];
00566     *data_len = input_len - padding_len;
00567 
00568     /* Avoid logical || since it results in a branch */
00569     bad |= padding_len > input_len;
00570     bad |= padding_len == 0;
00571 
00572     /* The number of bytes checked must be independent of padding_len */
00573     pad_idx = input_len - padding_len;
00574     for( i = 0; i < input_len - 1; i++ )
00575         bad |= input[i] * ( i >= pad_idx );
00576 
00577     return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
00578 }
00579 #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
00580 
00581 #if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
00582 /*
00583  * Zero padding: fill with 00 ... 00
00584  */
00585 static void add_zeros_padding( unsigned char *output,
00586                                size_t output_len, size_t data_len )
00587 {
00588     size_t i;
00589 
00590     for( i = data_len; i < output_len; i++ )
00591         output[i] = 0x00;
00592 }
00593 
00594 static int get_zeros_padding( unsigned char *input, size_t input_len,
00595                               size_t *data_len )
00596 {
00597     size_t i;
00598     unsigned char done = 0, prev_done;
00599 
00600     if( NULL == input || NULL == data_len )
00601         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00602 
00603     *data_len = 0;
00604     for( i = input_len; i > 0; i-- )
00605     {
00606         prev_done = done;
00607         done |= ( input[i-1] != 0 );
00608         *data_len |= i * ( done != prev_done );
00609     }
00610 
00611     return( 0 );
00612 }
00613 #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
00614 
00615 /*
00616  * No padding: don't pad :)
00617  *
00618  * There is no add_padding function (check for NULL in mbedtls_cipher_finish)
00619  * but a trivial get_padding function
00620  */
00621 static int get_no_padding( unsigned char *input, size_t input_len,
00622                               size_t *data_len )
00623 {
00624     if( NULL == input || NULL == data_len )
00625         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00626 
00627     *data_len = input_len;
00628 
00629     return( 0 );
00630 }
00631 #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
00632 
00633 int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
00634                    unsigned char *output, size_t *olen )
00635 {
00636     if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
00637         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00638 
00639     *olen = 0;
00640 
00641     if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
00642         MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
00643         MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
00644         MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
00645     {
00646         return( 0 );
00647     }
00648 
00649     if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
00650     {
00651         if( ctx->unprocessed_len != 0 )
00652             return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
00653 
00654         return( 0 );
00655     }
00656 
00657 #if defined(MBEDTLS_CIPHER_MODE_CBC)
00658     if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode )
00659     {
00660         int ret = 0;
00661 
00662         if( MBEDTLS_ENCRYPT == ctx->operation )
00663         {
00664             /* check for 'no padding' mode */
00665             if( NULL == ctx->add_padding )
00666             {
00667                 if( 0 != ctx->unprocessed_len )
00668                     return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
00669 
00670                 return( 0 );
00671             }
00672 
00673             ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ),
00674                     ctx->unprocessed_len );
00675         }
00676         else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len )
00677         {
00678             /*
00679              * For decrypt operations, expect a full block,
00680              * or an empty block if no padding
00681              */
00682             if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
00683                 return( 0 );
00684 
00685             return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
00686         }
00687 
00688         /* cipher block */
00689         if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
00690                 ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv,
00691                 ctx->unprocessed_data, output ) ) )
00692         {
00693             return( ret );
00694         }
00695 
00696         /* Set output size for decryption */
00697         if( MBEDTLS_DECRYPT == ctx->operation )
00698             return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ),
00699                                      olen );
00700 
00701         /* Set output size for encryption */
00702         *olen = mbedtls_cipher_get_block_size( ctx );
00703         return( 0 );
00704     }
00705 #else
00706     ((void) output);
00707 #endif /* MBEDTLS_CIPHER_MODE_CBC */
00708 
00709     return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
00710 }
00711 
00712 #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
00713 int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode )
00714 {
00715     if( NULL == ctx ||
00716         MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
00717     {
00718         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00719     }
00720 
00721     switch( mode )
00722     {
00723 #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
00724     case MBEDTLS_PADDING_PKCS7:
00725         ctx->add_padding = add_pkcs_padding;
00726         ctx->get_padding = get_pkcs_padding;
00727         break;
00728 #endif
00729 #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
00730     case MBEDTLS_PADDING_ONE_AND_ZEROS:
00731         ctx->add_padding = add_one_and_zeros_padding;
00732         ctx->get_padding = get_one_and_zeros_padding;
00733         break;
00734 #endif
00735 #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
00736     case MBEDTLS_PADDING_ZEROS_AND_LEN:
00737         ctx->add_padding = add_zeros_and_len_padding;
00738         ctx->get_padding = get_zeros_and_len_padding;
00739         break;
00740 #endif
00741 #if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
00742     case MBEDTLS_PADDING_ZEROS:
00743         ctx->add_padding = add_zeros_padding;
00744         ctx->get_padding = get_zeros_padding;
00745         break;
00746 #endif
00747     case MBEDTLS_PADDING_NONE:
00748         ctx->add_padding = NULL;
00749         ctx->get_padding = get_no_padding;
00750         break;
00751 
00752     default:
00753         return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
00754     }
00755 
00756     return( 0 );
00757 }
00758 #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
00759 
00760 #if defined(MBEDTLS_GCM_C)
00761 int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
00762                       unsigned char *tag, size_t tag_len )
00763 {
00764     if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag )
00765         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00766 
00767     if( MBEDTLS_ENCRYPT != ctx->operation )
00768         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00769 
00770     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
00771         return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len );
00772 
00773     return( 0 );
00774 }
00775 
00776 int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
00777                       const unsigned char *tag, size_t tag_len )
00778 {
00779     int ret;
00780 
00781     if( NULL == ctx || NULL == ctx->cipher_info ||
00782         MBEDTLS_DECRYPT != ctx->operation )
00783     {
00784         return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00785     }
00786 
00787     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
00788     {
00789         unsigned char check_tag[16];
00790         size_t i;
00791         int diff;
00792 
00793         if( tag_len > sizeof( check_tag ) )
00794             return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
00795 
00796         if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
00797                                      check_tag, tag_len ) ) )
00798         {
00799             return( ret );
00800         }
00801 
00802         /* Check the tag in "constant-time" */
00803         for( diff = 0, i = 0; i < tag_len; i++ )
00804             diff |= tag[i] ^ check_tag[i];
00805 
00806         if( diff != 0 )
00807             return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
00808 
00809         return( 0 );
00810     }
00811 
00812     return( 0 );
00813 }
00814 #endif /* MBEDTLS_GCM_C */
00815 
00816 /*
00817  * Packet-oriented wrapper for non-AEAD modes
00818  */
00819 int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
00820                   const unsigned char *iv, size_t iv_len,
00821                   const unsigned char *input, size_t ilen,
00822                   unsigned char *output, size_t *olen )
00823 {
00824     int ret;
00825     size_t finish_olen;
00826 
00827     if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
00828         return( ret );
00829 
00830     if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 )
00831         return( ret );
00832 
00833     if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 )
00834         return( ret );
00835 
00836     if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 )
00837         return( ret );
00838 
00839     *olen += finish_olen;
00840 
00841     return( 0 );
00842 }
00843 
00844 #if defined(MBEDTLS_CIPHER_MODE_AEAD)
00845 /*
00846  * Packet-oriented encryption for AEAD modes
00847  */
00848 int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
00849                          const unsigned char *iv, size_t iv_len,
00850                          const unsigned char *ad, size_t ad_len,
00851                          const unsigned char *input, size_t ilen,
00852                          unsigned char *output, size_t *olen,
00853                          unsigned char *tag, size_t tag_len )
00854 {
00855 #if defined(MBEDTLS_GCM_C)
00856     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
00857     {
00858         *olen = ilen;
00859         return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen,
00860                                    iv, iv_len, ad, ad_len, input, output,
00861                                    tag_len, tag ) );
00862     }
00863 #endif /* MBEDTLS_GCM_C */
00864 #if defined(MBEDTLS_CCM_C)
00865     if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
00866     {
00867         *olen = ilen;
00868         return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen,
00869                                      iv, iv_len, ad, ad_len, input, output,
00870                                      tag, tag_len ) );
00871     }
00872 #endif /* MBEDTLS_CCM_C */
00873 
00874     return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
00875 }
00876 
00877 /*
00878  * Packet-oriented decryption for AEAD modes
00879  */
00880 int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
00881                          const unsigned char *iv, size_t iv_len,
00882                          const unsigned char *ad, size_t ad_len,
00883                          const unsigned char *input, size_t ilen,
00884                          unsigned char *output, size_t *olen,
00885                          const unsigned char *tag, size_t tag_len )
00886 {
00887 #if defined(MBEDTLS_GCM_C)
00888     if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
00889     {
00890         int ret;
00891 
00892         *olen = ilen;
00893         ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen,
00894                                 iv, iv_len, ad, ad_len,
00895                                 tag, tag_len, input, output );
00896 
00897         if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED )
00898             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
00899 
00900         return( ret );
00901     }
00902 #endif /* MBEDTLS_GCM_C */
00903 #if defined(MBEDTLS_CCM_C)
00904     if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
00905     {
00906         int ret;
00907 
00908         *olen = ilen;
00909         ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen,
00910                                 iv, iv_len, ad, ad_len,
00911                                 input, output, tag, tag_len );
00912 
00913         if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED )
00914             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
00915 
00916         return( ret );
00917     }
00918 #endif /* MBEDTLS_CCM_C */
00919 
00920     return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
00921 }
00922 #endif /* MBEDTLS_CIPHER_MODE_AEAD */
00923 
00924 #endif /* MBEDTLS_CIPHER_C */