From a6c43a8d8acd3eceeaa3992a368374759bb838c8 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 11:01:43 +0200 Subject: [PATCH 01/18] openssl: OpenSSL 1.1.0 is thread-safe so we don't have to setup callbacks --- src/libstrongswan/plugins/openssl/openssl_plugin.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index e5c1dc0ee..ef02676f4 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -65,6 +65,11 @@ struct private_openssl_plugin_t { openssl_plugin_t public; }; +/** + * OpenSSL is thread-safe since 1.1.0 + */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + /** * Array of static mutexs, with CRYPTO_num_locks() mutex */ @@ -227,6 +232,14 @@ static void threading_cleanup() cleanup->destroy(cleanup); } +#else /* OPENSSL_VERSION_NUMBER */ + +#define threading_init() + +#define threading_cleanup() + +#endif + /** * Seed the OpenSSL RNG, if required */ From e2abe7ae975fa55d4d21210de7186c74a03604d4 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 11:02:36 +0200 Subject: [PATCH 02/18] openssl: Update initialization and cleanup for OpenSSL 1.1.0 We can't call OPENSSL_cleanup() as that would prevent us from re-initializing the library again (which we use in the Android app, that loads/unloads plugins). --- .../plugins/openssl/openssl_plugin.c | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index ef02676f4..3e3b986df 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -515,6 +515,10 @@ METHOD(plugin_t, get_features, int, METHOD(plugin_t, destroy, void, private_openssl_plugin_t *this) { +/* OpenSSL 1.1.0 cleans up itself at exit and while OPENSSL_cleanup() exists we + * can't call it as we couldn't re-initialize the library (as required by the + * unit tests and the Android app) */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L #ifndef OPENSSL_IS_BORINGSSL CONF_modules_free(); OBJ_cleanup(); @@ -526,6 +530,7 @@ METHOD(plugin_t, destroy, void, CRYPTO_cleanup_all_ex_data(); threading_cleanup(); ERR_free_strings(); +#endif /* OPENSSL_VERSION_NUMBER */ free(this); } @@ -568,12 +573,23 @@ plugin_t *openssl_plugin_create() }, ); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + /* note that we can't call OPENSSL_cleanup() when the plugin is destroyed + * as we couldn't initialize the library again afterwards */ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG | + OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL); +#else /* OPENSSL_VERSION_NUMBER */ threading_init(); - #ifndef OPENSSL_IS_BORINGSSL OPENSSL_config(NULL); #endif OpenSSL_add_all_algorithms(); +#ifndef OPENSSL_NO_ENGINE + /* activate support for hardware accelerators */ + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); +#endif /* OPENSSL_NO_ENGINE */ +#endif /* OPENSSL_VERSION_NUMBER */ #ifdef OPENSSL_FIPS /* we do this here as it may have been enabled via openssl.conf */ @@ -582,12 +598,6 @@ plugin_t *openssl_plugin_create() "openssl FIPS mode(%d) - %sabled ", fips_mode, fips_mode ? "en" : "dis"); #endif /* OPENSSL_FIPS */ -#ifndef OPENSSL_NO_ENGINE - /* activate support for hardware accelerators */ - ENGINE_load_builtin_engines(); - ENGINE_register_all_complete(); -#endif /* OPENSSL_NO_ENGINE */ - if (!seed_rng()) { DBG1(DBG_CFG, "no RNG found to seed OpenSSL"); From faa904fb0baa1bd805432634f921fda6ce96b284 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 11:17:31 +0200 Subject: [PATCH 03/18] openssl: Fix mapping from ASN1 to chunk_t with OpenSSL 1.1.0 ASN1_OBJECT is now opaque. --- src/libstrongswan/plugins/openssl/openssl_util.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_util.c b/src/libstrongswan/plugins/openssl/openssl_util.c index 914060358..a1d675f78 100644 --- a/src/libstrongswan/plugins/openssl/openssl_util.c +++ b/src/libstrongswan/plugins/openssl/openssl_util.c @@ -22,6 +22,12 @@ #include #include +/* these were added with 1.1.0 when ASN1_OBJECT was made opaque */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define OBJ_get0_data(o) ((o)->data) +#define OBJ_length(o) ((o)->length) +#endif + /** * Described in header. */ @@ -149,7 +155,7 @@ chunk_t openssl_asn1_obj2chunk(ASN1_OBJECT *asn1) { if (asn1) { - return chunk_create((u_char*)asn1->data, asn1->length); + return chunk_create((u_char*)OBJ_get0_data(asn1), OBJ_length(asn1)); } return chunk_empty; } From 1b36fbedf5707ea4318ae9216d3c65aebe1917da Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 11:17:56 +0200 Subject: [PATCH 04/18] openssl: Update crypter API to OpenSSL 1.1.0 EVP_CIPHER and EVP_CIPHER_CTX are now opaque types, the getters already existed before. --- .../plugins/openssl/openssl_crypter.c | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_crypter.c b/src/libstrongswan/plugins/openssl/openssl_crypter.c index 72a9ad92a..b9085f9aa 100644 --- a/src/libstrongswan/plugins/openssl/openssl_crypter.c +++ b/src/libstrongswan/plugins/openssl/openssl_crypter.c @@ -93,8 +93,10 @@ static char* lookup_algorithm(uint16_t ikev2_algo, size_t *key_size) static bool crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst, int enc) { + EVP_CIPHER_CTX *ctx; int len; u_char *out; + bool success = FALSE; out = data.ptr; if (dst) @@ -102,16 +104,19 @@ static bool crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv, *dst = chunk_alloc(data.len); out = dst->ptr; } - EVP_CIPHER_CTX ctx; - EVP_CIPHER_CTX_init(&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); + ctx = EVP_CIPHER_CTX_new(); + if (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)) + { + success = TRUE; + } + EVP_CIPHER_CTX_free(ctx); + return success; } METHOD(crypter_t, decrypt, bool, @@ -129,13 +134,13 @@ METHOD(crypter_t, encrypt, bool, METHOD(crypter_t, get_block_size, size_t, private_openssl_crypter_t *this) { - return this->cipher->block_size; + return EVP_CIPHER_block_size(this->cipher); } METHOD(crypter_t, get_iv_size, size_t, private_openssl_crypter_t *this) { - return this->cipher->iv_len; + return EVP_CIPHER_iv_length(this->cipher); } METHOD(crypter_t, get_key_size, size_t, From 54d629b7ad997a1ab5db655901c27622e5ff8187 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 11:47:26 +0200 Subject: [PATCH 05/18] openssl: Update DH API to OpenSSL 1.1.0 --- .../plugins/openssl/openssl_diffie_hellman.c | 52 +++++++++++++++---- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c index 5b1859b35..f08dfff7e 100644 --- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c @@ -22,9 +22,17 @@ #include #include "openssl_diffie_hellman.h" +#include "openssl_util.h" #include +/* these were added with 1.1.0 when DH was made opaque */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L +OPENSSL_KEY_FALLBACK(DH, key, pub_key, priv_key) +OPENSSL_KEY_FALLBACK(DH, pqg, p, q, g) +#define DH_set_length(dh, len) ({ (dh)->length = len; 1; }) +#endif + typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t; /** @@ -65,10 +73,12 @@ struct private_openssl_diffie_hellman_t { METHOD(diffie_hellman_t, get_my_public_value, bool, private_openssl_diffie_hellman_t *this, chunk_t *value) { + const BIGNUM *pubkey; + *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)); + DH_get0_key(this->dh, &pubkey, NULL); + BN_bn2bin(pubkey, value->ptr + value->len - BN_num_bytes(pubkey)); return TRUE; } @@ -116,8 +126,15 @@ METHOD(diffie_hellman_t, set_other_public_value, bool, METHOD(diffie_hellman_t, set_private_value, bool, private_openssl_diffie_hellman_t *this, chunk_t value) { - if (BN_bin2bn(value.ptr, value.len, this->dh->priv_key)) + BIGNUM *privkey; + + privkey = BN_bin2bn(value.ptr, value.len, NULL); + if (privkey) { + if (!DH_set0_key(this->dh, NULL, privkey)) + { + return FALSE; + } chunk_clear(&this->shared_secret); this->computed = FALSE; return DH_generate_key(this->dh); @@ -136,19 +153,28 @@ METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t, */ static status_t set_modulus(private_openssl_diffie_hellman_t *this) { + BIGNUM *p, *g; + diffie_hellman_params_t *params = diffie_hellman_get_params(this->group); if (!params) { return NOT_FOUND; } - this->dh->p = BN_bin2bn(params->prime.ptr, params->prime.len, NULL); - this->dh->g = BN_bin2bn(params->generator.ptr, params->generator.len, NULL); + p = BN_bin2bn(params->prime.ptr, params->prime.len, NULL); + g = BN_bin2bn(params->generator.ptr, params->generator.len, NULL); + if (!DH_set0_pqg(this->dh, p, NULL, g)) + { + return FAILED; + } if (params->exp_len != params->prime.len) { #ifdef OPENSSL_IS_BORINGSSL this->dh->priv_length = params->exp_len * 8; #else - this->dh->length = params->exp_len * 8; + if (!DH_set_length(this->dh, params->exp_len * 8)) + { + return FAILED; + } #endif } return SUCCESS; @@ -170,6 +196,7 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create( diffie_hellman_group_t group, chunk_t g, chunk_t p) { private_openssl_diffie_hellman_t *this; + const BIGNUM *privkey; INIT(this, .public = { @@ -198,8 +225,12 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create( if (group == MODP_CUSTOM) { - this->dh->p = BN_bin2bn(p.ptr, p.len, NULL); - this->dh->g = BN_bin2bn(g.ptr, g.len, NULL); + if (!DH_set0_pqg(this->dh, BN_bin2bn(p.ptr, p.len, NULL), NULL, + BN_bin2bn(g.ptr, g.len, NULL))) + { + destroy(this); + return NULL; + } } else { @@ -217,9 +248,8 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create( destroy(this); return NULL; } - DBG2(DBG_LIB, "size of DH secret exponent: %d bits", - BN_num_bits(this->dh->priv_key)); - + DH_get0_key(this->dh, NULL, &privkey); + DBG2(DBG_LIB, "size of DH secret exponent: %d bits", BN_num_bits(privkey)); return &this->public; } From 6d5df086f77074d5e449f308dc6c33923177de54 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 28 Jun 2016 15:19:57 +0200 Subject: [PATCH 06/18] openssl: Add macro to define fallback functions for non-opaque OpenSSL versions --- .../plugins/openssl/openssl_util.h | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/libstrongswan/plugins/openssl/openssl_util.h b/src/libstrongswan/plugins/openssl/openssl_util.h index 2db073139..264d47069 100644 --- a/src/libstrongswan/plugins/openssl/openssl_util.h +++ b/src/libstrongswan/plugins/openssl/openssl_util.h @@ -134,4 +134,42 @@ int openssl_asn1_known_oid(ASN1_OBJECT *obj); */ time_t openssl_asn1_to_time(ASN1_TIME *time); +/** + * Macros to define fallback getters/setters to access keys (BIGNUM*) for types + * that were made opaque with OpenSSL 1.1.0. + */ +#define OPENSSL_KEY_FALLBACK(...) VA_ARGS_DISPATCH(OPENSSL_KEY_FALLBACK, __VA_ARGS__)(__VA_ARGS__) +#define OPENSSL_KEY_FALLBACK3(type, k1, k2) \ +__attribute__((unused)) \ +static inline void type##_get0(const type *o, const BIGNUM **k1, const BIGNUM **k2) { \ + if (k1) *k1 = o->k1; \ + if (k2) *k2 = o->k2; } \ +__attribute__((unused)) \ +static inline int type##_set0(type *o, BIGNUM *k1, BIGNUM *k2) { \ + if (k1) { BN_clear_free(o->k1); o->k1 = k1; } \ + if (k2) { BN_clear_free(o->k2); o->k2 = k2; } \ + return 1; } +#define OPENSSL_KEY_FALLBACK4(type, name, k1, k2) \ +__attribute__((unused)) \ +static inline void type##_get0_##name(const type *o, const BIGNUM **k1, const BIGNUM **k2) { \ + if (k1) *k1 = o->k1; \ + if (k2) *k2 = o->k2; } \ +__attribute__((unused)) \ +static inline int type##_set0_##name(type *o, BIGNUM *k1, BIGNUM *k2) { \ + if (k1) { BN_clear_free(o->k1); o->k1 = k1; } \ + if (k2) { BN_clear_free(o->k2); o->k2 = k2; } \ + return 1; } +#define OPENSSL_KEY_FALLBACK5(type, name, k1, k2, k3) \ +__attribute__((unused)) \ +static inline void type##_get0_##name(const type *o, const BIGNUM **k1, const BIGNUM **k2, const BIGNUM **k3) { \ + if (k1) *k1 = o->k1; \ + if (k2) *k2 = o->k2; \ + if (k3) *k3 = o->k3; } \ +__attribute__((unused)) \ +static inline int type##_set0_##name(type *o, BIGNUM *k1, BIGNUM *k2, BIGNUM *k3) { \ + if (k1) { BN_clear_free(o->k1); o->k1 = k1; } \ + if (k2) { BN_clear_free(o->k2); o->k2 = k2; } \ + if (k3) { BN_clear_free(o->k3); o->k3 = k3; } \ + return 1; } + #endif /** OPENSSL_UTIL_H_ @}*/ From 375a5ed2400ba51918f01623ee0067acb2960d9d Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 12:07:50 +0200 Subject: [PATCH 07/18] openssl: Make some utilities take const BIGNUM pointers --- src/libstrongswan/plugins/openssl/openssl_util.c | 5 +++-- src/libstrongswan/plugins/openssl/openssl_util.h | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_util.c b/src/libstrongswan/plugins/openssl/openssl_util.c index a1d675f78..6580e1c7d 100644 --- a/src/libstrongswan/plugins/openssl/openssl_util.c +++ b/src/libstrongswan/plugins/openssl/openssl_util.c @@ -76,7 +76,8 @@ error: /** * Described in header. */ -bool openssl_bn_cat(int len, BIGNUM *a, BIGNUM *b, chunk_t *chunk) +bool openssl_bn_cat(const int len, const BIGNUM *a, const BIGNUM *b, + chunk_t *chunk) { int offset; @@ -133,7 +134,7 @@ bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b) /** * Described in header. */ -bool openssl_bn2chunk(BIGNUM *bn, chunk_t *chunk) +bool openssl_bn2chunk(const BIGNUM *bn, chunk_t *chunk) { *chunk = chunk_alloc(BN_num_bytes(bn)); if (BN_bn2bin(bn, chunk->ptr) == chunk->len) diff --git a/src/libstrongswan/plugins/openssl/openssl_util.h b/src/libstrongswan/plugins/openssl/openssl_util.h index 264d47069..f4186e8c4 100644 --- a/src/libstrongswan/plugins/openssl/openssl_util.h +++ b/src/libstrongswan/plugins/openssl/openssl_util.h @@ -60,7 +60,8 @@ bool openssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash); * @param chunk resulting chunk * @return TRUE on success, FALSE otherwise */ -bool openssl_bn_cat(int len, BIGNUM *a, BIGNUM *b, chunk_t *chunk); +bool openssl_bn_cat(const int len, const BIGNUM *a, const BIGNUM *b, + chunk_t *chunk); /** * Splits a chunk into two bignums of equal binary length. @@ -80,7 +81,7 @@ bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b); * @param chunk the chunk (data gets allocated) * @return TRUE on success, FALSE otherwise */ -bool openssl_bn2chunk(BIGNUM *bn, chunk_t *chunk); +bool openssl_bn2chunk(const BIGNUM *bn, chunk_t *chunk); /** * Allocate a chunk using the i2d function of a given object From 3fb2c8edb7bf15969ff99b6bbb2e6cf789193b87 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 12:08:29 +0200 Subject: [PATCH 08/18] openssl: Update RSA API to OpenSSL 1.1.0 --- .../plugins/openssl/openssl_rsa_private_key.c | 41 +++++++++++++++---- .../plugins/openssl/openssl_rsa_public_key.c | 27 ++++++++---- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index de02f302d..485e0bbc7 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -20,6 +20,7 @@ #include "openssl_rsa_private_key.h" #include "openssl_rsa_public_key.h" +#include "openssl_util.h" #include @@ -35,6 +36,12 @@ */ #define PUBLIC_EXPONENT 0x10001 +#if OPENSSL_VERSION_NUMBER < 0x10100000L +OPENSSL_KEY_FALLBACK(RSA, key, n, e, d) +OPENSSL_KEY_FALLBACK(RSA, factors, p, q) +OPENSSL_KEY_FALLBACK(RSA, crt_params, dmp1, dmq1, iqmp) +#endif + typedef struct private_openssl_rsa_private_key_t private_openssl_rsa_private_key_t; /** @@ -436,22 +443,38 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type, } else if (n.ptr && e.ptr && d.ptr && p.ptr && q.ptr && coeff.ptr) { + BIGNUM *bn_n, *bn_e, *bn_d, *bn_p, *bn_q; + BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; + this->rsa = RSA_new(); - this->rsa->n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL); - this->rsa->e = BN_bin2bn((const u_char*)e.ptr, e.len, NULL); - this->rsa->d = BN_bin2bn((const u_char*)d.ptr, d.len, NULL); - this->rsa->p = BN_bin2bn((const u_char*)p.ptr, p.len, NULL); - this->rsa->q = BN_bin2bn((const u_char*)q.ptr, q.len, NULL); + + bn_n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL); + bn_e = BN_bin2bn((const u_char*)e.ptr, e.len, NULL); + bn_d = BN_bin2bn((const u_char*)d.ptr, d.len, NULL); + if (!RSA_set0_key(this->rsa, bn_n, bn_e, bn_d)) + { + destroy(this); + return NULL; + + } + bn_p = BN_bin2bn((const u_char*)p.ptr, p.len, NULL); + bn_q = BN_bin2bn((const u_char*)q.ptr, q.len, NULL); + if (!RSA_set0_factors(this->rsa, bn_p, bn_q)) + { + destroy(this); + return NULL; + } if (exp1.ptr) { - this->rsa->dmp1 = BN_bin2bn((const u_char*)exp1.ptr, exp1.len, NULL); + dmp1 = BN_bin2bn((const u_char*)exp1.ptr, exp1.len, NULL); } if (exp2.ptr) { - this->rsa->dmq1 = BN_bin2bn((const u_char*)exp2.ptr, exp2.len, NULL); + dmq1 = BN_bin2bn((const u_char*)exp2.ptr, exp2.len, NULL); } - this->rsa->iqmp = BN_bin2bn((const u_char*)coeff.ptr, coeff.len, NULL); - if (RSA_check_key(this->rsa) == 1) + iqmp = BN_bin2bn((const u_char*)coeff.ptr, coeff.len, NULL); + if (RSA_set0_crt_params(this->rsa, dmp1, dmq1, iqmp) && + RSA_check_key(this->rsa) == 1) { return &this->public; } diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index db928569f..d66d5016e 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -28,6 +28,10 @@ #include #include +#if OPENSSL_VERSION_NUMBER < 0x10100000L +OPENSSL_KEY_FALLBACK(RSA, key, n, e, d) +#endif + typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t; /** @@ -224,11 +228,13 @@ bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp) break; default: { + const BIGNUM *bn_n, *bn_e; chunk_t n = chunk_empty, e = chunk_empty; bool success = FALSE; - if (openssl_bn2chunk(rsa->n, &n) && - openssl_bn2chunk(rsa->e, &e)) + RSA_get0_key(rsa, &bn_n, &bn_e, NULL); + if (openssl_bn2chunk(bn_n, &n) && + openssl_bn2chunk(bn_e, &e)) { success = lib->encoding->encode(lib->encoding, type, rsa, fp, CRED_PART_RSA_MODULUS, n, @@ -297,10 +303,12 @@ METHOD(public_key_t, get_encoding, bool, } default: { + const BIGNUM *bn_n, *bn_e; chunk_t n = chunk_empty, e = chunk_empty; - if (openssl_bn2chunk(this->rsa->n, &n) && - openssl_bn2chunk(this->rsa->e, &e)) + RSA_get0_key(this->rsa, &bn_n, &bn_e, NULL); + if (openssl_bn2chunk(bn_n, &n) && + openssl_bn2chunk(bn_e, &e)) { success = lib->encoding->encode(lib->encoding, type, NULL, encoding, CRED_PART_RSA_MODULUS, n, @@ -416,10 +424,15 @@ openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type, } else if (n.ptr && e.ptr && type == KEY_RSA) { + BIGNUM *bn_n, *bn_e; + this->rsa = RSA_new(); - this->rsa->n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL); - this->rsa->e = BN_bin2bn((const u_char*)e.ptr, e.len, NULL); - return &this->public; + bn_n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL); + bn_e = BN_bin2bn((const u_char*)e.ptr, e.len, NULL); + if (RSA_set0_key(this->rsa, bn_n, bn_e, NULL)) + { + return &this->public; + } } destroy(this); return NULL; From 6688f7986eaa3defeb6136021d635e53a5f4cfdb Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 12:36:32 +0200 Subject: [PATCH 09/18] openssl: Update ECDSA API to OpenSSL 1.1.0 --- .../plugins/openssl/openssl_ec_private_key.c | 10 ++++++++-- .../plugins/openssl/openssl_ec_public_key.c | 19 ++++++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c index bc7884c99..24fe623eb 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c @@ -28,6 +28,10 @@ #include #include +#if OPENSSL_VERSION_NUMBER < 0x10100000L +OPENSSL_KEY_FALLBACK(ECDSA_SIG, r, s) +#endif + typedef struct private_openssl_ec_private_key_t private_openssl_ec_private_key_t; /** @@ -59,15 +63,17 @@ bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp); static bool build_signature(private_openssl_ec_private_key_t *this, chunk_t hash, chunk_t *signature) { - bool built = FALSE; + const BIGNUM *r, *s; ECDSA_SIG *sig; + bool built = FALSE; sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec); if (sig) { + ECDSA_SIG_get0(sig, &r, &s); /* concatenate BNs r/s to a signature chunk */ built = openssl_bn_cat(EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)), - sig->r, sig->s, signature); + r, s, signature); ECDSA_SIG_free(sig); } return built; diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c index 21dcb0120..a1e56fc5e 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c @@ -27,6 +27,10 @@ #include #include +#if OPENSSL_VERSION_NUMBER < 0x10100000L +OPENSSL_KEY_FALLBACK(ECDSA_SIG, r, s) +#endif + typedef struct private_openssl_ec_public_key_t private_openssl_ec_public_key_t; /** @@ -55,14 +59,23 @@ struct private_openssl_ec_public_key_t { static bool verify_signature(private_openssl_ec_public_key_t *this, chunk_t hash, chunk_t signature) { - bool valid = FALSE; + BIGNUM *r, *s; ECDSA_SIG *sig; + bool valid = FALSE; sig = ECDSA_SIG_new(); if (sig) { - /* split the signature chunk in r and s */ - if (openssl_bn_split(signature, sig->r, sig->s)) + r = BN_new(); + s = BN_new(); + if (!openssl_bn_split(signature, r, s)) + { + BN_free(r); + BN_free(s); + ECDSA_SIG_free(sig); + return FALSE; + } + if (ECDSA_SIG_set0(sig, r, s)) { valid = (ECDSA_do_verify(hash.ptr, hash.len, sig, this->ec) == 1); } From 08d7e1f190834dd1d9e030c6a542d5a1aa9bcf0b Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 15:49:19 +0200 Subject: [PATCH 10/18] openssl: Update x509 API to OpenSSL 1.1.0 --- .../plugins/openssl/openssl_x509.c | 60 +++++++++++++++---- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c index 7a5b206dd..e95eb729b 100644 --- a/src/libstrongswan/plugins/openssl/openssl_x509.c +++ b/src/libstrongswan/plugins/openssl/openssl_x509.c @@ -60,6 +60,25 @@ #define OPENSSL_NO_RFC3779 #endif +/* added with 1.0.2 */ +#if OPENSSL_VERSION_NUMBER < 0x10002000L +static inline void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, const X509 *x) { + if (psig) { *psig = x->signature; } + if (palg) { *palg = x->sig_alg; } +} +#endif + +/* added with 1.1.0 when X509 etc. was made opaque */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define X509_get0_extensions(x509) ({ (x509)->cert_info->extensions; }) +#define X509_get0_tbs_sigalg(x509) ({ (x509)->cert_info->signature; }) +#define X509_ALGOR_get0(oid, ppt, ppv, alg) ({ *(oid) = (alg)->algorithm; }) +#define X509_PUBKEY_get0_param(oid, pk, len, pa, pub) X509_ALGOR_get0(oid, NULL, NULL, (pub)->algor) +#define X509v3_addr_get_afi v3_addr_get_afi +#define X509v3_addr_get_range v3_addr_get_range +#define X509v3_addr_is_canonical v3_addr_is_canonical +#endif + typedef struct private_openssl_x509_t private_openssl_x509_t; /** @@ -380,6 +399,7 @@ METHOD(certificate_t, issued_by, bool, public_key_t *key; bool valid; x509_t *x509 = (x509_t*)issuer; + ASN1_BIT_STRING *sig; chunk_t tbs; if (&this->public.x509.interface == issuer) @@ -413,9 +433,14 @@ METHOD(certificate_t, issued_by, bool, { return FALSE; } + /* i2d_re_X509_tbs() was added with 1.1.0 when X509 was made opaque */ +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + tbs = openssl_i2chunk(re_X509_tbs, this->x509); +#else tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info); - valid = key->verify(key, this->scheme, tbs, - openssl_asn1_str2chunk(this->x509->signature)); +#endif + X509_get0_signature(&sig, NULL, this->x509); + valid = key->verify(key, this->scheme, tbs, openssl_asn1_str2chunk(sig)); free(tbs.ptr); key->destroy(key); if (valid && scheme) @@ -850,7 +875,7 @@ static void parse_ipAddrBlock_ext_fam(private_openssl_x509_t *this, return; } - afi = v3_addr_get_afi(fam); + afi = X509v3_addr_get_afi(fam); switch (afi) { case IANA_AFI_IPV4: @@ -871,7 +896,7 @@ static void parse_ipAddrBlock_ext_fam(private_openssl_x509_t *this, for (i = 0; i < sk_IPAddressOrRange_num(list); i++) { aor = sk_IPAddressOrRange_value(list, i); - if (v3_addr_get_range(aor, afi, from.ptr, to.ptr, from.len) > 0) + if (X509v3_addr_get_range(aor, afi, from.ptr, to.ptr, from.len) > 0) { ts = traffic_selector_create_from_bytes(0, type, from, 0, to, 65535); if (ts) @@ -897,7 +922,7 @@ static bool parse_ipAddrBlock_ext(private_openssl_x509_t *this, return FALSE; } - if (!v3_addr_is_canonical(blocks)) + if (!X509v3_addr_is_canonical(blocks)) { sk_IPAddressFamily_free(blocks); return FALSE; @@ -964,7 +989,7 @@ static bool parse_extensions(private_openssl_x509_t *this) STACK_OF(X509_EXTENSION) *extensions; int i, num; - extensions = this->x509->cert_info->extensions; + extensions = X509_get0_extensions(this->x509); if (extensions) { num = sk_X509_EXTENSION_num(extensions); @@ -1041,6 +1066,8 @@ static bool parse_certificate(private_openssl_x509_t *this) const unsigned char *ptr = this->encoding.ptr; hasher_t *hasher; chunk_t chunk; + ASN1_OBJECT *oid, *oid_tbs; + X509_ALGOR *alg; this->x509 = d2i_X509(NULL, &ptr, this->encoding.len); if (!this->x509) @@ -1057,7 +1084,12 @@ static bool parse_certificate(private_openssl_x509_t *this) this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509)); this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509)); - switch (openssl_asn1_known_oid(this->x509->cert_info->key->algor->algorithm)) + if (!X509_PUBKEY_get0_param(&oid, NULL, NULL, NULL, + X509_get_X509_PUBKEY(this->x509))) + { + return FALSE; + } + switch (openssl_asn1_known_oid(oid)) { case OID_RSA_ENCRYPTION: this->pubkey = lib->creds->create(lib->creds, @@ -1086,14 +1118,18 @@ static bool parse_certificate(private_openssl_x509_t *this) this->notBefore = openssl_asn1_to_time(X509_get_notBefore(this->x509)); this->notAfter = openssl_asn1_to_time(X509_get_notAfter(this->x509)); - if (!chunk_equals( - openssl_asn1_obj2chunk(this->x509->cert_info->signature->algorithm), - openssl_asn1_obj2chunk(this->x509->sig_alg->algorithm))) + /* while X509_ALGOR_cmp() is declared in the headers of older OpenSSL + * versions, at least on Ubuntu 14.04 it is not actually defined */ + X509_get0_signature(NULL, &alg, this->x509); + X509_ALGOR_get0(&oid, NULL, NULL, alg); + alg = X509_get0_tbs_sigalg(this->x509); + X509_ALGOR_get0(&oid_tbs, NULL, NULL, alg); + if (!chunk_equals(openssl_asn1_obj2chunk(oid), + openssl_asn1_obj2chunk(oid_tbs))) { return FALSE; } - this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid( - this->x509->sig_alg->algorithm)); + this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(oid)); if (!parse_extensions(this)) { From 989ba4b6cd16cf724c07434f5cbb5c3db4000d93 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 16:56:22 +0200 Subject: [PATCH 11/18] openssl: Update CRL API to OpenSSL 1.1.0 There is currently no way to compare the outer and inner algorithms encoded in a parsed CRL. X509_CRL_verify() does not seem to check that either, though (unlike X509_verify()). --- .../plugins/openssl/openssl_crl.c | 49 ++++++++++++++++--- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.c b/src/libstrongswan/plugins/openssl/openssl_crl.c index cb02c663c..20bac6be5 100644 --- a/src/libstrongswan/plugins/openssl/openssl_crl.c +++ b/src/libstrongswan/plugins/openssl/openssl_crl.c @@ -46,6 +46,17 @@ #include #include +#if OPENSSL_VERSION_NUMBER < 0x10100000L +static inline void X509_CRL_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, const X509_CRL *crl) { + if (psig) { *psig = crl->signature; } + if (palg) { *palg = crl->sig_alg; } +} +#define X509_REVOKED_get0_serialNumber(r) ({ (r)->serialNumber; }) +#define X509_REVOKED_get0_revocationDate(r) ({ (r)->revocationDate; }) +#define X509_CRL_get0_extensions(c) ({ (c)->crl->extensions; }) +#define X509_ALGOR_get0(oid, ppt, ppv, alg) ({ *(oid) = (alg)->algorithm; }) +#endif + typedef struct private_openssl_crl_t private_openssl_crl_t; /** @@ -141,11 +152,13 @@ METHOD(enumerator_t, crl_enumerate, bool, revoked = sk_X509_REVOKED_value(this->stack, this->i); if (serial) { - *serial = openssl_asn1_str2chunk(revoked->serialNumber); + *serial = openssl_asn1_str2chunk( + X509_REVOKED_get0_serialNumber(revoked)); } if (date) { - *date = openssl_asn1_to_time(revoked->revocationDate); + *date = openssl_asn1_to_time( + X509_REVOKED_get0_revocationDate(revoked)); } if (reason) { @@ -231,6 +244,7 @@ METHOD(certificate_t, issued_by, bool, chunk_t fingerprint, tbs; public_key_t *key; x509_t *x509; + ASN1_BIT_STRING *sig; bool valid; if (issuer->get_type(issuer) != CERT_X509) @@ -266,9 +280,14 @@ METHOD(certificate_t, issued_by, bool, { return FALSE; } + /* i2d_re_X509_CRL_tbs() was added with 1.1.0 when X509_CRL became opaque */ +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + tbs = openssl_i2chunk(re_X509_CRL_tbs, this->crl); +#else tbs = openssl_i2chunk(X509_CRL_INFO, this->crl->crl); - valid = key->verify(key, this->scheme, tbs, - openssl_asn1_str2chunk(this->crl->signature)); +#endif + X509_CRL_get0_signature(&sig, NULL, this->crl); + valid = key->verify(key, this->scheme, tbs, openssl_asn1_str2chunk(sig)); free(tbs.ptr); key->destroy(key); if (valid && scheme) @@ -448,7 +467,7 @@ static bool parse_extensions(private_openssl_crl_t *this) X509_EXTENSION *ext; STACK_OF(X509_EXTENSION) *extensions; - extensions = this->crl->crl->extensions; + extensions = X509_CRL_get0_extensions(this->crl); if (extensions) { num = sk_X509_EXTENSION_num(extensions); @@ -494,6 +513,8 @@ static bool parse_extensions(private_openssl_crl_t *this) static bool parse_crl(private_openssl_crl_t *this) { const unsigned char *ptr = this->encoding.ptr; + ASN1_OBJECT *oid; + X509_ALGOR *alg; this->crl = d2i_X509_CRL(NULL, &ptr, this->encoding.len); if (!this->crl) @@ -501,14 +522,28 @@ static bool parse_crl(private_openssl_crl_t *this) return FALSE; } + X509_CRL_get0_signature(NULL, &alg, this->crl); + X509_ALGOR_get0(&oid, NULL, NULL, alg); +#if OPENSSL_VERSION_NUMBER < 0x10100000L if (!chunk_equals( openssl_asn1_obj2chunk(this->crl->crl->sig_alg->algorithm), openssl_asn1_obj2chunk(this->crl->sig_alg->algorithm))) { return FALSE; } - this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid( - this->crl->sig_alg->algorithm)); +#elif 0 + /* FIXME: we currently can't do this if X509_CRL is opaque (>= 1.1.0) as + * X509_CRL_get0_tbs_sigalg() does not exist and there does not seem to be + * another easy way to get the algorithm from the tbsCertList of the CRL */ + alg = X509_CRL_get0_tbs_sigalg(this->crl); + X509_ALGOR_get0(&oid_tbs, NULL, NULL, alg); + if (!chunk_equals(openssl_asn1_obj2chunk(oid), + openssl_asn1_obj2chunk(oid_tbs))) + { + return FALSE; + } +#endif + this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(oid)); this->issuer = openssl_x509_name2id(X509_CRL_get_issuer(this->crl)); if (!this->issuer) From a9f388e368f5db4c910c57a30ec16170b9ade3c8 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 17:22:34 +0200 Subject: [PATCH 12/18] openssl: Update PKCS#7 API to OpenSSL 1.1.0 --- src/libstrongswan/plugins/openssl/openssl_pkcs7.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c index 891e829ae..f10987c8d 100644 --- a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c +++ b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c @@ -29,6 +29,10 @@ #include +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define X509_ATTRIBUTE_get0_object(attr) ({ (attr)->object; }) +#endif + typedef struct private_openssl_pkcs7_t private_openssl_pkcs7_t; /** @@ -432,11 +436,11 @@ METHOD(pkcs7_t, get_attribute, bool, for (i = 0; i < CMS_signed_get_attr_count(si); i++) { attr = CMS_signed_get_attr(si, i); - if (!attr->single && sk_ASN1_TYPE_num(attr->value.set) == 1 && - openssl_asn1_known_oid(attr->object) == oid) + if (X509_ATTRIBUTE_count(attr) == 1 && + openssl_asn1_known_oid(X509_ATTRIBUTE_get0_object(attr)) == oid) { /* get first value in SET */ - type = sk_ASN1_TYPE_value(attr->value.set, 0); + type = X509_ATTRIBUTE_get0_type(attr, 0); chunk = wrapped = openssl_i2chunk(ASN1_TYPE, type); if (asn1_unwrap(&chunk, &chunk) != 0x100 /* ASN1_INVALID */) { From 985d7b1c67213400a7c9ca389caaab0a09f80eb5 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 17:26:16 +0200 Subject: [PATCH 13/18] openssl: Update PKCS#12 API to OpenSSL 1.1.0 --- src/libstrongswan/plugins/openssl/openssl_pkcs12.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs12.c b/src/libstrongswan/plugins/openssl/openssl_pkcs12.c index d16b2cc05..705e96c69 100644 --- a/src/libstrongswan/plugins/openssl/openssl_pkcs12.c +++ b/src/libstrongswan/plugins/openssl/openssl_pkcs12.c @@ -23,6 +23,10 @@ #include #include +#ifdef OPENSSL_IS_BORINGSSL +#define EVP_PKEY_base_id(p) EVP_PKEY_type(p->type) +#endif + typedef struct private_pkcs12_t private_pkcs12_t; /** @@ -110,7 +114,7 @@ static bool add_key(private_pkcs12_t *this, EVP_PKEY *private) { /* no private key is ok */ return TRUE; } - switch (EVP_PKEY_type(private->type)) + switch (EVP_PKEY_base_id(private)) { case EVP_PKEY_RSA: type = KEY_RSA; From cd08eb84cbb30c03792ae15560fd52044aa8fd56 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 17:27:54 +0200 Subject: [PATCH 14/18] openssl: Don't use deprecated RAND_pseudo_bytes() --- src/libstrongswan/plugins/openssl/openssl_rng.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_rng.c b/src/libstrongswan/plugins/openssl/openssl_rng.c index f8e98fc0f..a25b6b4b6 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rng.c +++ b/src/libstrongswan/plugins/openssl/openssl_rng.c @@ -49,13 +49,6 @@ struct private_openssl_rng_t { METHOD(rng_t, get_bytes, bool, private_openssl_rng_t *this, size_t bytes, uint8_t *buffer) { - if (this->quality == RNG_WEAK) - { - /* RAND_pseudo_bytes() returns 1 if returned bytes are strong, - * 0 if of not. Both is acceptable for RNG_WEAK. */ - return RAND_pseudo_bytes((char*)buffer, bytes) != -1; - } - /* A 0 return value is a failure for RAND_bytes() */ return RAND_bytes((char*)buffer, bytes) == 1; } From 97b1a27f434fcc13e5be6d6c9acd7969aafd262f Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 17:31:31 +0200 Subject: [PATCH 15/18] openssl: Update HMAC API to OpenSSL 1.1.0 --- .../plugins/openssl/openssl_hmac.c | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.c b/src/libstrongswan/plugins/openssl/openssl_hmac.c index b99a0c947..16e707116 100644 --- a/src/libstrongswan/plugins/openssl/openssl_hmac.c +++ b/src/libstrongswan/plugins/openssl/openssl_hmac.c @@ -68,7 +68,14 @@ struct private_mac_t { /** * Current HMAC context */ - HMAC_CTX hmac; + HMAC_CTX *hmac; + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + /** + * Static context for OpenSSL < 1.1.0 + */ + HMAC_CTX hmac_ctx; +#endif /** * Key set on HMAC_CTX? @@ -80,14 +87,14 @@ METHOD(mac_t, set_key, bool, private_mac_t *this, chunk_t key) { #if OPENSSL_VERSION_NUMBER >= 0x10000000L - if (HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL)) + if (HMAC_Init_ex(this->hmac, key.ptr, key.len, this->hasher, NULL)) { this->key_set = TRUE; return TRUE; } return FALSE; #else /* OPENSSL_VERSION_NUMBER < 1.0 */ - HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL); + HMAC_Init_ex(this->hmac, key.ptr, key.len, this->hasher, NULL); this->key_set = TRUE; return TRUE; #endif @@ -101,7 +108,7 @@ METHOD(mac_t, get_mac, bool, return FALSE; } #if OPENSSL_VERSION_NUMBER >= 0x10000000L - if (!HMAC_Update(&this->hmac, data.ptr, data.len)) + if (!HMAC_Update(this->hmac, data.ptr, data.len)) { return FALSE; } @@ -109,17 +116,17 @@ METHOD(mac_t, get_mac, bool, { return TRUE; } - if (!HMAC_Final(&this->hmac, out, NULL)) + if (!HMAC_Final(this->hmac, out, NULL)) { return FALSE; } #else /* OPENSSL_VERSION_NUMBER < 1.0 */ - HMAC_Update(&this->hmac, data.ptr, data.len); + HMAC_Update(this->hmac, data.ptr, data.len); if (out == NULL) { return TRUE; } - HMAC_Final(&this->hmac, out, NULL); + HMAC_Final(this->hmac, out, NULL); #endif return set_key(this, chunk_empty); } @@ -133,7 +140,11 @@ METHOD(mac_t, get_mac_size, size_t, METHOD(mac_t, destroy, void, private_mac_t *this) { - HMAC_CTX_cleanup(&this->hmac); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + HMAC_CTX_free(this->hmac); +#else + HMAC_CTX_cleanup(&this->hmac_ctx); +#endif free(this); } @@ -167,7 +178,12 @@ static mac_t *hmac_create(hash_algorithm_t algo) return NULL; } - HMAC_CTX_init(&this->hmac); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + this->hmac = HMAC_CTX_new(); +#else + HMAC_CTX_init(&this->hmac_ctx); + this->hmac = &this->hmac_ctx; +#endif return &this->public; } From fedec33f5a1a3a7a02ddfebc650fb44190faf1bc Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 17:33:58 +0200 Subject: [PATCH 16/18] openssl: Update GCM/crypter API to OpenSSL 1.1.0 --- .../plugins/openssl/openssl_gcm.c | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libstrongswan/plugins/openssl/openssl_gcm.c b/src/libstrongswan/plugins/openssl/openssl_gcm.c index 147e4afb4..6bbe4af95 100644 --- a/src/libstrongswan/plugins/openssl/openssl_gcm.c +++ b/src/libstrongswan/plugins/openssl/openssl_gcm.c @@ -71,7 +71,7 @@ struct private_aead_t { static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv, u_char *out, int enc) { - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; u_char nonce[NONCE_LEN]; bool success = FALSE; int len; @@ -79,29 +79,29 @@ static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv, memcpy(nonce, this->salt, SALT_LEN); memcpy(nonce + SALT_LEN, iv.ptr, IV_LEN); - EVP_CIPHER_CTX_init(&ctx); - EVP_CIPHER_CTX_set_padding(&ctx, 0); - if (!EVP_CipherInit_ex(&ctx, this->cipher, NULL, NULL, NULL, enc) || - !EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, NONCE_LEN, NULL) || - !EVP_CipherInit_ex(&ctx, NULL, NULL, this->key.ptr, nonce, enc)) + ctx = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_set_padding(ctx, 0); + if (!EVP_CipherInit_ex(ctx, this->cipher, NULL, NULL, NULL, enc) || + !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, NONCE_LEN, NULL) || + !EVP_CipherInit_ex(ctx, NULL, NULL, this->key.ptr, nonce, enc)) { goto done; } - if (!enc && !EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, this->icv_size, + if (!enc && !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, this->icv_size, data.ptr + data.len)) { /* set ICV for verification on decryption */ goto done; } - if (assoc.len && !EVP_CipherUpdate(&ctx, NULL, &len, assoc.ptr, assoc.len)) + if (assoc.len && !EVP_CipherUpdate(ctx, NULL, &len, assoc.ptr, assoc.len)) { /* set AAD if specified */ goto done; } - if (!EVP_CipherUpdate(&ctx, out, &len, data.ptr, data.len) || - !EVP_CipherFinal_ex(&ctx, out + len, &len)) + if (!EVP_CipherUpdate(ctx, out, &len, data.ptr, data.len) || + !EVP_CipherFinal_ex(ctx, out + len, &len)) { /* EVP_CipherFinal_ex fails if ICV is incorrect on decryption */ goto done; } - if (enc && !EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, this->icv_size, + if (enc && !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, this->icv_size, out + data.len)) { /* copy back the ICV when encrypting */ goto done; @@ -109,7 +109,7 @@ static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv, success = TRUE; done: - EVP_CIPHER_CTX_cleanup(&ctx); + EVP_CIPHER_CTX_free(ctx); return success; } @@ -152,7 +152,7 @@ METHOD(aead_t, decrypt, bool, METHOD(aead_t, get_block_size, size_t, private_aead_t *this) { - return this->cipher->block_size; + return EVP_CIPHER_block_size(this->cipher); } METHOD(aead_t, get_icv_size, size_t, From c1410cb045169c47c59459673219f2e7d878c22c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 17:44:57 +0200 Subject: [PATCH 17/18] openssl: Whitelist OPENSSL_init_crypto() and others in leak detective Lots of static data is allocated in this function, which isn't freed until the library is unloaded (we can't call OPENSSL_cleanup() as initialization would fail when calling it again later). When enabling the leak detective the test runner eventually crashes as all the data allocated during initialization has an invalid size when freed after leak detective has been unloaded. --- src/libstrongswan/utils/leak_detective.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index a0bdae715..aeadc0cb3 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -564,6 +564,10 @@ char *whitelist[] = { "ECDSA_do_sign_ex", "ECDSA_verify", "RSA_new_method", + /* OpenSSL 1.1.0 does not cleanup anymore until the library is unloaded */ + "OPENSSL_init_crypto", + "CRYPTO_THREAD_lock_new", + "ERR_add_error_data", /* OpenSSL libssl */ "SSL_COMP_get_compression_methods", /* NSPR */ From 505c318701620531f579d074634b1a4607efd684 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 27 Jun 2016 18:04:39 +0200 Subject: [PATCH 18/18] leak-detective: Try to properly free allocations after deinitialization If a function we whitelist allocates memory while leak detective is enabled but only frees it after LD has already been disabled, free() will get called with invalid pointers (not pointing to the actually allocated memory by LD), which will cause checks in the C library to fail and the program to crash. This tries to detect such cases and calling free with the correct pointer. --- src/libstrongswan/utils/leak_detective.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index aeadc0cb3..d0f646c31 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -844,6 +844,18 @@ HOOK(void, free, void *ptr) if (!enabled || thread_disabled->get(thread_disabled)) { + /* after deinitialization we might have to free stuff we allocated + * while we were enabled */ + if (!first_header.magic && ptr) + { + hdr = ptr - sizeof(memory_header_t); + tail = ptr + hdr->bytes; + if (hdr->magic == MEMORY_HEADER_MAGIC && + tail->magic == MEMORY_TAIL_MAGIC) + { + ptr = hdr; + } + } real_free(ptr); return; } @@ -960,6 +972,7 @@ METHOD(leak_detective_t, destroy, void, lock->destroy(lock); thread_disabled->destroy(thread_disabled); free(this); + first_header.magic = 0; first_header.next = NULL; }