added a wrapper plugin for OpenSSL crypters (AES, 3DES, Blowfish etc.)
authorTobias Brunner <tobias@strongswan.org>
Mon, 28 Apr 2008 14:25:19 +0000 (14:25 -0000)
committerTobias Brunner <tobias@strongswan.org>
Mon, 28 Apr 2008 14:25:19 +0000 (14:25 -0000)
configure.in
src/libstrongswan/Makefile.am
src/libstrongswan/plugins/openssl/Makefile.am [new file with mode: 0644]
src/libstrongswan/plugins/openssl/openssl_crypter.c [new file with mode: 0644]
src/libstrongswan/plugins/openssl/openssl_crypter.h [new file with mode: 0644]
src/libstrongswan/plugins/openssl/openssl_plugin.c [new file with mode: 0644]
src/libstrongswan/plugins/openssl/openssl_plugin.h [new file with mode: 0644]

index 9ec34b8..30a9f28 100644 (file)
@@ -496,6 +496,16 @@ AC_ARG_ENABLE(
        fi],
 )
 
+AC_ARG_ENABLE(
+       [openssl],
+       AS_HELP_STRING([--enable-openssl],[enables the OpenSSL crypto plugin. (default is NO).]),
+       [if test x$enableval = xyes; then
+               openssl=true
+        else
+               openssl=false
+       fi],
+)
+
 dnl =========================
 dnl  check required programs
 dnl =========================
@@ -597,6 +607,11 @@ if test x$mysql = xtrue; then
        AC_CHECK_HEADER([sqlite3.h],,[AC_MSG_ERROR([SQLite header sqlite3.h not found!])])
 fi
 
+if test x$openssl = xtrue; then
+       AC_HAVE_LIBRARY([ssl],[LIBS="$LIBS"],[AC_MSG_ERROR([OpenSSL library ssl not found])])
+       AC_CHECK_HEADER([openssl/evp.h],,[AC_MSG_ERROR([OpenSSL header openssl/evp.h not found!])])
+fi
+
 dnl =========================
 dnl  set Makefile.am vars
 dnl =========================
@@ -643,6 +658,7 @@ AM_CONDITIONAL(USE_PLUTO_OR_CHARON, test x$pluto = xtrue -o x$charon = xtrue)
 AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$tools = xtrue)
 AM_CONDITIONAL(USE_FILE_CONFIG, test x$pluto = xtrue -o x$stroke = xtrue)
 AM_CONDITIONAL(USE_PADLOCK, test x$padlock = xtrue)
+AM_CONDITIONAL(USE_OPENSSL, test x$openssl = xtrue)
 
 dnl ==============================
 dnl  set global definitions
@@ -676,6 +692,7 @@ AC_OUTPUT(
        src/libstrongswan/plugins/mysql/Makefile
        src/libstrongswan/plugins/sqlite/Makefile
        src/libstrongswan/plugins/padlock/Makefile
+       src/libstrongswan/plugins/openssl/Makefile
        src/libcrypto/Makefile
        src/libfreeswan/Makefile
        src/pluto/Makefile
index 9852bdf..29c3157 100644 (file)
@@ -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 (file)
index 0000000..b26515d
--- /dev/null
@@ -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 (file)
index 0000000..e85ad91
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <openssl/evp.h>
+
+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 (file)
index 0000000..fae0136
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <crypto/crypters/crypter.h>
+
+/**
+ * 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 (file)
index 0000000..bfdec83
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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/evp.h>
+
+#include "openssl_plugin.h"
+
+#include <library.h>
+#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 (file)
index 0000000..fb60e38
--- /dev/null
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <plugins/plugin.h>
+
+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_ @}*/