mbedtls ported to mbed-classic

Fork of mbedtls by Christopher Haster

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