diff options
Diffstat (limited to 'src/libstrongswan/plugins/openssl')
-rw-r--r-- | src/libstrongswan/plugins/openssl/Makefile.am | 4 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/Makefile.in | 23 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_crl.c | 7 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_crypter.c | 28 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_ec_public_key.c | 4 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_hasher.c | 88 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_hmac.c | 191 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_hmac.h | 45 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_plugin.c | 55 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_rng.c | 100 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_rng.h | 54 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c | 3 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c | 4 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_sha1_prf.c | 20 | ||||
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_x509.c | 13 |
15 files changed, 533 insertions, 106 deletions
diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am index 5c845a19c..c59888663 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.am +++ b/src/libstrongswan/plugins/openssl/Makefile.am @@ -22,7 +22,9 @@ libstrongswan_openssl_la_SOURCES = \ openssl_ec_private_key.c openssl_ec_private_key.h \ openssl_ec_public_key.c openssl_ec_public_key.h \ openssl_x509.c openssl_x509.h \ - openssl_crl.c openssl_crl.h + openssl_crl.c openssl_crl.h \ + openssl_rng.c openssl_rng.h \ + openssl_hmac.c openssl_hmac.h libstrongswan_openssl_la_LDFLAGS = -module -avoid-version libstrongswan_openssl_la_LIBADD = -lcrypto diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in index 8994ff1b4..ada44ead3 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.in +++ b/src/libstrongswan/plugins/openssl/Makefile.in @@ -49,6 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -80,7 +81,8 @@ am_libstrongswan_openssl_la_OBJECTS = openssl_plugin.lo \ openssl_sha1_prf.lo openssl_diffie_hellman.lo \ openssl_rsa_private_key.lo openssl_rsa_public_key.lo \ openssl_ec_diffie_hellman.lo openssl_ec_private_key.lo \ - openssl_ec_public_key.lo openssl_x509.lo openssl_crl.lo + openssl_ec_public_key.lo openssl_x509.lo openssl_crl.lo \ + openssl_rng.lo openssl_hmac.lo libstrongswan_openssl_la_OBJECTS = \ $(am_libstrongswan_openssl_la_OBJECTS) libstrongswan_openssl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ @@ -89,7 +91,7 @@ libstrongswan_openssl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ @MONOLITHIC_FALSE@am_libstrongswan_openssl_la_rpath = -rpath \ @MONOLITHIC_FALSE@ $(plugindir) @MONOLITHIC_TRUE@am_libstrongswan_openssl_la_rpath = -DEFAULT_INCLUDES = -I.@am__isrc@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f @@ -115,6 +117,7 @@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BFDLIB = @BFDLIB@ BTLIB = @BTLIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ @@ -209,11 +212,14 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ c_plugins = @c_plugins@ +charon_natt_port = @charon_natt_port@ +charon_plugins = @charon_plugins@ +charon_udp_port = @charon_udp_port@ clearsilver_LIBS = @clearsilver_LIBS@ datadir = @datadir@ datarootdir = @datarootdir@ dbusservicedir = @dbusservicedir@ -default_pkcs11 = @default_pkcs11@ +dev_headers = @dev_headers@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ @@ -230,11 +236,12 @@ imcvdir = @imcvdir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ +ipsec_script = @ipsec_script@ +ipsec_script_upper = @ipsec_script_upper@ ipsecdir = @ipsecdir@ ipsecgroup = @ipsecgroup@ ipseclibdir = @ipseclibdir@ ipsecuser = @ipsecuser@ -libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ libexecdir = @libexecdir@ linux_headers = @linux_headers@ @@ -250,6 +257,7 @@ mkdir_p = @mkdir_p@ nm_CFLAGS = @nm_CFLAGS@ nm_LIBS = @nm_LIBS@ nm_ca_dir = @nm_ca_dir@ +nm_plugins = @nm_plugins@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ @@ -259,7 +267,6 @@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ plugindir = @plugindir@ -pluto_plugins = @pluto_plugins@ pool_plugins = @pool_plugins@ prefix = @prefix@ program_transform_name = @program_transform_name@ @@ -304,7 +311,9 @@ libstrongswan_openssl_la_SOURCES = \ openssl_ec_private_key.c openssl_ec_private_key.h \ openssl_ec_public_key.c openssl_ec_public_key.h \ openssl_x509.c openssl_x509.h \ - openssl_crl.c openssl_crl.h + openssl_crl.c openssl_crl.h \ + openssl_rng.c openssl_rng.h \ + openssl_hmac.c openssl_hmac.h libstrongswan_openssl_la_LDFLAGS = -module -avoid-version libstrongswan_openssl_la_LIBADD = -lcrypto @@ -398,7 +407,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_private_key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_public_key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_hasher.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_hmac.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rng.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rsa_private_key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rsa_public_key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_sha1_prf.Plo@am__quote@ diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.c b/src/libstrongswan/plugins/openssl/openssl_crl.c index 9a9efb2b6..e529ff8a5 100644 --- a/src/libstrongswan/plugins/openssl/openssl_crl.c +++ b/src/libstrongswan/plugins/openssl/openssl_crl.c @@ -225,7 +225,8 @@ METHOD(certificate_t, has_subject_or_issuer, id_match_t, } METHOD(certificate_t, issued_by, bool, - private_openssl_crl_t *this, certificate_t *issuer) + private_openssl_crl_t *this, certificate_t *issuer, + signature_scheme_t *scheme) { chunk_t fingerprint, tbs; public_key_t *key; @@ -270,6 +271,10 @@ METHOD(certificate_t, issued_by, bool, openssl_asn1_str2chunk(this->crl->signature)); free(tbs.ptr); key->destroy(key); + if (valid && scheme) + { + *scheme = this->scheme; + } return valid; } diff --git a/src/libstrongswan/plugins/openssl/openssl_crypter.c b/src/libstrongswan/plugins/openssl/openssl_crypter.c index cd9a3bd4a..07b96b320 100644 --- a/src/libstrongswan/plugins/openssl/openssl_crypter.c +++ b/src/libstrongswan/plugins/openssl/openssl_crypter.c @@ -90,7 +90,7 @@ static char* lookup_algorithm(u_int16_t ikev2_algo, size_t *key_size) /** * Do the actual en/decryption in an EVP context */ -static void crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv, +static bool crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst, int enc) { int len; @@ -104,25 +104,26 @@ static void crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv, } EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); - EVP_CipherInit_ex(&ctx, this->cipher, NULL, NULL, NULL, enc); - EVP_CIPHER_CTX_set_padding(&ctx, 0); /* disable padding */ - EVP_CIPHER_CTX_set_key_length(&ctx, this->key.len); - EVP_CipherInit_ex(&ctx, NULL, NULL, this->key.ptr, iv.ptr, enc); - EVP_CipherUpdate(&ctx, out, &len, data.ptr, data.len); - EVP_CipherFinal_ex(&ctx, out + len, &len); /* since padding is disabled this does nothing */ - EVP_CIPHER_CTX_cleanup(&ctx); + return EVP_CipherInit_ex(&ctx, this->cipher, NULL, NULL, NULL, enc) && + EVP_CIPHER_CTX_set_padding(&ctx, 0) /* disable padding */ && + EVP_CIPHER_CTX_set_key_length(&ctx, this->key.len) && + EVP_CipherInit_ex(&ctx, NULL, NULL, this->key.ptr, iv.ptr, enc) && + EVP_CipherUpdate(&ctx, out, &len, data.ptr, data.len) && + /* since padding is disabled this does nothing */ + EVP_CipherFinal_ex(&ctx, out + len, &len) && + EVP_CIPHER_CTX_cleanup(&ctx); } -METHOD(crypter_t, decrypt, void, +METHOD(crypter_t, decrypt, bool, private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst) { - crypt(this, data, iv, dst, 0); + return crypt(this, data, iv, dst, 0); } -METHOD(crypter_t, encrypt, void, +METHOD(crypter_t, encrypt, bool, private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst) { - crypt(this, data, iv, dst, 1); + return crypt(this, data, iv, dst, 1); } METHOD(crypter_t, get_block_size, size_t, @@ -143,10 +144,11 @@ METHOD(crypter_t, get_key_size, size_t, return this->key.len; } -METHOD(crypter_t, set_key, void, +METHOD(crypter_t, set_key, bool, private_openssl_crypter_t *this, chunk_t key) { memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len)); + return TRUE; } METHOD(crypter_t, destroy, void, diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c index 7461695ad..9cb68a3ab 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c @@ -221,13 +221,13 @@ bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp) return FALSE; } hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); - if (!hasher) + if (!hasher || !hasher->allocate_hash(hasher, key, fp)) { DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed"); + DESTROY_IF(hasher); free(key.ptr); return FALSE; } - hasher->allocate_hash(hasher, key, fp); hasher->destroy(hasher); free(key.ptr); lib->encoding->cache(lib->encoding, type, ec, *fp); diff --git a/src/libstrongswan/plugins/openssl/openssl_hasher.c b/src/libstrongswan/plugins/openssl/openssl_hasher.c index d81f4b21e..50b14698b 100644 --- a/src/libstrongswan/plugins/openssl/openssl_hasher.c +++ b/src/libstrongswan/plugins/openssl/openssl_hasher.c @@ -40,91 +40,45 @@ struct private_openssl_hasher_t { EVP_MD_CTX *ctx; }; -/** - * Mapping from the algorithms defined in IKEv2 to - * OpenSSL algorithm names - */ -typedef struct { - /** - * Identifier specified in IKEv2 - */ - int ikev2_id; - - /** - * Name of the algorithm, as used in OpenSSL - */ - char *name; -} openssl_algorithm_t; - -#define END_OF_LIST -1 - -/** - * Algorithms for integrity - */ -static openssl_algorithm_t integrity_algs[] = { - {HASH_MD2, "md2"}, - {HASH_MD5, "md5"}, - {HASH_SHA1, "sha1"}, - {HASH_SHA224, "sha224"}, - {HASH_SHA256, "sha256"}, - {HASH_SHA384, "sha384"}, - {HASH_SHA512, "sha512"}, - {HASH_MD4, "md4"}, - {END_OF_LIST, NULL}, -}; - -/** - * Look up an OpenSSL algorithm name - */ -static char* lookup_algorithm(openssl_algorithm_t *openssl_algo, - u_int16_t ikev2_algo) -{ - while (openssl_algo->ikev2_id != END_OF_LIST) - { - if (ikev2_algo == openssl_algo->ikev2_id) - { - return openssl_algo->name; - } - openssl_algo++; - } - return NULL; -} - METHOD(hasher_t, get_hash_size, size_t, private_openssl_hasher_t *this) { return this->hasher->md_size; } -METHOD(hasher_t, reset, void, +METHOD(hasher_t, reset, bool, private_openssl_hasher_t *this) { - EVP_DigestInit_ex(this->ctx, this->hasher, NULL); + return EVP_DigestInit_ex(this->ctx, this->hasher, NULL) == 1; } -METHOD(hasher_t, get_hash, void, +METHOD(hasher_t, get_hash, bool, private_openssl_hasher_t *this, chunk_t chunk, u_int8_t *hash) { - EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len); + if (EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len) != 1) + { + return FALSE; + } if (hash) { - EVP_DigestFinal_ex(this->ctx, hash, NULL); - reset(this); + if (EVP_DigestFinal_ex(this->ctx, hash, NULL) != 1) + { + return FALSE; + } + return reset(this); } + return TRUE; } -METHOD(hasher_t, allocate_hash, void, +METHOD(hasher_t, allocate_hash, bool, private_openssl_hasher_t *this, chunk_t chunk, chunk_t *hash) { if (hash) { *hash = chunk_alloc(get_hash_size(this)); - get_hash(this, chunk, hash->ptr); - } - else - { - get_hash(this, chunk, NULL); + return get_hash(this, chunk, hash->ptr); } + return get_hash(this, chunk, NULL); } METHOD(hasher_t, destroy, void, @@ -140,11 +94,11 @@ METHOD(hasher_t, destroy, void, openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo) { private_openssl_hasher_t *this; + char* name; - char* name = lookup_algorithm(integrity_algs, algo); + name = enum_to_name(hash_algorithm_short_names, algo); if (!name) { - /* algo unavailable */ return NULL; } @@ -171,7 +125,11 @@ openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo) this->ctx = EVP_MD_CTX_create(); /* initialization */ - reset(this); + if (!reset(this)) + { + destroy(this); + return NULL; + } return &this->public; } diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.c b/src/libstrongswan/plugins/openssl/openssl_hmac.c new file mode 100644 index 000000000..5d05425d3 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_hmac.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2012 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. + */ + +/* + * Copyright (C) 2012 Aleksandr Grinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <openssl/evp.h> +#include <openssl/hmac.h> + +#include "openssl_hmac.h" + +#include <crypto/mac.h> +#include <crypto/prfs/mac_prf.h> +#include <crypto/signers/mac_signer.h> + +typedef struct private_mac_t private_mac_t; + +/** + * Private data of a mac_t object. + */ +struct private_mac_t { + + /** + * Public interface + */ + mac_t public; + + /** + * Hasher to use + */ + const EVP_MD *hasher; + + /** + * Current HMAC context + */ + HMAC_CTX hmac; +}; + +METHOD(mac_t, set_key, bool, + private_mac_t *this, chunk_t key) +{ +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + return HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL); +#else /* OPENSSL_VERSION_NUMBER < 1.0 */ + HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL); + return TRUE; +#endif +} + +METHOD(mac_t, get_mac, bool, + private_mac_t *this, chunk_t data, u_int8_t *out) +{ +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + if (!HMAC_Update(&this->hmac, data.ptr, data.len)) + { + return FALSE; + } + if (out == NULL) + { + return TRUE; + } + if (!HMAC_Final(&this->hmac, out, NULL)) + { + return FALSE; + } +#else /* OPENSSL_VERSION_NUMBER < 1.0 */ + HMAC_Update(&this->hmac, data.ptr, data.len); + if (out == NULL) + { + return TRUE; + } + HMAC_Final(&this->hmac, out, NULL); +#endif + return set_key(this, chunk_empty); +} + +METHOD(mac_t, get_mac_size, size_t, + private_mac_t *this) +{ + return EVP_MD_size(this->hasher); +} + +METHOD(mac_t, destroy, void, + private_mac_t *this) +{ + HMAC_CTX_cleanup(&this->hmac); + free(this); +} + +/* + * Create an OpenSSL-backed implementation of the mac_t interface + */ +static mac_t *hmac_create(hash_algorithm_t algo) +{ + private_mac_t *this; + char *name; + + name = enum_to_name(hash_algorithm_short_names, algo); + if (!name) + { + return NULL; + } + + INIT(this, + .public = { + .get_mac = _get_mac, + .get_mac_size = _get_mac_size, + .set_key = _set_key, + .destroy = _destroy, + }, + .hasher = EVP_get_digestbyname(name), + ); + + if (!this->hasher) + { + free(this); + return NULL; + } + + HMAC_CTX_init(&this->hmac); + if (!set_key(this, chunk_empty)) + { + destroy(this); + return NULL; + } + + return &this->public; +} + +/* + * Described in header + */ +prf_t *openssl_hmac_prf_create(pseudo_random_function_t algo) +{ + mac_t *hmac; + + hmac = hmac_create(hasher_algorithm_from_prf(algo)); + if (hmac) + { + return mac_prf_create(hmac); + } + return NULL; +} + +/* + * Described in header + */ +signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo) +{ + mac_t *hmac; + size_t trunc; + + hmac = hmac_create(hasher_algorithm_from_integrity(algo, &trunc)); + if (hmac) + { + return mac_signer_create(hmac, trunc); + } + return NULL; +} + diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.h b/src/libstrongswan/plugins/openssl/openssl_hmac.h new file mode 100644 index 000000000..95ab6bfc3 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_hmac.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2012 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. + */ + +/** + * Implements HMAC based PRF and signer using OpenSSL's HMAC functions. + * + * @defgroup openssl_hmac openssl_hmac + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_HMAC_H_ +#define OPENSSL_HMAC_H_ + +#include <crypto/prfs/prf.h> +#include <crypto/signers/signer.h> + +/** + * Creates a new prf_t object based on an HMAC. + * + * @param algo algorithm to implement + * @return prf_t object, NULL if not supported + */ +prf_t *openssl_hmac_prf_create(pseudo_random_function_t algo); + +/** + * Creates a new signer_t object based on an HMAC. + * + * @param algo algorithm to implement + * @return signer_t, NULL if not supported + */ +signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo); + +#endif /** OPENSSL_HMAC_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index c93ceacc9..b69de981e 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -40,6 +40,8 @@ #include "openssl_ec_public_key.h" #include "openssl_x509.h" #include "openssl_crl.h" +#include "openssl_rng.h" +#include "openssl_hmac.h" typedef struct private_openssl_plugin_t private_openssl_plugin_t; @@ -127,7 +129,9 @@ static void destroy_function(struct CRYPTO_dynlock_value *lock, */ static unsigned long id_function(void) { - return (unsigned long)thread_current_id(); + /* ensure the thread ID is never zero, otherwise OpenSSL might try to + * acquire locks recursively */ + return 1 + (unsigned long)thread_current_id(); } /** @@ -170,7 +174,11 @@ static bool seed_rng() return FALSE; } } - rng->get_bytes(rng, sizeof(buf), buf); + if (!rng->get_bytes(rng, sizeof(buf), buf)) + { + rng->destroy(rng); + return FALSE; + } RAND_seed(buf, sizeof(buf)); } DESTROY_IF(rng); @@ -260,6 +268,41 @@ METHOD(plugin_t, get_features, int, PLUGIN_REGISTER(PRF, openssl_sha1_prf_create), PLUGIN_PROVIDE(PRF, PRF_KEYED_SHA1), #endif +#ifndef OPENSSL_NO_HMAC + PLUGIN_REGISTER(PRF, openssl_hmac_prf_create), +#ifndef OPENSSL_NO_MD5 + PLUGIN_PROVIDE(PRF, PRF_HMAC_MD5), +#endif +#ifndef OPENSSL_NO_SHA1 + PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA1), +#endif +#ifndef OPENSSL_NO_SHA256 + PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA2_256), +#endif +#ifndef OPENSSL_NO_SHA512 + PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA2_384), + PLUGIN_PROVIDE(PRF, PRF_HMAC_SHA2_512), +#endif + PLUGIN_REGISTER(SIGNER, openssl_hmac_signer_create), +#ifndef OPENSSL_NO_MD5 + PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_MD5_96), + PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_MD5_128), +#endif +#ifndef OPENSSL_NO_SHA1 + PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA1_96), + PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA1_128), + PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA1_160), +#endif +#ifndef OPENSSL_NO_SHA256 + PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_256_128), + PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_256_256), +#endif +#ifndef OPENSSL_NO_SHA512 + PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_384_192), + PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_384_384), + PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_256), +#endif +#endif /* OPENSSL_NO_HMAC */ #ifndef OPENSSL_NO_DH /* MODP DH groups */ PLUGIN_REGISTER(DH, openssl_diffie_hellman_create), @@ -284,7 +327,7 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), PLUGIN_REGISTER(PRIVKEY_GEN, openssl_rsa_private_key_gen, FALSE), PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_RSA), - PLUGIN_REGISTER(PUBKEY, openssl_rsa_public_key_load, FALSE), + PLUGIN_REGISTER(PUBKEY, openssl_rsa_public_key_load, TRUE), PLUGIN_PROVIDE(PUBKEY, KEY_RSA), PLUGIN_REGISTER(PUBKEY, openssl_rsa_public_key_load, TRUE), PLUGIN_PROVIDE(PUBKEY, KEY_ANY), @@ -317,6 +360,9 @@ METHOD(plugin_t, get_features, int, /* certificate/CRL loading */ PLUGIN_REGISTER(CERT_DECODE, openssl_x509_load, TRUE), PLUGIN_PROVIDE(CERT_DECODE, CERT_X509), + PLUGIN_SDEPEND(PUBKEY, KEY_RSA), + PLUGIN_SDEPEND(PUBKEY, KEY_ECDSA), + PLUGIN_SDEPEND(PUBKEY, KEY_DSA), PLUGIN_REGISTER(CERT_DECODE, openssl_crl_load, TRUE), PLUGIN_PROVIDE(CERT_DECODE, CERT_X509_CRL), #ifndef OPENSSL_NO_ECDH @@ -360,6 +406,9 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_ECDSA_521), #endif #endif /* OPENSSL_NO_ECDSA */ + PLUGIN_REGISTER(RNG, openssl_rng_create), + PLUGIN_PROVIDE(RNG, RNG_STRONG), + PLUGIN_PROVIDE(RNG, RNG_WEAK), }; *features = f; return countof(f); diff --git a/src/libstrongswan/plugins/openssl/openssl_rng.c b/src/libstrongswan/plugins/openssl/openssl_rng.c new file mode 100644 index 000000000..c83244f60 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_rng.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2012 Aleksandr Grinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <debug.h> +#include <openssl/rand.h> +#include <openssl/err.h> + +#include "openssl_rng.h" + +typedef struct private_openssl_rng_t private_openssl_rng_t; + +/** + * Private data of openssl_rng_t + */ +struct private_openssl_rng_t { + + /** + * Public part of this class. + */ + openssl_rng_t public; + + /** + * Quality of randomness + */ + rng_quality_t quality; +}; + +METHOD(rng_t, get_bytes, bool, + private_openssl_rng_t *this, size_t bytes, u_int8_t *buffer) +{ + u_int32_t ret; + + if (this->quality == RNG_STRONG) + { + ret = RAND_bytes((char*)buffer, bytes); + } + else + { + ret = RAND_pseudo_bytes((char*)buffer, bytes); + } + return ret != 0; +} + +METHOD(rng_t, allocate_bytes, bool, + private_openssl_rng_t *this, size_t bytes, chunk_t *chunk) +{ + *chunk = chunk_alloc(bytes); + if (!get_bytes(this, chunk->len, chunk->ptr)) + { + chunk_free(chunk); + return FALSE; + } + return TRUE; +} + +METHOD(rng_t, destroy, void, + private_openssl_rng_t *this) +{ + free(this); +} + +/* + * Described in header. + */ +openssl_rng_t *openssl_rng_create(rng_quality_t quality) +{ + private_openssl_rng_t *this; + + INIT(this, + .public = { + .rng = { + .get_bytes = _get_bytes, + .allocate_bytes = _allocate_bytes, + .destroy = _destroy, + }, + }, + .quality = quality, + ); + + return &this->public; +} diff --git a/src/libstrongswan/plugins/openssl/openssl_rng.h b/src/libstrongswan/plugins/openssl/openssl_rng.h new file mode 100644 index 000000000..a4596563a --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_rng.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 Aleksandr Grinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup openssl_rng openssl_rng + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_RNG_H_ +#define OPENSSL_RNG_H_ + +#include <library.h> + +typedef struct openssl_rng_t openssl_rng_t; + +/** + * Implementation of random number using OpenSSL. + */ +struct openssl_rng_t { + + /** + * Implements rng_t interface. + */ + rng_t rng; +}; + +/** + * Constructor to create openssl_rng_t. + * + * @param quality quality of randomness + * @return openssl_rng_t + */ +openssl_rng_t *openssl_rng_create(rng_quality_t quality); + +#endif /** OPENSSL_RNG_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index d1afd94cc..98cd700bf 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -475,7 +475,8 @@ static bool login(ENGINE *engine, chunk_t keyid) { found = TRUE; key = shared->get_key(shared); - if (snprintf(pin, sizeof(pin), "%.*s", key.len, key.ptr) >= sizeof(pin)) + if (snprintf(pin, sizeof(pin), + "%.*s", (int)key.len, key.ptr) >= sizeof(pin)) { continue; } diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index a24bae5d6..5872a8159 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -217,13 +217,13 @@ bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp) return FALSE; } hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); - if (!hasher) + if (!hasher || !hasher->allocate_hash(hasher, key, fp)) { DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed"); + DESTROY_IF(hasher); free(key.ptr); return FALSE; } - hasher->allocate_hash(hasher, key, fp); free(key.ptr); hasher->destroy(hasher); lib->encoding->cache(lib->encoding, type, rsa, *fp); diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c index 20f2fa984..8501e2cd4 100644 --- a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c +++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c @@ -35,7 +35,7 @@ struct private_openssl_sha1_prf_t { SHA_CTX ctx; }; -METHOD(prf_t, get_bytes, void, +METHOD(prf_t, get_bytes, bool, private_openssl_sha1_prf_t *this, chunk_t seed, u_int8_t *bytes) { SHA1_Update(&this->ctx, seed.ptr, seed.len); @@ -50,6 +50,8 @@ METHOD(prf_t, get_bytes, void, hash[3] = htonl(this->ctx.h3); hash[4] = htonl(this->ctx.h4); } + + return TRUE; } METHOD(prf_t, get_block_size, size_t, @@ -58,18 +60,15 @@ METHOD(prf_t, get_block_size, size_t, return HASH_SIZE_SHA1; } -METHOD(prf_t, allocate_bytes, void, +METHOD(prf_t, allocate_bytes, bool, 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); + return get_bytes(this, seed, chunk->ptr); } + return get_bytes(this, seed, NULL); } METHOD(prf_t, get_key_size, size_t, @@ -78,11 +77,15 @@ METHOD(prf_t, get_key_size, size_t, return HASH_SIZE_SHA1; } -METHOD(prf_t, set_key, void, +METHOD(prf_t, set_key, bool, private_openssl_sha1_prf_t *this, chunk_t key) { SHA1_Init(&this->ctx); + if (key.len % 4) + { + return FALSE; + } if (key.len >= 4) { this->ctx.h0 ^= untoh32(key.ptr); @@ -103,6 +106,7 @@ METHOD(prf_t, set_key, void, { this->ctx.h4 ^= untoh32(key.ptr + 16); } + return TRUE; } METHOD(prf_t, destroy, void, diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c index 5caf5182c..e85c5cc90 100644 --- a/src/libstrongswan/plugins/openssl/openssl_x509.c +++ b/src/libstrongswan/plugins/openssl/openssl_x509.c @@ -350,7 +350,8 @@ METHOD(certificate_t, has_issuer, id_match_t, } METHOD(certificate_t, issued_by, bool, - private_openssl_x509_t *this, certificate_t *issuer) + private_openssl_x509_t *this, certificate_t *issuer, + signature_scheme_t *scheme) { public_key_t *key; bool valid; @@ -393,6 +394,10 @@ METHOD(certificate_t, issued_by, bool, openssl_asn1_str2chunk(this->x509->signature)); free(tbs.ptr); key->destroy(key); + if (valid && scheme) + { + *scheme = this->scheme; + } return valid; } @@ -968,14 +973,14 @@ static bool parse_certificate(private_openssl_x509_t *this) parse_extKeyUsage(this); hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); - if (!hasher) + if (!hasher || !hasher->allocate_hash(hasher, this->encoding, &this->hash)) { + DESTROY_IF(hasher); return FALSE; } - hasher->allocate_hash(hasher, this->encoding, &this->hash); hasher->destroy(hasher); - if (issued_by(this, &this->public.x509.interface)) + if (issued_by(this, &this->public.x509.interface, NULL)) { this->flags |= X509_SELF_SIGNED; } |