Annotation of embedaddon/strongswan/src/libstrongswan/plugins/openssl/openssl_crypter.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2008 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "openssl_crypter.h"
                     17: 
                     18: #include <openssl/evp.h>
                     19: 
                     20: typedef struct private_openssl_crypter_t private_openssl_crypter_t;
                     21: 
                     22: /**
                     23:  * Private data of openssl_crypter_t
                     24:  */
                     25: struct private_openssl_crypter_t {
                     26: 
                     27:        /**
                     28:         * Public part of this class.
                     29:         */
                     30:        openssl_crypter_t public;
                     31: 
                     32:        /*
                     33:         * the key
                     34:         */
                     35:        chunk_t key;
                     36: 
                     37:        /*
                     38:         * the cipher to use
                     39:         */
                     40:        const EVP_CIPHER *cipher;
                     41: };
                     42: 
                     43: /**
                     44:  * Look up an OpenSSL algorithm name and validate its key size
                     45:  */
                     46: static char* lookup_algorithm(uint16_t ikev2_algo, size_t *key_size)
                     47: {
                     48:        struct {
                     49:                /* identifier specified in IKEv2 */
                     50:                int ikev2_id;
                     51:                /* name of the algorithm, as used in OpenSSL */
                     52:                char *name;
                     53:                /* default key size in bytes */
                     54:                size_t key_def;
                     55:                /* minimum key size */
                     56:                size_t key_min;
                     57:                /* maximum key size */
                     58:                size_t key_max;
                     59:        } mappings[] = {
                     60:                {ENCR_DES,                      "des-cbc",               8,              8,               8},
                     61:                {ENCR_3DES,             "des-ede3-cbc", 24,             24,              24},
                     62:                {ENCR_RC5,                      "rc5-cbc",              16,              5,             255},
                     63:                {ENCR_IDEA,             "idea-cbc",             16,             16,              16},
                     64:                {ENCR_CAST,             "cast5-cbc",    16,              5,              16},
                     65:                {ENCR_BLOWFISH,         "bf-cbc",               16,              5,              56},
                     66:        };
                     67:        int i;
                     68: 
                     69:        for (i = 0; i < countof(mappings); i++)
                     70:        {
                     71:                if (ikev2_algo == mappings[i].ikev2_id)
                     72:                {
                     73:                        /* set the key size if it is not set */
                     74:                        if (*key_size == 0)
                     75:                        {
                     76:                                *key_size = mappings[i].key_def;
                     77:                        }
                     78:                        /* validate key size */
                     79:                        if (*key_size < mappings[i].key_min ||
                     80:                                *key_size > mappings[i].key_max)
                     81:                        {
                     82:                                return NULL;
                     83:                        }
                     84:                        return mappings[i].name;
                     85:                }
                     86:        }
                     87:        return NULL;
                     88: }
                     89: 
                     90: /**
                     91:  * Do the actual en/decryption in an EVP context
                     92:  */
                     93: static bool crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv,
                     94:                                  chunk_t *dst, int enc)
                     95: {
                     96:        EVP_CIPHER_CTX *ctx;
                     97:        int len;
                     98:        u_char *out;
                     99:        bool success = FALSE;
                    100: 
                    101:        out = data.ptr;
                    102:        if (dst)
                    103:        {
                    104:                *dst = chunk_alloc(data.len);
                    105:                out = dst->ptr;
                    106:        }
                    107:        ctx = EVP_CIPHER_CTX_new();
                    108:        if (EVP_CipherInit_ex(ctx, this->cipher, NULL, NULL, NULL, enc) &&
                    109:                EVP_CIPHER_CTX_set_padding(ctx, 0) /* disable padding */ &&
                    110:                EVP_CIPHER_CTX_set_key_length(ctx, this->key.len) &&
                    111:                EVP_CipherInit_ex(ctx, NULL, NULL, this->key.ptr, iv.ptr, enc) &&
                    112:                EVP_CipherUpdate(ctx, out, &len, data.ptr, data.len) &&
                    113:                /* since padding is disabled this does nothing */
                    114:                EVP_CipherFinal_ex(ctx, out + len, &len))
                    115:        {
                    116:                success = TRUE;
                    117:        }
                    118:        EVP_CIPHER_CTX_free(ctx);
                    119:        return success;
                    120: }
                    121: 
                    122: METHOD(crypter_t, decrypt, bool,
                    123:        private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
                    124: {
                    125:        return crypt(this, data, iv, dst, 0);
                    126: }
                    127: 
                    128: METHOD(crypter_t, encrypt, bool,
                    129:        private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
                    130: {
                    131:        return crypt(this, data, iv, dst, 1);
                    132: }
                    133: 
                    134: METHOD(crypter_t, get_block_size, size_t,
                    135:        private_openssl_crypter_t *this)
                    136: {
                    137:        return EVP_CIPHER_block_size(this->cipher);
                    138: }
                    139: 
                    140: METHOD(crypter_t, get_iv_size, size_t,
                    141:        private_openssl_crypter_t *this)
                    142: {
                    143:        return EVP_CIPHER_iv_length(this->cipher);
                    144: }
                    145: 
                    146: METHOD(crypter_t, get_key_size, size_t,
                    147:        private_openssl_crypter_t *this)
                    148: {
                    149:        return this->key.len;
                    150: }
                    151: 
                    152: METHOD(crypter_t, set_key, bool,
                    153:        private_openssl_crypter_t *this, chunk_t key)
                    154: {
                    155:        memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len));
                    156:        return TRUE;
                    157: }
                    158: 
                    159: METHOD(crypter_t, destroy, void,
                    160:        private_openssl_crypter_t *this)
                    161: {
                    162:        chunk_clear(&this->key);
                    163:        free(this);
                    164: }
                    165: 
                    166: /*
                    167:  * Described in header
                    168:  */
                    169: openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo,
                    170:                                                                                                  size_t key_size)
                    171: {
                    172:        private_openssl_crypter_t *this;
                    173: 
                    174:        INIT(this,
                    175:                .public = {
                    176:                        .crypter = {
                    177:                                .encrypt = _encrypt,
                    178:                                .decrypt = _decrypt,
                    179:                                .get_block_size = _get_block_size,
                    180:                                .get_iv_size = _get_iv_size,
                    181:                                .get_key_size = _get_key_size,
                    182:                                .set_key = _set_key,
                    183:                                .destroy = _destroy,
                    184:                        },
                    185:                },
                    186:        );
                    187: 
                    188:        switch (algo)
                    189:        {
                    190:                case ENCR_NULL:
                    191:                        this->cipher = EVP_enc_null();
                    192:                        key_size = 0;
                    193:                        break;
                    194:                case ENCR_AES_CBC:
                    195:                        switch (key_size)
                    196:                        {
                    197:                                case 0:
                    198:                                        key_size = 16;
                    199:                                        /* FALL */
                    200:                                case 16:        /* AES 128 */
                    201:                                        this->cipher = EVP_get_cipherbyname("aes-128-cbc");
                    202:                                        break;
                    203:                                case 24:        /* AES-192 */
                    204:                                        this->cipher = EVP_get_cipherbyname("aes-192-cbc");
                    205:                                        break;
                    206:                                case 32:        /* AES-256 */
                    207:                                        this->cipher = EVP_get_cipherbyname("aes-256-cbc");
                    208:                                        break;
                    209:                                default:
                    210:                                        free(this);
                    211:                                        return NULL;
                    212:                        }
                    213:                        break;
                    214:                case ENCR_AES_ECB:
                    215:                        switch (key_size)
                    216:                        {
                    217:                                case 0:
                    218:                                        key_size = 16;
                    219:                                        /* FALL */
                    220:                                case 16:        /* AES 128 */
                    221:                                        this->cipher = EVP_get_cipherbyname("aes-128-ecb");
                    222:                                        break;
                    223:                                case 24:        /* AES-192 */
                    224:                                        this->cipher = EVP_get_cipherbyname("aes-192-ecb");
                    225:                                        break;
                    226:                                case 32:        /* AES-256 */
                    227:                                        this->cipher = EVP_get_cipherbyname("aes-256-ecb");
                    228:                                        break;
                    229:                                default:
                    230:                                        free(this);
                    231:                                        return NULL;
                    232:                        }
                    233:                        break;
                    234:                case ENCR_CAMELLIA_CBC:
                    235:                        switch (key_size)
                    236:                        {
                    237:                                case 0:
                    238:                                        key_size = 16;
                    239:                                        /* FALL */
                    240:                                case 16:        /* CAMELLIA 128 */
                    241:                                        this->cipher = EVP_get_cipherbyname("camellia-128-cbc");
                    242:                                        break;
                    243:                                case 24:        /* CAMELLIA 192 */
                    244:                                        this->cipher = EVP_get_cipherbyname("camellia-192-cbc");
                    245:                                        break;
                    246:                                case 32:        /* CAMELLIA 256 */
                    247:                                        this->cipher = EVP_get_cipherbyname("camellia-256-cbc");
                    248:                                        break;
                    249:                                default:
                    250:                                        free(this);
                    251:                                        return NULL;
                    252:                        }
                    253:                        break;
                    254: #ifndef OPENSSL_NO_DES
                    255:                case ENCR_DES_ECB:
                    256:                        key_size = 8;
                    257:                        this->cipher = EVP_des_ecb();
                    258:                        break;
                    259: #endif
                    260:                default:
                    261:                {
                    262:                        char* name;
                    263: 
                    264:                        name = lookup_algorithm(algo, &key_size);
                    265:                        if (!name)
                    266:                        {
                    267:                                /* algo unavailable or key_size invalid */
                    268:                                free(this);
                    269:                                return NULL;
                    270:                        }
                    271:                        this->cipher = EVP_get_cipherbyname(name);
                    272:                        break;
                    273:                }
                    274:        }
                    275: 
                    276:        if (!this->cipher)
                    277:        {
                    278:                /* OpenSSL does not support the requested algo */
                    279:                free(this);
                    280:                return NULL;
                    281:        }
                    282: 
                    283:        this->key = chunk_alloc(key_size);
                    284: 
                    285:        return &this->public;
                    286: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>