From 17353034f35cbb06e315d02b57a9b7319909b6ea Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 28 Apr 2008 14:25:19 +0000 Subject: added a wrapper plugin for OpenSSL crypters (AES, 3DES, Blowfish etc.) --- src/libstrongswan/Makefile.am | 4 + src/libstrongswan/plugins/openssl/Makefile.am | 13 ++ .../plugins/openssl/openssl_crypter.c | 250 +++++++++++++++++++++ .../plugins/openssl/openssl_crypter.h | 49 ++++ src/libstrongswan/plugins/openssl/openssl_plugin.c | 80 +++++++ src/libstrongswan/plugins/openssl/openssl_plugin.h | 47 ++++ 6 files changed, 443 insertions(+) create mode 100644 src/libstrongswan/plugins/openssl/Makefile.am create mode 100644 src/libstrongswan/plugins/openssl/openssl_crypter.c create mode 100644 src/libstrongswan/plugins/openssl/openssl_crypter.h create mode 100644 src/libstrongswan/plugins/openssl/openssl_plugin.c create mode 100644 src/libstrongswan/plugins/openssl/openssl_plugin.h (limited to 'src') diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index 9852bdf35..29c31574d 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -144,6 +144,10 @@ if USE_PADLOCK SUBDIRS += plugins/padlock endif +if USE_OPENSSL + SUBDIRS += plugins/openssl +endif + if USE_INTEGRITY_TEST # build fips_signer which in turn builds fips_signature.h ######################################################### diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am new file mode 100644 index 000000000..b26515dbc --- /dev/null +++ b/src/libstrongswan/plugins/openssl/Makefile.am @@ -0,0 +1,13 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-openssl.la + +libstrongswan_openssl_la_SOURCES = openssl_plugin.h openssl_plugin.c \ + openssl_crypter.c openssl_crypter.h + +libstrongswan_openssl_la_LDFLAGS = -module +libstrongswan_openssl_la_LIBADD = -lssl + diff --git a/src/libstrongswan/plugins/openssl/openssl_crypter.c b/src/libstrongswan/plugins/openssl/openssl_crypter.c new file mode 100644 index 000000000..e85ad9134 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_crypter.c @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * 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. See . + * + * 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. + * + * $Id$ + */ + +#include "openssl_crypter.h" + +#include + +typedef struct private_openssl_crypter_t private_openssl_crypter_t; + +/** + * Private data of openssl_crypter_t + */ +struct private_openssl_crypter_t { + + /** + * Public part of this class. + */ + openssl_crypter_t public; + + /* + * the key + */ + chunk_t key; + + /* + * the cipher to use + */ + const EVP_CIPHER *cipher; +}; + +/** + * Mapping from the algorithms defined in IKEv2 to + * OpenSSL algorithm names and their key length + */ +typedef struct { + /** + * Identifier specified in IKEv2 + */ + u_int16_t ikev2_id; + + /** + * Name of the algorithm, as used in OpenSSL + */ + char *name; + + /** + * Minimum valid key length in bytes + */ + size_t key_size_min; + + /** + * Maximum valid key length in bytes + */ + size_t key_size_max; +} openssl_algorithm_t; + +#define END_OF_LIST -1 + +/** + * Algorithms for encryption + */ +static openssl_algorithm_t encryption_algs[] = { +/* {ENCR_DES_IV64, "***", 0, 0}, */ + {ENCR_DES, "des", 8, 8}, /* 64 bits */ + {ENCR_3DES, "des3", 24, 24}, /* 192 bits */ + {ENCR_RC5, "rc5", 5, 255}, /* 40 to 2040 bits, RFC 2451 */ + {ENCR_IDEA, "idea", 16, 16}, /* 128 bits, RFC 2451 */ + {ENCR_CAST, "cast", 5, 16}, /* 40 to 128 bits, RFC 2451 */ + {ENCR_BLOWFISH, "blowfish", 5, 56}, /* 40 to 448 bits, RFC 2451 */ +/* {ENCR_3IDEA, "***", 0, 0}, */ +/* {ENCR_DES_IV32, "***", 0, 0}, */ +/* {ENCR_NULL, "***", 0, 0}, */ /* handled separately */ +/* {ENCR_AES_CBC, "***", 0, 0}, */ /* handled separately */ +/* {ENCR_AES_CTR, "***", 0, 0}, */ /* disabled in evp.h */ + {END_OF_LIST, NULL, 0, 0}, +}; + +/** + * Look up an OpenSSL algorithm name and its key size + */ +static char* lookup_algorithm(openssl_algorithm_t *openssl_algo, + u_int16_t ikev2_algo, size_t key_size) +{ + while (openssl_algo->ikev2_id != END_OF_LIST) + { + if (ikev2_algo == openssl_algo->ikev2_id) + { + /* validate key size */ + if (key_size < openssl_algo->key_size_min || + key_size > openssl_algo->key_size_max) + { + return NULL; + } + return openssl_algo->name; + } + openssl_algo++; + } + return NULL; +} + +static void crypt(private_openssl_crypter_t *this, chunk_t data, + chunk_t iv, chunk_t *dst, int enc) +{ + int len, finlen; + unsigned char buf[data.len + this->cipher->block_size]; + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + EVP_CipherInit_ex(&ctx, this->cipher, NULL, this->key.ptr, iv.ptr, enc); + EVP_CIPHER_CTX_set_padding(&ctx, 0); /* disable padding */ + EVP_CipherUpdate(&ctx, buf, &len, data.ptr, data.len); + EVP_CipherFinal_ex(&ctx, buf + len, &finlen); + len += finlen; + *dst = chunk_alloc(len); + memcpy(dst->ptr, buf, len); + EVP_CIPHER_CTX_cleanup(&ctx); + /* TODO: because we don't use padding, we can simplify this a bit because + * EVP_CryptFinal_ex does not do anything but checking if any data is left. + * so we can work without buffer and fill the dst directly */ +} + +/** + * Implementation of crypter_t.decrypt. + */ +static void decrypt(private_openssl_crypter_t *this, chunk_t data, + chunk_t iv, chunk_t *dst) +{ + crypt(this, data, iv, dst, 0); +} + + +/** + * Implementation of crypter_t.encrypt. + */ +static void encrypt (private_openssl_crypter_t *this, chunk_t data, + chunk_t iv, chunk_t *dst) +{ + crypt(this, data, iv, dst, 1); +} + +/** + * Implementation of crypter_t.get_block_size. + */ +static size_t get_block_size(private_openssl_crypter_t *this) +{ + return this->cipher->block_size; +} + +/** + * Implementation of crypter_t.get_key_size. + */ +static size_t get_key_size(private_openssl_crypter_t *this) +{ + return this->key.len; +} + +/** + * Implementation of crypter_t.set_key. + */ +static void set_key(private_openssl_crypter_t *this, chunk_t key) +{ + memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len)); +} + +/** + * Implementation of crypter_t.destroy and aes_crypter_t.destroy. + */ +static void destroy (private_openssl_crypter_t *this) +{ + free(this->key.ptr); + free(this); +} + +/* + * Described in header + */ +openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo, + size_t key_size) +{ + private_openssl_crypter_t *this; + + this = malloc_thing(private_openssl_crypter_t); + + switch (algo) + { + case ENCR_NULL: + this->cipher = EVP_enc_null(); + break; + case ENCR_AES_CBC: + switch (key_size) + { + case 16: /* AES 128 */ + this->cipher = EVP_get_cipherbyname("aes128"); + break; + case 24: /* AES-192 */ + this->cipher = EVP_get_cipherbyname("aes192"); + break; + case 32: /* AES-256 */ + this->cipher = EVP_get_cipherbyname("aes256"); + break; + default: + free(this); + return NULL; + } + break; + default: + { + char* name = lookup_algorithm(encryption_algs, algo, key_size); + if (!name) + { + /* algo unavailable or key_size invalid */ + free(this); + return NULL; + } + this->cipher = EVP_get_cipherbyname(name); + break; + } + } + + if (!this->cipher) + { + /* OpenSSL does not support the requested algo */ + free(this); + return NULL; + } + + this->key = chunk_alloc(key_size); + + this->public.crypter_interface.encrypt = (void (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt; + this->public.crypter_interface.decrypt = (void (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt; + this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *)) get_block_size; + this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *)) get_key_size; + this->public.crypter_interface.set_key = (void (*) (crypter_t *,chunk_t)) set_key; + this->public.crypter_interface.destroy = (void (*) (crypter_t *)) destroy; + + return &this->public; +} diff --git a/src/libstrongswan/plugins/openssl/openssl_crypter.h b/src/libstrongswan/plugins/openssl/openssl_crypter.h new file mode 100644 index 000000000..fae013670 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_crypter.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * 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. See . + * + * 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. + */ + +/** + * @defgroup openssl_crypter openssl_crypter + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_CRYPTER_H_ +#define OPENSSL_CRYPTER_H_ + +typedef struct openssl_crypter_t openssl_crypter_t; + +#include + +/** + * Implementation of AES using OpenSSL. + */ +struct openssl_crypter_t { + + /** + * The crypter_t interface. + */ + crypter_t crypter_interface; +}; + +/** + * Constructor to create openssl_crypter_t. + * + * @param algo algorithm to implement, must be ENCR_AES_CBC + * @param key_size key size in bytes + * @return openssl_crypter_t, NULL if not supported + */ +openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo, + size_t key_size); + +#endif /* OPENSSL_CRYPTER_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c new file mode 100644 index 000000000..bfdec83ca --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * 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. See . + * + * 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. + * + * $Id$ + */ + +#include + +#include "openssl_plugin.h" + +#include +#include "openssl_crypter.h" + +typedef struct private_openssl_plugin_t private_openssl_plugin_t; + +/** + * private data of openssl_plugin + */ +struct private_openssl_plugin_t { + + /** + * public functions + */ + openssl_plugin_t public; +}; + +/** + * Implementation of openssl_plugin_t.destroy + */ +static void destroy(private_openssl_plugin_t *this) +{ + lib->crypto->remove_crypter(lib->crypto, + (crypter_constructor_t)openssl_crypter_create); + + EVP_cleanup(); + + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_openssl_plugin_t *this = malloc_thing(private_openssl_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + OpenSSL_add_all_algorithms(); + + lib->crypto->add_crypter(lib->crypto, ENCR_DES, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_3DES, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_RC5, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_IDEA, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_CAST, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_BLOWFISH, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_NULL, + (crypter_constructor_t)openssl_crypter_create); + lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, + (crypter_constructor_t)openssl_crypter_create); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.h b/src/libstrongswan/plugins/openssl/openssl_plugin.h new file mode 100644 index 000000000..fb60e38df --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * + * 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. See . + * + * 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. + */ + +/** + * @defgroup openssl_p openssl + * @ingroup plugins + * + * @defgroup openssl_plugin openssl_plugin + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_PLUGIN_H_ +#define OPENSSL_PLUGIN_H_ + +#include + +typedef struct openssl_plugin_t openssl_plugin_t; + +/** + * Plugin implementing crypto functions via the OpenSSL library + */ +struct openssl_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a openssl_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* OPENSSL_PLUGIN_H_ @}*/ -- cgit v1.2.3