Implemented the PRF_KEYED_SHA1 algorithm in the openssl plugin
authorMartin Willi <martin@revosec.ch>
Mon, 8 Mar 2010 11:40:45 +0000 (12:40 +0100)
committerMartin Willi <martin@revosec.ch>
Mon, 8 Mar 2010 12:16:12 +0000 (13:16 +0100)
configure.in
src/libstrongswan/Makefile.am
src/libstrongswan/plugins/openssl/Makefile.am
src/libstrongswan/plugins/openssl/openssl_plugin.c
src/libstrongswan/plugins/openssl/openssl_sha1_prf.c [new file with mode: 0644]
src/libstrongswan/plugins/openssl/openssl_sha1_prf.h [new file with mode: 0644]

index 8124992..89a32fe 100644 (file)
@@ -208,7 +208,6 @@ fi
 
 if test x$eap_aka = xtrue; then
        fips_prf=true;
-       sha1=true;
        simaka=true;
 fi
 
@@ -218,7 +217,9 @@ if test x$eap_sim = xtrue; then
 fi
 
 if test x$fips_prf = xtrue; then
-       sha1=true;
+       if test x$openssl = xfalse; then
+               sha1=true;
+       fi
 fi
 
 if test x$smp = xtrue; then
@@ -676,9 +677,6 @@ if test x$md5 = xtrue; then
        libstrongswan_plugins=${libstrongswan_plugins}" md5"
        pluto_plugins=${pluto_plugins}" md5"
 fi
-if test x$fips_prf = xtrue; then
-       libstrongswan_plugins=${libstrongswan_plugins}" fips-prf"
-fi
 if test x$random = xtrue; then
        libstrongswan_plugins=${libstrongswan_plugins}" random"
        pluto_plugins=${pluto_plugins}" random"
@@ -730,6 +728,9 @@ if test x$gcrypt = xtrue; then
        libstrongswan_plugins=${libstrongswan_plugins}" gcrypt"
        pluto_plugins=${pluto_plugins}" gcrypt"
 fi
+if test x$fips_prf = xtrue; then
+       libstrongswan_plugins=${libstrongswan_plugins}" fips-prf"
+fi
 if test x$xcbc = xtrue; then
        libstrongswan_plugins=${libstrongswan_plugins}" xcbc"
 fi
index 351e799..2b80e61 100644 (file)
@@ -171,13 +171,6 @@ if MONOLITHIC
 endif
 endif
 
-if USE_FIPS_PRF
-  SUBDIRS += plugins/fips_prf
-if MONOLITHIC
-  libstrongswan_la_LIBADD += plugins/fips_prf/libstrongswan-fips-prf.la
-endif
-endif
-
 if USE_GMP
   SUBDIRS += plugins/gmp
 if MONOLITHIC
@@ -304,6 +297,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_FIPS_PRF
+  SUBDIRS += plugins/fips_prf
+if MONOLITHIC
+  libstrongswan_la_LIBADD += plugins/fips_prf/libstrongswan-fips-prf.la
+endif
+endif
+
 if USE_AGENT
   SUBDIRS += plugins/agent
 if MONOLITHIC
index eee1ca5..a507997 100644 (file)
@@ -14,6 +14,7 @@ libstrongswan_openssl_la_SOURCES = \
        openssl_util.c openssl_util.h \
        openssl_crypter.c openssl_crypter.h \
        openssl_hasher.c openssl_hasher.h \
+       openssl_sha1_prf.c openssl_sha1_prf.h \
        openssl_diffie_hellman.c openssl_diffie_hellman.h \
        openssl_rsa_private_key.c openssl_rsa_private_key.h \
        openssl_rsa_public_key.c openssl_rsa_public_key.h \
index 941b643..165f83c 100644 (file)
@@ -27,6 +27,7 @@
 #include "openssl_util.h"
 #include "openssl_crypter.h"
 #include "openssl_hasher.h"
+#include "openssl_sha1_prf.h"
 #include "openssl_diffie_hellman.h"
 #include "openssl_ec_diffie_hellman.h"
 #include "openssl_rsa_private_key.h"
@@ -170,6 +171,8 @@ static void destroy(private_openssl_plugin_t *this)
                                        (crypter_constructor_t)openssl_crypter_create);
        lib->crypto->remove_hasher(lib->crypto,
                                        (hasher_constructor_t)openssl_hasher_create);
+       lib->crypto->remove_prf(lib->crypto,
+                                       (prf_constructor_t)openssl_sha1_prf_create);
        lib->crypto->remove_dh(lib->crypto,
                                        (dh_constructor_t)openssl_diffie_hellman_create);
        lib->crypto->remove_dh(lib->crypto,
@@ -256,6 +259,10 @@ plugin_t *openssl_plugin_create()
        lib->crypto->add_hasher(lib->crypto, HASH_SHA512,
                                        (hasher_constructor_t)openssl_hasher_create);
 
+       /* prf */
+       lib->crypto->add_prf(lib->crypto, PRF_KEYED_SHA1,
+                                       (prf_constructor_t)openssl_sha1_prf_create);
+
        /* (ec) diffie hellman */
        lib->crypto->add_dh(lib->crypto, MODP_2048_BIT,
                                                (dh_constructor_t)openssl_diffie_hellman_create);
diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c
new file mode 100644 (file)
index 0000000..b653880
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * 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.
+ */
+
+#include "openssl_sha1_prf.h"
+
+#include <openssl/sha.h>
+
+typedef struct private_openssl_sha1_prf_t private_openssl_sha1_prf_t;
+
+/**
+ * Private data of an openssl_sha1_prf_t object.
+ */
+struct private_openssl_sha1_prf_t {
+
+       /**
+        * Public openssl_sha1_prf_t interface.
+        */
+       openssl_sha1_prf_t public;
+
+       /**
+        * SHA1 context
+        */
+       SHA_CTX ctx;
+};
+
+METHOD(prf_t, get_bytes, void,
+       private_openssl_sha1_prf_t *this, chunk_t seed, u_int8_t *bytes)
+{
+       SHA1_Update(&this->ctx, seed.ptr, seed.len);
+
+       if (bytes)
+       {
+               u_int32_t *hash = (u_int32_t*)bytes;
+
+               hash[0] = htonl(this->ctx.h0);
+               hash[1] = htonl(this->ctx.h1);
+               hash[2] = htonl(this->ctx.h2);
+               hash[3] = htonl(this->ctx.h3);
+               hash[4] = htonl(this->ctx.h4);
+       }
+}
+
+METHOD(prf_t, get_block_size, size_t,
+       private_openssl_sha1_prf_t *this)
+{
+       return HASH_SIZE_SHA1;
+}
+
+METHOD(prf_t, allocate_bytes, void,
+       private_openssl_sha1_prf_t *this, chunk_t seed, chunk_t *chunk)
+{
+       if (chunk)
+       {
+               *chunk = chunk_alloc(HASH_SIZE_SHA1);
+               get_bytes(this, seed, chunk->ptr);
+       }
+       else
+       {
+               get_bytes(this, seed, NULL);
+       }
+}
+
+METHOD(prf_t, get_key_size, size_t,
+       private_openssl_sha1_prf_t *this)
+{
+       return HASH_SIZE_SHA1;
+}
+
+METHOD(prf_t, set_key, void,
+       private_openssl_sha1_prf_t *this, chunk_t key)
+{
+       SHA1_Init(&this->ctx);
+
+       if (key.len >= 4)
+       {
+               this->ctx.h0 ^= untoh32(key.ptr);
+       }
+       if (key.len >= 8)
+       {
+               this->ctx.h1 ^= untoh32(key.ptr + 4);
+       }
+       if (key.len >= 12)
+       {
+               this->ctx.h2 ^= untoh32(key.ptr + 8);
+       }
+       if (key.len >= 16)
+       {
+               this->ctx.h3 ^= untoh32(key.ptr + 12);
+       }
+       if (key.len >= 20)
+       {
+               this->ctx.h4 ^= untoh32(key.ptr + 16);
+       }
+}
+
+METHOD(prf_t, destroy, void,
+       private_openssl_sha1_prf_t *this)
+{
+       free(this);
+}
+
+/**
+ * See header
+ */
+openssl_sha1_prf_t *openssl_sha1_prf_create(pseudo_random_function_t algo)
+{
+       private_openssl_sha1_prf_t *this;
+
+       if (algo != PRF_KEYED_SHA1)
+       {
+               return NULL;
+       }
+
+       INIT(this,
+               .public.prf = {
+                       .get_block_size = _get_block_size,
+                       .get_bytes = _get_bytes,
+                       .allocate_bytes = _allocate_bytes,
+                       .get_key_size = _get_key_size,
+                       .set_key = _set_key,
+                       .destroy = _destroy,
+               },
+       );
+
+       return &this->public;
+}
+
diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h
new file mode 100644 (file)
index 0000000..9a24e7e
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * 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_sha1_prf openssl_sha1_prf
+ * @{ @ingroup sha1_p
+ */
+
+#ifndef OPENSSL_SHA1_PRF_H_
+#define OPENSSL_SHA1_PRF_H_
+
+typedef struct openssl_sha1_prf_t openssl_sha1_prf_t;
+
+#include <crypto/prfs/prf.h>
+
+/**
+ * Implementation of prf_t interface using keyed SHA1 algorithm as used
+ * in EAP-AKA/FIPS_PRF.
+ */
+struct openssl_sha1_prf_t {
+
+       /**
+        * Implements prf_t interface.
+        */
+       prf_t prf;
+};
+
+/**
+ * Creates a new openssl_sha1_prf_t.
+ *
+ * @param algo         algorithm, must be PRF_KEYED_SHA1
+ * @return                     sha1_keyed_prf_tobject
+ */
+openssl_sha1_prf_t *openssl_sha1_prf_create(pseudo_random_function_t algo);
+
+#endif /** OPENSSL_SHA1_PRF_H_ @}*/