diff options
Diffstat (limited to 'src/libstrongswan/plugins/openssl')
19 files changed, 405 insertions, 135 deletions
diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in index 302016937..f453f43b5 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.in +++ b/src/libstrongswan/plugins/openssl/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -15,7 +15,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -79,8 +89,6 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src/libstrongswan/plugins/openssl -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/m4/config/ltoptions.m4 \ @@ -94,6 +102,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -210,12 +219,14 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ +ATOMICLIB = @ATOMICLIB@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ @@ -265,6 +276,7 @@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ @@ -299,6 +311,7 @@ PTHREADLIB = @PTHREADLIB@ PYTHON = @PYTHON@ PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PACKAGE_VERSION = @PYTHON_PACKAGE_VERSION@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ @@ -410,6 +423,7 @@ random_device = @random_device@ resolv_conf = @resolv_conf@ routing_table = @routing_table@ routing_table_prio = @routing_table_prio@ +runstatedir = @runstatedir@ s_plugins = @s_plugins@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ @@ -485,7 +499,6 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libstrongswan/plugins/openssl/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/libstrongswan/plugins/openssl/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -815,6 +828,8 @@ uninstall-am: uninstall-pluginLTLIBRARIES mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-pluginLTLIBRARIES +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. 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 <collections/enumerator.h> #include <credentials/certificates/x509.h> +#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) diff --git a/src/libstrongswan/plugins/openssl/openssl_crypter.c b/src/libstrongswan/plugins/openssl/openssl_crypter.c index 26f4700b8..b9085f9aa 100644 --- a/src/libstrongswan/plugins/openssl/openssl_crypter.c +++ b/src/libstrongswan/plugins/openssl/openssl_crypter.c @@ -43,7 +43,7 @@ struct private_openssl_crypter_t { /** * Look up an OpenSSL algorithm name and validate its key size */ -static char* lookup_algorithm(u_int16_t ikev2_algo, size_t *key_size) +static char* lookup_algorithm(uint16_t ikev2_algo, size_t *key_size) { struct { /* identifier specified in IKEv2 */ @@ -57,12 +57,12 @@ static char* lookup_algorithm(u_int16_t ikev2_algo, size_t *key_size) /* maximum key size */ size_t key_max; } mappings[] = { - {ENCR_DES, "des", 8, 8, 8}, - {ENCR_3DES, "des3", 24, 24, 24}, - {ENCR_RC5, "rc5", 16, 5, 255}, - {ENCR_IDEA, "idea", 16, 16, 16}, - {ENCR_CAST, "cast", 16, 5, 16}, - {ENCR_BLOWFISH, "blowfish", 16, 5, 56}, + {ENCR_DES, "des-cbc", 8, 8, 8}, + {ENCR_3DES, "des-ede3-cbc", 24, 24, 24}, + {ENCR_RC5, "rc5-cbc", 16, 5, 255}, + {ENCR_IDEA, "idea-cbc", 16, 16, 16}, + {ENCR_CAST, "cast5-cbc", 16, 5, 16}, + {ENCR_BLOWFISH, "bf-cbc", 16, 5, 56}, }; int i; @@ -93,8 +93,10 @@ static char* lookup_algorithm(u_int16_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, @@ -193,13 +198,13 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo, key_size = 16; /* FALL */ case 16: /* AES 128 */ - this->cipher = EVP_get_cipherbyname("aes128"); + this->cipher = EVP_get_cipherbyname("aes-128-cbc"); break; case 24: /* AES-192 */ - this->cipher = EVP_get_cipherbyname("aes192"); + this->cipher = EVP_get_cipherbyname("aes-192-cbc"); break; case 32: /* AES-256 */ - this->cipher = EVP_get_cipherbyname("aes256"); + this->cipher = EVP_get_cipherbyname("aes-256-cbc"); break; default: free(this); @@ -213,13 +218,13 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo, key_size = 16; /* FALL */ case 16: /* CAMELLIA 128 */ - this->cipher = EVP_get_cipherbyname("camellia128"); + this->cipher = EVP_get_cipherbyname("camellia-128-cbc"); break; case 24: /* CAMELLIA 192 */ - this->cipher = EVP_get_cipherbyname("camellia192"); + this->cipher = EVP_get_cipherbyname("camellia-192-cbc"); break; case 32: /* CAMELLIA 256 */ - this->cipher = EVP_get_cipherbyname("camellia256"); + this->cipher = EVP_get_cipherbyname("camellia-256-cbc"); break; default: free(this); diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c index 49ec48804..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 <openssl/dh.h> #include "openssl_diffie_hellman.h" +#include "openssl_util.h" #include <utils/debug.h> +/* 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,16 +153,29 @@ 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) { - this->dh->length = params->exp_len * 8; +#ifdef OPENSSL_IS_BORINGSSL + this->dh->priv_length = params->exp_len * 8; +#else + if (!DH_set_length(this->dh, params->exp_len * 8)) + { + return FAILED; + } +#endif } return SUCCESS; } @@ -166,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 = { @@ -194,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 { @@ -213,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; } 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 <openssl/ecdsa.h> #include <openssl/x509.h> +#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 <openssl/ecdsa.h> #include <openssl/x509.h> +#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); } 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, diff --git a/src/libstrongswan/plugins/openssl/openssl_hasher.c b/src/libstrongswan/plugins/openssl/openssl_hasher.c index 50b14698b..96ee230c9 100644 --- a/src/libstrongswan/plugins/openssl/openssl_hasher.c +++ b/src/libstrongswan/plugins/openssl/openssl_hasher.c @@ -43,7 +43,7 @@ struct private_openssl_hasher_t { METHOD(hasher_t, get_hash_size, size_t, private_openssl_hasher_t *this) { - return this->hasher->md_size; + return EVP_MD_size(this->hasher); } METHOD(hasher_t, reset, bool, @@ -53,7 +53,7 @@ METHOD(hasher_t, reset, bool, } METHOD(hasher_t, get_hash, bool, - private_openssl_hasher_t *this, chunk_t chunk, u_int8_t *hash) + private_openssl_hasher_t *this, chunk_t chunk, uint8_t *hash) { if (EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len) != 1) { diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.c b/src/libstrongswan/plugins/openssl/openssl_hmac.c index 065187a8c..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,28 +87,28 @@ 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 } METHOD(mac_t, get_mac, bool, - private_mac_t *this, chunk_t data, u_int8_t *out) + private_mac_t *this, chunk_t data, uint8_t *out) { if (!this->key_set) { 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; } 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 <library.h> #include <credentials/sets/mem_cred.h> +#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; diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c index 891e829ae..5752d96de 100644 --- a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c +++ b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c @@ -29,6 +29,10 @@ #include <openssl/cms.h> +#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 */) { @@ -503,7 +507,7 @@ static bool decrypt_symmetric(private_openssl_pkcs7_t *this, chunk_t key, chunk_t iv; size_t key_size; - /* read encryption algorithm from interal structures; TODO fixup */ + /* read encryption algorithm from internal structures; TODO fixup */ alg = this->cms->envelopedData->encryptedContentInfo-> contentEncryptionAlgorithm; encr = encryption_algorithm_from_oid(openssl_asn1_known_oid(alg->algorithm), diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index aeb9be409..3e3b986df 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -66,6 +66,11 @@ struct private_openssl_plugin_t { }; /** + * OpenSSL is thread-safe since 1.1.0 + */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +/** * Array of static mutexs, with CRYPTO_num_locks() mutex */ static mutex_t **mutex = NULL; @@ -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 */ @@ -502,8 +515,14 @@ 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(); +#endif EVP_cleanup(); #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); @@ -511,6 +530,7 @@ METHOD(plugin_t, destroy, void, CRYPTO_cleanup_all_ex_data(); threading_cleanup(); ERR_free_strings(); +#endif /* OPENSSL_VERSION_NUMBER */ free(this); } @@ -553,10 +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 */ @@ -565,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"); diff --git a/src/libstrongswan/plugins/openssl/openssl_rng.c b/src/libstrongswan/plugins/openssl/openssl_rng.c index c807bb607..a25b6b4b6 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rng.c +++ b/src/libstrongswan/plugins/openssl/openssl_rng.c @@ -47,15 +47,8 @@ struct private_openssl_rng_t { }; METHOD(rng_t, get_bytes, bool, - private_openssl_rng_t *this, size_t bytes, u_int8_t *buffer) + 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; } 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 <utils/debug.h> @@ -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 <openssl/rsa.h> #include <openssl/x509.h> +#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; diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c index 446c93e2b..f6df03f12 100644 --- a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c +++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c @@ -40,7 +40,7 @@ struct private_openssl_sha1_prf_t { }; METHOD(prf_t, get_bytes, bool, - private_openssl_sha1_prf_t *this, chunk_t seed, u_int8_t *bytes) + private_openssl_sha1_prf_t *this, chunk_t seed, uint8_t *bytes) { #if OPENSSL_VERSION_NUMBER >= 0x10000000L if (!SHA1_Update(&this->ctx, seed.ptr, seed.len)) @@ -53,7 +53,7 @@ METHOD(prf_t, get_bytes, bool, if (bytes) { - u_int32_t *hash = (u_int32_t*)bytes; + uint32_t *hash = (uint32_t*)bytes; hash[0] = htonl(this->ctx.h0); hash[1] = htonl(this->ctx.h1); diff --git a/src/libstrongswan/plugins/openssl/openssl_util.c b/src/libstrongswan/plugins/openssl/openssl_util.c index 2f9813701..6580e1c7d 100644 --- a/src/libstrongswan/plugins/openssl/openssl_util.c +++ b/src/libstrongswan/plugins/openssl/openssl_util.c @@ -22,6 +22,12 @@ #include <openssl/evp.h> #include <openssl/x509.h> +/* 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. */ @@ -51,7 +57,7 @@ bool openssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash) goto error; } - *hash = chunk_alloc(hasher->md_size); + *hash = chunk_alloc(EVP_MD_size(hasher)); if (!EVP_DigestFinal_ex(ctx, hash->ptr, NULL)) { chunk_free(hash); @@ -70,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; @@ -127,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) @@ -149,7 +156,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; } diff --git a/src/libstrongswan/plugins/openssl/openssl_util.h b/src/libstrongswan/plugins/openssl/openssl_util.h index 2db073139..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 @@ -134,4 +135,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_ @}*/ 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)) { |