diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-12-05 16:15:54 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-12-05 16:15:54 +0000 |
commit | c7f1b0530b85bc7654e68992f25ed8ced5d0a80d (patch) | |
tree | 861798cd7da646014ed6919766b053099646710d /src/libstrongswan/plugins/openssl | |
parent | 8b80ab5a6950ce6515f477624794defd7531642a (diff) | |
download | vyos-strongswan-c7f1b0530b85bc7654e68992f25ed8ced5d0a80d.tar.gz vyos-strongswan-c7f1b0530b85bc7654e68992f25ed8ced5d0a80d.zip |
[svn-upgrade] Integrating new upstream version, strongswan (4.2.9)
Diffstat (limited to 'src/libstrongswan/plugins/openssl')
5 files changed, 200 insertions, 91 deletions
diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c index 95c079b0b..7c83b3dea 100644 --- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -12,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: openssl_diffie_hellman.c 3896 2008-04-29 15:42:34Z tobias $ + * $Id: openssl_diffie_hellman.c 4639 2008-11-12 15:09:24Z martin $ */ #include <openssl/dh.h> @@ -38,23 +39,28 @@ struct modulus_entry_t { BIGNUM *(*get_prime)(BIGNUM *bn); /* + * Optimum length of exponent in bits. + */ + long opt_exponent_len; + + /* * Generator value. */ u_int16_t generator; }; /** - * All supported modulus values. + * All supported modulus values - optimum exponent size according to RFC 3526. */ static modulus_entry_t modulus_entries[] = { - {MODP_768_BIT, get_rfc2409_prime_768, 2}, - {MODP_1024_BIT, get_rfc2409_prime_1024, 2}, - {MODP_1536_BIT, get_rfc3526_prime_1536, 2}, - {MODP_2048_BIT, get_rfc3526_prime_2048, 2}, - {MODP_3072_BIT, get_rfc3526_prime_3072, 2}, - {MODP_4096_BIT, get_rfc3526_prime_4096, 2}, - {MODP_6144_BIT, get_rfc3526_prime_6144, 2}, - {MODP_8192_BIT, get_rfc3526_prime_8192, 2}, + {MODP_768_BIT, get_rfc2409_prime_768, 256, 2}, + {MODP_1024_BIT, get_rfc2409_prime_1024, 256, 2}, + {MODP_1536_BIT, get_rfc3526_prime_1536, 256, 2}, + {MODP_2048_BIT, get_rfc3526_prime_2048, 384, 2}, + {MODP_3072_BIT, get_rfc3526_prime_3072, 384, 2}, + {MODP_4096_BIT, get_rfc3526_prime_4096, 512, 2}, + {MODP_6144_BIT, get_rfc3526_prime_6144, 512, 2}, + {MODP_8192_BIT, get_rfc3526_prime_8192, 512, 2}, }; typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t; @@ -87,7 +93,7 @@ struct private_openssl_diffie_hellman_t { * Shared secret */ chunk_t shared_secret; - + /** * True if shared secret is computed */ @@ -95,68 +101,57 @@ struct private_openssl_diffie_hellman_t { }; /** - * Convert a BIGNUM to a chunk - */ -static void bn2chunk(BIGNUM *bn, chunk_t *chunk) -{ - chunk->len = BN_num_bytes(bn); - chunk->ptr = malloc(chunk->len); - BN_bn2bin(bn, chunk->ptr); -} - -/** - * Implementation of openssl_diffie_hellman_t.set_other_public_value. + * Implementation of openssl_diffie_hellman_t.get_my_public_value. */ -static void set_other_public_value(private_openssl_diffie_hellman_t *this, chunk_t value) +static void get_my_public_value(private_openssl_diffie_hellman_t *this, + chunk_t *value) { - int len; - BN_bin2bn(value.ptr, value.len, this->pub_key); - - len = DH_size(this->dh); - chunk_free(&this->shared_secret); - this->shared_secret = chunk_alloc(len); - - if (DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh) < 0) { - DBG1("DH shared secret computation failed"); - return; - } - - this->computed = TRUE; + *value = chunk_alloc(DH_size(this->dh)); + memset(value->ptr, 0, value->len); + BN_bn2bin(this->dh->pub_key, + value->ptr + value->len - BN_num_bytes(this->dh->pub_key)); } /** - * Implementation of openssl_diffie_hellman_t.get_other_public_value. + * Implementation of openssl_diffie_hellman_t.get_shared_secret. */ -static status_t get_other_public_value(private_openssl_diffie_hellman_t *this, - chunk_t *value) +static status_t get_shared_secret(private_openssl_diffie_hellman_t *this, + chunk_t *secret) { if (!this->computed) { return FAILED; } - bn2chunk(this->pub_key, value); + /* shared secret should requires a len according the DH group */ + *secret = chunk_alloc(DH_size(this->dh)); + memset(secret->ptr, 0, secret->len); + memcpy(secret->ptr + secret->len - this->shared_secret.len, + this->shared_secret.ptr, this->shared_secret.len); + return SUCCESS; } -/** - * Implementation of openssl_diffie_hellman_t.get_my_public_value. - */ -static void get_my_public_value(private_openssl_diffie_hellman_t *this,chunk_t *value) -{ - bn2chunk(this->dh->pub_key, value); -} /** - * Implementation of openssl_diffie_hellman_t.get_shared_secret. + * Implementation of openssl_diffie_hellman_t.set_other_public_value. */ -static status_t get_shared_secret(private_openssl_diffie_hellman_t *this, chunk_t *secret) +static void set_other_public_value(private_openssl_diffie_hellman_t *this, + chunk_t value) { - if (!this->computed) + int len; + + BN_bin2bn(value.ptr, value.len, this->pub_key); + chunk_clear(&this->shared_secret); + this->shared_secret.ptr = malloc(DH_size(this->dh)); + memset(this->shared_secret.ptr, 0xFF, this->shared_secret.len); + len = DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh); + if (len < 0) { - return FAILED; + DBG1("DH shared secret computation failed"); + return; } - *secret = chunk_clone(this->shared_secret); - return SUCCESS; + this->shared_secret.len = len; + this->computed = TRUE; } /** @@ -173,6 +168,11 @@ static diffie_hellman_group_t get_dh_group(private_openssl_diffie_hellman_t *thi static status_t set_modulus(private_openssl_diffie_hellman_t *this) { int i; + bool ansi_x9_42; + + ansi_x9_42 = lib->settings->get_bool(lib->settings, + "charon.dh_exponent_ansi_x9_42", TRUE); + for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++) { if (modulus_entries[i].group == this->group) @@ -180,6 +180,10 @@ static status_t set_modulus(private_openssl_diffie_hellman_t *this) this->dh->p = modulus_entries[i].get_prime(NULL); this->dh->g = BN_new(); BN_set_word(this->dh->g, modulus_entries[i].generator); + if (!ansi_x9_42) + { + this->dh->length = modulus_entries[i].opt_exponent_len; + } return SUCCESS; } } @@ -193,7 +197,7 @@ static void destroy(private_openssl_diffie_hellman_t *this) { BN_clear_free(this->pub_key); DH_free(this->dh); - chunk_free(&this->shared_secret); + chunk_clear(&this->shared_secret); free(this); } @@ -206,7 +210,6 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t g this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value; - this->public.dh.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value; this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value; this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group; this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy; @@ -220,7 +223,6 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t g this->group = group; this->computed = FALSE; - this->pub_key = BN_new(); this->shared_secret = chunk_empty; @@ -237,6 +239,7 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t g destroy(this); return NULL; } + DBG2("size of DH secret exponent: %d bits", BN_num_bits(this->dh->priv_key)); return &this->public; } diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c index 9d2bd44cd..9a89ad045 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: openssl_ec_diffie_hellman.c 4052 2008-06-10 09:19:18Z tobias $ + * $Id: openssl_ec_diffie_hellman.c 4566 2008-11-04 13:12:11Z martin $ */ #include <openssl/ec.h> @@ -217,24 +217,6 @@ static void set_other_public_value(private_openssl_ec_diffie_hellman_t *this, ch } /** - * Implementation of openssl_ec_diffie_hellman_t.get_other_public_value. - */ -static status_t get_other_public_value(private_openssl_ec_diffie_hellman_t *this, - chunk_t *value) -{ - if (!this->computed) - { - return FAILED; - } - - if (!ecp2chunk(this->ec_group, this->pub_key, value)) - { - return FAILED; - } - return SUCCESS; -} - -/** * Implementation of openssl_ec_diffie_hellman_t.get_my_public_value. */ static void get_my_public_value(private_openssl_ec_diffie_hellman_t *this,chunk_t *value) @@ -283,7 +265,6 @@ openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(diffie_hellman_gro this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value; - this->public.dh.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value; this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value; this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group; this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy; diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index 82c54a95e..dcc78aed6 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -12,15 +13,18 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: openssl_plugin.c 4309 2008-08-28 11:07:57Z martin $ + * $Id: openssl_plugin.c 4583 2008-11-05 12:37:37Z martin $ */ #include <openssl/evp.h> #include <openssl/engine.h> +#include <openssl/crypto.h> +#include <pthread.h> #include "openssl_plugin.h" #include <library.h> +#include <utils/mutex.h> #include "openssl_crypter.h" #include "openssl_hasher.h" #include "openssl_diffie_hellman.h" @@ -44,6 +48,120 @@ struct private_openssl_plugin_t { }; /** + * Array of static mutexs, with CRYPTO_num_locks() mutex + */ +static mutex_t **mutex = NULL; + +/** + * Locking callback for static locks + */ +static void locking_function(int mode, int type, const char *file, int line) +{ + if (mutex) + { + if (mode & CRYPTO_LOCK) + { + mutex[type]->lock(mutex[type]); + } + else + { + mutex[type]->unlock(mutex[type]); + } + } +} + +/** + * Implementation of dynlock + */ +struct CRYPTO_dynlock_value { + mutex_t *mutex; +}; + +/** + * Callback to create a dynamic lock + */ +static struct CRYPTO_dynlock_value *create_function(const char *file, int line) +{ + struct CRYPTO_dynlock_value *lock; + + lock = malloc_thing(struct CRYPTO_dynlock_value); + lock->mutex = mutex_create(MUTEX_DEFAULT); + return lock; +} + +/** + * Callback to (un-)lock a dynamic lock + */ +static void lock_function(int mode, struct CRYPTO_dynlock_value *lock, + const char *file, int line) +{ + if (mode & CRYPTO_LOCK) + { + lock->mutex->lock(lock->mutex); + } + else + { + lock->mutex->unlock(lock->mutex); + } +} + +/** + * Callback to destroy a dynamic lock + */ +static void destroy_function(struct CRYPTO_dynlock_value *lock, + const char *file, int line) +{ + lock->mutex->destroy(lock->mutex); + free(lock); +} + +/** + * Thread-ID callback function + */ +static unsigned long id_function(void) +{ + return pthread_self(); +} + +/** + * initialize OpenSSL for multi-threaded use + */ +static void threading_init() +{ + int i, num_locks; + + CRYPTO_set_id_callback(id_function); + CRYPTO_set_locking_callback(locking_function); + + CRYPTO_set_dynlock_create_callback(create_function); + CRYPTO_set_dynlock_lock_callback(lock_function); + CRYPTO_set_dynlock_destroy_callback(destroy_function); + + num_locks = CRYPTO_num_locks(); + mutex = malloc(sizeof(mutex_t*) * num_locks); + for (i = 0; i < num_locks; i++) + { + mutex[i] = mutex_create(MUTEX_DEFAULT); + } +} + +/** + * cleanup OpenSSL threading locks + */ +static void threading_cleanup() +{ + int i, num_locks; + + num_locks = CRYPTO_num_locks(); + for (i = 0; i < num_locks; i++) + { + mutex[i]->destroy(mutex[i]); + } + free(mutex); + mutex = NULL; +} + +/** * Implementation of openssl_plugin_t.destroy */ static void destroy(private_openssl_plugin_t *this) @@ -68,6 +186,8 @@ static void destroy(private_openssl_plugin_t *this) ENGINE_cleanup(); EVP_cleanup(); + threading_cleanup(); + free(this); } @@ -80,6 +200,8 @@ plugin_t *plugin_create() this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + threading_init(); + OpenSSL_add_all_algorithms(); /* activate support for hardware accelerators */ diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index 8ad75215a..a815ce622 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: openssl_rsa_private_key.c 4317 2008-09-02 11:00:13Z martin $ + * $Id: openssl_rsa_private_key.c 4564 2008-11-04 13:01:36Z martin $ */ #include "openssl_rsa_private_key.h" @@ -74,9 +74,11 @@ openssl_rsa_public_key_t *openssl_rsa_public_key_create_from_n_e(BIGNUM *n, BIGN * Build an EMPSA PKCS1 signature described in PKCS#1 */ static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this, - int type, chunk_t data, chunk_t *signature) + int type, chunk_t data, chunk_t *out) { bool success = FALSE; + u_char *sig = NULL; + u_int len; const EVP_MD *hasher = EVP_get_digestbynid(type); if (!hasher) { @@ -105,14 +107,17 @@ static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this, goto error; } - *signature = chunk_alloc(RSA_size(this->rsa)); - - if (!EVP_SignFinal(ctx, signature->ptr, &signature->len, key)) + sig = malloc(EVP_PKEY_size(key)); + if (EVP_SignFinal(ctx, sig, &len, key)) { - goto error; + out->ptr = sig; + out->len = len; + success = TRUE; + } + else + { + free(sig); } - - success = TRUE; error: if (key) diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index 61b5b9b64..794fa8123 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: openssl_rsa_public_key.c 4317 2008-09-02 11:00:13Z martin $ + * $Id: openssl_rsa_public_key.c 4567 2008-11-04 14:05:42Z martin $ */ #include "openssl_rsa_public_key.h" @@ -90,13 +90,11 @@ static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this, goto error; } - /* remove any preceding 0-bytes from signature */ - while (signature.len && *(signature.ptr) == 0x00) + /* VerifyFinal expects a signature of exactly RSA size (no leading 0x00) */ + if (signature.len > RSA_size(this->rsa)) { - signature.len -= 1; - signature.ptr++; + signature = chunk_skip(signature, signature.len - RSA_size(this->rsa)); } - valid = (EVP_VerifyFinal(ctx, signature.ptr, signature.len, key) == 1); error: |