| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536 | /** * \file cipher.c *  * \brief Generic cipher wrapper for PolarSSL * * \author Adriaan de Jong <dejong@fox-it.com> * *  Copyright (C) 2006-2010, Brainspark B.V. * *  This file is part of PolarSSL (http://www.polarssl.org) *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> * *  All rights reserved. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License along *  with this program; if not, write to the Free Software Foundation, Inc., *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */#include "config.h"#if defined(POLARSSL_CIPHER_C)#include "polarssl/cipher.h"#include "polarssl/cipher_wrap.h"#include <stdlib.h>#if defined ( __GNUC__ )#include <my_strings.h>#endif#if defined _MSC_VER && !defined strcasecmp#define strcasecmp _stricmp#endifstatic const int supported_ciphers[] = {#if defined(POLARSSL_AES_C)        POLARSSL_CIPHER_AES_128_CBC,        POLARSSL_CIPHER_AES_192_CBC,        POLARSSL_CIPHER_AES_256_CBC,#if defined(POLARSSL_CIPHER_MODE_CFB)        POLARSSL_CIPHER_AES_128_CFB128,        POLARSSL_CIPHER_AES_192_CFB128,        POLARSSL_CIPHER_AES_256_CFB128,#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */#if defined(POLARSSL_CIPHER_MODE_CTR)        POLARSSL_CIPHER_AES_128_CTR,        POLARSSL_CIPHER_AES_192_CTR,        POLARSSL_CIPHER_AES_256_CTR,#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */#endif /* defined(POLARSSL_AES_C) */#if defined(POLARSSL_CAMELLIA_C)        POLARSSL_CIPHER_CAMELLIA_128_CBC,        POLARSSL_CIPHER_CAMELLIA_192_CBC,        POLARSSL_CIPHER_CAMELLIA_256_CBC,#if defined(POLARSSL_CIPHER_MODE_CFB)        POLARSSL_CIPHER_CAMELLIA_128_CFB128,        POLARSSL_CIPHER_CAMELLIA_192_CFB128,        POLARSSL_CIPHER_CAMELLIA_256_CFB128,#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */#if defined(POLARSSL_CIPHER_MODE_CTR)        POLARSSL_CIPHER_CAMELLIA_128_CTR,        POLARSSL_CIPHER_CAMELLIA_192_CTR,        POLARSSL_CIPHER_CAMELLIA_256_CTR,#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */#endif /* defined(POLARSSL_CAMELLIA_C) */#if defined(POLARSSL_DES_C)        POLARSSL_CIPHER_DES_CBC,        POLARSSL_CIPHER_DES_EDE_CBC,        POLARSSL_CIPHER_DES_EDE3_CBC,#endif /* defined(POLARSSL_DES_C) */        0};const int *cipher_list( void ){    return supported_ciphers;}const cipher_info_t *cipher_info_from_type( cipher_type_t cipher_type ){    /* Find static cipher information */    switch ( cipher_type )    {#if defined(POLARSSL_AES_C)        case POLARSSL_CIPHER_AES_128_CBC:            return &aes_128_cbc_info;        case POLARSSL_CIPHER_AES_192_CBC:            return &aes_192_cbc_info;        case POLARSSL_CIPHER_AES_256_CBC:            return &aes_256_cbc_info;#if defined(POLARSSL_CIPHER_MODE_CFB)        case POLARSSL_CIPHER_AES_128_CFB128:            return &aes_128_cfb128_info;        case POLARSSL_CIPHER_AES_192_CFB128:            return &aes_192_cfb128_info;        case POLARSSL_CIPHER_AES_256_CFB128:            return &aes_256_cfb128_info;#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */#if defined(POLARSSL_CIPHER_MODE_CTR)        case POLARSSL_CIPHER_AES_128_CTR:            return &aes_128_ctr_info;        case POLARSSL_CIPHER_AES_192_CTR:            return &aes_192_ctr_info;        case POLARSSL_CIPHER_AES_256_CTR:            return &aes_256_ctr_info;#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */#endif#if defined(POLARSSL_CAMELLIA_C)        case POLARSSL_CIPHER_CAMELLIA_128_CBC:            return &camellia_128_cbc_info;        case POLARSSL_CIPHER_CAMELLIA_192_CBC:            return &camellia_192_cbc_info;        case POLARSSL_CIPHER_CAMELLIA_256_CBC:            return &camellia_256_cbc_info;#if defined(POLARSSL_CIPHER_MODE_CFB)        case POLARSSL_CIPHER_CAMELLIA_128_CFB128:            return &camellia_128_cfb128_info;        case POLARSSL_CIPHER_CAMELLIA_192_CFB128:            return &camellia_192_cfb128_info;        case POLARSSL_CIPHER_CAMELLIA_256_CFB128:            return &camellia_256_cfb128_info;#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */#if defined(POLARSSL_CIPHER_MODE_CTR)        case POLARSSL_CIPHER_CAMELLIA_128_CTR:            return &camellia_128_ctr_info;        case POLARSSL_CIPHER_CAMELLIA_192_CTR:            return &camellia_192_ctr_info;        case POLARSSL_CIPHER_CAMELLIA_256_CTR:            return &camellia_256_ctr_info;#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */#endif#if defined(POLARSSL_DES_C)        case POLARSSL_CIPHER_DES_CBC:            return &des_cbc_info;        case POLARSSL_CIPHER_DES_EDE_CBC:            return &des_ede_cbc_info;        case POLARSSL_CIPHER_DES_EDE3_CBC:            return &des_ede3_cbc_info;#endif        default:            return NULL;    }}const cipher_info_t *cipher_info_from_string( const char *cipher_name ){    if( NULL == cipher_name )        return NULL;    /* Get the appropriate cipher information */#if defined(POLARSSL_CAMELLIA_C)    if( !strcasecmp( "CAMELLIA-128-CBC", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CBC );    if( !strcasecmp( "CAMELLIA-192-CBC", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CBC );    if( !strcasecmp( "CAMELLIA-256-CBC", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CBC );#if defined(POLARSSL_CIPHER_MODE_CFB)    if( !strcasecmp( "CAMELLIA-128-CFB128", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CFB128 );    if( !strcasecmp( "CAMELLIA-192-CFB128", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CFB128 );    if( !strcasecmp( "CAMELLIA-256-CFB128", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CFB128 );#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */#if defined(POLARSSL_CIPHER_MODE_CTR)    if( !strcasecmp( "CAMELLIA-128-CTR", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_128_CTR );    if( !strcasecmp( "CAMELLIA-192-CTR", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_192_CTR );    if( !strcasecmp( "CAMELLIA-256-CTR", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_CAMELLIA_256_CTR );#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */#endif#if defined(POLARSSL_AES_C)    if( !strcasecmp( "AES-128-CBC", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CBC );    if( !strcasecmp( "AES-192-CBC", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CBC );    if( !strcasecmp( "AES-256-CBC", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CBC );#if defined(POLARSSL_CIPHER_MODE_CFB)    if( !strcasecmp( "AES-128-CFB128", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CFB128 );    if( !strcasecmp( "AES-192-CFB128", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CFB128 );    if( !strcasecmp( "AES-256-CFB128", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CFB128 );#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */#if defined(POLARSSL_CIPHER_MODE_CTR)    if( !strcasecmp( "AES-128-CTR", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_AES_128_CTR );    if( !strcasecmp( "AES-192-CTR", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_AES_192_CTR );    if( !strcasecmp( "AES-256-CTR", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CTR );#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */#endif#if defined(POLARSSL_DES_C)    if( !strcasecmp( "DES-CBC", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_DES_CBC );    if( !strcasecmp( "DES-EDE-CBC", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE_CBC );    if( !strcasecmp( "DES-EDE3-CBC", cipher_name ) )        return cipher_info_from_type( POLARSSL_CIPHER_DES_EDE3_CBC );#endif    return NULL;}int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info ){    if( NULL == cipher_info || NULL == ctx )        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;    memset( ctx, 0, sizeof( ctx ) );    if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )        return POLARSSL_ERR_CIPHER_ALLOC_FAILED;    ctx->cipher_info = cipher_info;    return 0;}int cipher_free_ctx( cipher_context_t *ctx ){    if( ctx == NULL || ctx->cipher_info == NULL )        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;    ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );    return 0;}int cipher_setkey( cipher_context_t *ctx, const unsigned char *key,        int key_length, const operation_t operation ){    if( NULL == ctx || NULL == ctx->cipher_info )        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;    ctx->key_length = key_length;    ctx->operation = operation;    /*     * For CFB128 and CTR mode always use the encryption key schedule     */    if( POLARSSL_ENCRYPT == operation ||        POLARSSL_MODE_CFB128 == ctx->cipher_info->mode ||        POLARSSL_MODE_CTR == ctx->cipher_info->mode )    {        return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,                ctx->key_length );    }    if( POLARSSL_DECRYPT == operation )        return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,                ctx->key_length );    return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;}int cipher_reset( cipher_context_t *ctx, const unsigned char *iv ){    if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;    ctx->unprocessed_len = 0;    memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) );    return 0;}int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,        unsigned char *output, size_t *olen ){    int ret;    size_t copy_len = 0;    if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ||        input == output )    {        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;    }    *olen = 0;    if( ctx->cipher_info->mode == POLARSSL_MODE_CBC )    {        /*         * If there is not enough data for a full block, cache it.         */        if( ( ctx->operation == POLARSSL_DECRYPT &&                ilen + ctx->unprocessed_len <= cipher_get_block_size( ctx ) ) ||             ( ctx->operation == POLARSSL_ENCRYPT &&                ilen + ctx->unprocessed_len < cipher_get_block_size( ctx ) ) )        {            memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,                    ilen );            ctx->unprocessed_len += ilen;            return 0;        }        /*         * Process cached data first         */        if( ctx->unprocessed_len != 0 )        {            copy_len = cipher_get_block_size( ctx ) - ctx->unprocessed_len;            memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,                    copy_len );            if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,                    ctx->operation, cipher_get_block_size( ctx ), ctx->iv,                    ctx->unprocessed_data, output ) ) )            {                return ret;            }            *olen += cipher_get_block_size( ctx );            output += cipher_get_block_size( ctx );            ctx->unprocessed_len = 0;            input += copy_len;            ilen -= copy_len;        }        /*         * Cache final, incomplete block         */        if( 0 != ilen )        {            copy_len = ilen % cipher_get_block_size( ctx );            if( copy_len == 0 && ctx->operation == POLARSSL_DECRYPT )                copy_len = cipher_get_block_size(ctx);            memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),                    copy_len );            ctx->unprocessed_len += copy_len;            ilen -= copy_len;        }        /*         * Process remaining full blocks         */        if( ilen )        {            if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,                    ctx->operation, ilen, ctx->iv, input, output ) ) )            {                return ret;            }            *olen += ilen;        }        return 0;    }    if( ctx->cipher_info->mode == POLARSSL_MODE_CFB128 )    {        if( 0 != ( ret = ctx->cipher_info->base->cfb128_func( ctx->cipher_ctx,                ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,                input, output ) ) )        {            return ret;        }        *olen = ilen;        return 0;    }    if( ctx->cipher_info->mode == POLARSSL_MODE_CTR )    {        if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,                ilen, &ctx->unprocessed_len, ctx->iv,                ctx->unprocessed_data, input, output ) ) )        {            return ret;        }        *olen = ilen;        return 0;    }    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;}static void add_pkcs_padding( unsigned char *output, size_t output_len,        size_t data_len ){    size_t padding_len = output_len - data_len;    unsigned char i = 0;    for( i = 0; i < padding_len; i++ )        output[data_len + i] = (unsigned char) padding_len;}static int get_pkcs_padding( unsigned char *input, unsigned char input_len,        size_t *data_len){    int i = 0;    unsigned char padding_len = 0;    if( NULL == input || NULL == data_len )        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;    padding_len = input[input_len - 1];    if( padding_len > input_len )        return POLARSSL_ERR_CIPHER_INVALID_PADDING;    for( i = input_len - padding_len; i < input_len; i++ )        if( input[i] != padding_len )            return POLARSSL_ERR_CIPHER_INVALID_PADDING;    *data_len = input_len - padding_len;    return 0;}int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen){    int ret = 0;    if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;    *olen = 0;    if( POLARSSL_MODE_CFB128 == ctx->cipher_info->mode ||        POLARSSL_MODE_CTR == ctx->cipher_info->mode )    {        return 0;    }    if( POLARSSL_MODE_CBC == ctx->cipher_info->mode )    {        if( POLARSSL_ENCRYPT == ctx->operation )        {            add_pkcs_padding( ctx->unprocessed_data, cipher_get_iv_size( ctx ),                    ctx->unprocessed_len );        }        else if ( cipher_get_block_size( ctx ) != ctx->unprocessed_len )        {            /* For decrypt operations, expect a full block */            return POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED;        }        /* cipher block */        if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,                ctx->operation, cipher_get_block_size( ctx ), ctx->iv,                ctx->unprocessed_data, output ) ) )        {            return ret;        }        /* Set output size for decryption */        if( POLARSSL_DECRYPT == ctx->operation )            return get_pkcs_padding( output, cipher_get_block_size( ctx ), olen );        /* Set output size for encryption */        *olen = cipher_get_block_size( ctx );        return 0;    }    return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;}#if defined(POLARSSL_SELF_TEST)#ifdef PRINTF_STDLIB#include <stdio.h>#endif#ifdef PRINTF_CUSTOM#include "tinystdio.h"#endif#define ASSERT(x) if (!(x)) { \        printf( "failed with %i at %s\n", value, (#x) ); \    return( 1 ); \}/* * Checkup routine */int cipher_self_test( int verbose ){    ((void) verbose);    return( 0 );}#endif#endif
 |