Skip to content

Commit

Permalink
lib-ssl-iostream,lib-dcrypt: Raise minimum OpenSSL compatibility leve…
Browse files Browse the repository at this point in the history
…l to 1.1.1

But retain compatibility with LibreSSL.
  • Loading branch information
cmouse committed Nov 27, 2024
1 parent e3bbaad commit b24ed13
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 270 deletions.
60 changes: 17 additions & 43 deletions m4/ssl.m4
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,8 @@ AC_DEFUN([DOVECOT_SSL], [
build_dcrypt_openssl=no
have_openssl=no
dnl libressl pkg pretends to be openssl 1.0.0, so we can't check 1.0.2 here
dnl so we check for 1.0.0 first, then after this check, we check that the
dnl lib we found actually is 1.0.2 or later.
PKG_CHECK_EXISTS([openssl], [
PKG_CHECK_MODULES(SSL, [openssl >= 1.0.0])
PKG_CHECK_MODULES(SSL, [openssl >= 1.1.1])
], [
AC_CHECK_LIB(ssl, SSL_read, [
AC_CHECK_HEADERS(openssl/ssl.h openssl/err.h, [
Expand All @@ -42,18 +38,18 @@ AC_DEFUN([DOVECOT_SSL], [
])
])
AC_MSG_CHECKING([if OpenSSL version is 1.0.2 or better])
AC_MSG_CHECKING([if OpenSSL version is 1.1.1 or better])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER < 0x10002000L
#if OPENSSL_VERSION_NUMBER < 0x10101000L
#error "fail-compile"
#endif]], [[ return 0; ]])],
[ssl_version_ge_102=true], [ssl_version_ge_102=false])
AC_MSG_RESULT([$ssl_version_ge_102])
[ssl_version_ge_111=true], [ssl_version_ge_111=false])
AC_MSG_RESULT([$ssl_version_ge_111])
AS_IF([test $ssl_version_ge_102 != true], [
AC_MSG_ERROR([OpenSSL v1.0.2 or better required to build Dovecot])
AS_IF([test $ssl_version_ge_111 != true], [
AC_MSG_ERROR([OpenSSL v1.1.1 or better required to build Dovecot])
])
AC_MSG_CHECKING([if OpenSSL version is 3.0.0 or better])
Expand Down Expand Up @@ -99,43 +95,21 @@ AC_DEFUN([DOVECOT_SSL], [
AC_DEFINE(HAVE_SSL_NEW_MEM_FUNCS,, [Define if CRYPTO_set_mem_functions has new style parameters])
])
DOVECOT_CHECK_SSL_FUNC([ECDSA_SIG_get0])
DOVECOT_CHECK_SSL_FUNC([ECDSA_SIG_set0])
DOVECOT_CHECK_SSL_FUNC([EC_GROUP_order_bits])
dnl OpenSSl 3.0
DOVECOT_CHECK_SSL_FUNC([ERR_get_error_all])
DOVECOT_CHECK_SSL_FUNC([ERR_get_error_line_data])
DOVECOT_CHECK_SSL_FUNC([ERR_remove_state])
DOVECOT_CHECK_SSL_FUNC([ERR_remove_thread_state])
DOVECOT_CHECK_SSL_FUNC([EVP_MAC_CTX_new])
DOVECOT_CHECK_SSL_FUNC([EVP_MD_CTX_new])
DOVECOT_CHECK_SSL_FUNC([EVP_PKEY_get_raw_private_key])
DOVECOT_CHECK_SSL_FUNC([EVP_PKEY_get0_RSA])
DOVECOT_CHECK_SSL_FUNC([EVP_PKEY_get0_EC_KEY])
DOVECOT_CHECK_SSL_FUNC([EVP_PKEY_get0_DH])
DOVECOT_CHECK_SSL_FUNC([EVP_PKEY_set1_encoded_public_key])
DOVECOT_CHECK_SSL_FUNC([HMAC_CTX_init])
DOVECOT_CHECK_SSL_FUNC([HMAC_CTX_new])
DOVECOT_CHECK_SSL_FUNC([OBJ_cleanup])
DOVECOT_CHECK_SSL_FUNC([OBJ_length])
DOVECOT_CHECK_SSL_FUNC([OPENSSL_cleanup])
DOVECOT_CHECK_SSL_FUNC([OPENSSL_init_ssl])
DOVECOT_CHECK_SSL_FUNC([OPENSSL_thread_stop])
DOVECOT_CHECK_SSL_FUNC([OSSL_PROVIDER_try_load])
DOVECOT_CHECK_SSL_FUNC([PEM_read_bio_Parameters])
DOVECOT_CHECK_SSL_FUNC([RSA_set0_crt_params])
DOVECOT_CHECK_SSL_FUNC([RSA_set0_factors])
DOVECOT_CHECK_SSL_FUNC([RSA_set0_key])
DOVECOT_CHECK_SSL_FUNC([SSL_CIPHER_get_kx_nid])
DOVECOT_CHECK_SSL_FUNC([SSL_clear_options])
DOVECOT_CHECK_SSL_FUNC([SSL_client_hello_get0_ciphers])
DOVECOT_CHECK_SSL_FUNC([SSL_CTX_set0_tmp_dh_pkey])
DOVECOT_CHECK_SSL_FUNC([SSL_CTX_set_ciphersuites])
DOVECOT_CHECK_SSL_FUNC([SSL_CTX_set_ecdh_auto])
DOVECOT_CHECK_SSL_FUNC([SSL_CTX_set_min_proto_version])
DOVECOT_CHECK_SSL_FUNC([SSL_CTX_set_tmp_dh_callback])
DOVECOT_CHECK_SSL_FUNC([SSL_CTX_set_tmp_rsa_callback])
DOVECOT_CHECK_SSL_FUNC([SSL_CTX_set_current_cert])
DOVECOT_CHECK_SSL_FUNC([SSL_CTX_set0_tmp_dh_pkey])
dnl LibreSSL
DOVECOT_CHECK_SSL_FUNC([EVP_PKEY_check])
DOVECOT_CHECK_SSL_FUNC([OPENSSL_buf2hexstr])
DOVECOT_CHECK_SSL_FUNC([SSL_get1_peer_certificate])
DOVECOT_CHECK_SSL_FUNC([SSL_load_error_strings])
DOVECOT_CHECK_SSL_FUNC([SSL_CTX_set_client_hello_cb])
DOVECOT_CHECK_SSL_FUNC([SSL_CTX_select_current_cert])
DOVECOT_CHECK_SSL_FUNC([SSL_client_hello_get0_ciphers])
CFLAGS="$old_CFLAGS"
])
140 changes: 23 additions & 117 deletions src/lib-dcrypt/dcrypt-openssl1.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,32 +75,8 @@
2<tab>key algo oid<tab>1<tab>symmetric algo name<tab>salt<tab>hash algo<tab>rounds<tab>E(RSA = i2d_PrivateKey, EC=Private Point)<tab>key id
**/

#ifndef HAVE_EVP_PKEY_get0_EC_KEY
# define EVP_PKEY_get0_EC_KEY(x) x->pkey.ec
#endif
#ifndef HAVE_EVP_PKEY_get0_RSA
# define EVP_PKEY_get0_RSA(x) x->pkey.rsa
#endif

#ifndef HAVE_OBJ_length
# define OBJ_length(o) ((o)->length)
#endif

#ifndef HAVE_EVP_MD_CTX_new
# define EVP_MD_CTX_new() EVP_MD_CTX_create()
# define EVP_MD_CTX_free(ctx) EVP_MD_CTX_destroy(ctx)
#endif

#ifndef HAVE_HMAC_CTX_new
# define HMAC_Init_ex(ctx, key, key_len, md, impl) \
HMAC_Init_ex(&(ctx), key, key_len, md, impl)
# define HMAC_Update(ctx, data, len) HMAC_Update(&(ctx), data, len)
# define HMAC_Final(ctx, md, len) HMAC_Final(&(ctx), md, len)
# define HMAC_CTX_free(ctx) HMAC_cleanup(&(ctx))
#else
# define HMAC_CTX_free(ctx) \
#define HMAC_CTX_free(ctx) \
STMT_START { HMAC_CTX_free(ctx); (ctx) = NULL; } STMT_END
#endif

/* Not always present */
#ifndef HAVE_BN_secure_new
Expand All @@ -120,7 +96,15 @@
ERR_get_error_line_data(NULL, NULL, data, flags)
#endif

#if defined(HAVE_EVP_PKEY_get_raw_private_key) && defined(NID_X25519)
#if !defined(NID_ED448) && defined(NID_Ed448)
# define NID_ED448 NID_Ed448
#endif

#if !defined(NID_ED25519) && defined(NID_Ed25519)
# define NID_ED25519 NID_Ed25519
#endif

#if defined(NID_X25519)
# define HAVE_X25519
# define IS_XD_CURVE(nid) \
((nid) == NID_X25519 || (nid) == NID_X448)
Expand All @@ -133,6 +117,17 @@
static ASN1_OBJECT *CHACHA20_POLY1305_OBJ = NULL;
#endif

#ifndef HAVE_OPENSSL_buf2hexstr
static char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len)
{
char *dest = OPENSSL_malloc(len*2 + 1);
buffer_t buf;
buffer_create_from_data(&buf, dest, len*2 + 1);
binary_to_hex_append(&buf, buffer, len);
return str_c_modifiable(&buf);
}
#endif

struct dcrypt_context_symmetric {
pool_t pool;
const EVP_CIPHER *cipher;
Expand All @@ -150,11 +145,7 @@ struct dcrypt_context_symmetric {
struct dcrypt_context_hmac {
pool_t pool;
const EVP_MD *md;
#ifdef HAVE_HMAC_CTX_new
HMAC_CTX *ctx;
#else
HMAC_CTX ctx;
#endif
unsigned char *key;
size_t klen;
};
Expand Down Expand Up @@ -207,18 +198,6 @@ dcrypt_openssl_key_string_get_info(const char *key_data,
const char **encryption_key_hash_r, const char **key_hash_r,
const char **error_r);

#ifndef HAVE_EC_GROUP_order_bits
static int EC_GROUP_order_bits(const EC_GROUP *grp)
{
int bits;
BIGNUM *bn = BN_new();
(void)EC_GROUP_get_order(grp, bn, NULL);
bits = BN_num_bits(bn);
BN_free(bn);
return bits;
}
#endif

static const char *ssl_err2str(unsigned long err, const char *data, int flags)
{
const char *ret;
Expand Down Expand Up @@ -685,11 +664,9 @@ dcrypt_openssl_ctx_hmac_init(struct dcrypt_context_hmac *ctx,

i_assert(ctx->ctx == NULL);
i_assert(ctx->md != NULL);
#ifdef HAVE_HMAC_CTX_new
ctx->ctx = HMAC_CTX_new();
if (ctx->ctx == NULL)
return dcrypt_openssl_error(error_r);
#endif
ec = HMAC_Init_ex(ctx->ctx, ctx->key, ctx->klen, ctx->md, NULL);
if (ec != 1) {
HMAC_CTX_free(ctx->ctx);
Expand Down Expand Up @@ -1773,54 +1750,6 @@ static bool load_jwk_curve_key(EVP_PKEY **key_r, bool want_private_key,
#endif
}

/* RSA helpers */
#if !defined(HAVE_RSA_set0_key)
static int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
{
if (n == NULL || e == NULL) {
RSAerr(0, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
BN_free(r->n);
r->n = n;
BN_free(r->e);
r->e = e;
BN_free(r->d);
r->d = d;
return 1;
}
#endif
#if !defined(HAVE_RSA_set0_factors)
static int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
{
if (p == NULL || q == NULL) {
RSAerr(0, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
BN_free(r->p);
r->p = p;
BN_free(r->q);
r->q = q;
return 1;
}
#endif
#if !defined(HAVE_RSA_set0_crt_params)
static int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
{
if (dmp1 == NULL || dmq1 == NULL || iqmp == NULL) {
RSAerr(0, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
BN_free(r->dmp1);
r->dmp1 = dmp1;
BN_free(r->dmq1);
r->dmq1 = dmq1;
BN_free(r->iqmp);
r->iqmp = iqmp;
return 1;
}
#endif

/* This function calculates missing parameters. The only required values
* are e, n, d. If p_r and q_r are provided, they can be used directly
* instead of deriving them. */
Expand Down Expand Up @@ -2220,6 +2149,7 @@ dcrypt_openssl_load_private_key_jwk(struct dcrypt_private_key **key_r,

i_assert(ret || error != NULL);

#ifdef HAVE_EVP_PKEY_check
if (ret) {
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey, NULL);
int ec = EVP_PKEY_check(pctx);
Expand All @@ -2232,6 +2162,7 @@ dcrypt_openssl_load_private_key_jwk(struct dcrypt_private_key **key_r,
EVP_PKEY_free(pkey);
}
}
#endif

if (!ret)
*error_r = t_strdup_printf("Cannot load JWK private key: %s", error);
Expand Down Expand Up @@ -3762,31 +3693,6 @@ dcrypt_openssl_digest(const char *algorithm, const void *data, size_t data_len,
return ret;
}

#ifndef HAVE_ECDSA_SIG_get0
static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
i_assert(sig != NULL);
*pr = sig->r;
*ps = sig->s;
}
#endif
#ifndef HAVE_ECDSA_SIG_set0
static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
{
if (sig == NULL || r == NULL || s == NULL) {
ECDSAerr(0, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}

BN_free(sig->r);
sig->r = r;
BN_free(sig->s);
sig->s = s;

return 1;
}
#endif

static bool
dcrypt_openssl_sign_ecdsa(struct dcrypt_private_key *key, const char *algorithm,
const void *data, size_t data_len, buffer_t *signature_r,
Expand Down
2 changes: 1 addition & 1 deletion src/lib-dcrypt/test-crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include <stdio.h>
#include <openssl/evp.h>

#if defined(HAVE_EVP_PKEY_get_raw_private_key) && defined(NID_X25519)
#if defined(NID_X25519)
# define HAVE_X25519
#endif

Expand Down
2 changes: 1 addition & 1 deletion src/lib-dcrypt/test-stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include <stdio.h>
#include <openssl/evp.h>

#if defined(HAVE_EVP_PKEY_get_raw_private_key) && defined(NID_X25519)
#if defined(NID_X25519)
# define HAVE_X25519
#endif

Expand Down
28 changes: 0 additions & 28 deletions src/lib-ssl-iostream/dovecot-openssl-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,7 @@ void dovecot_openssl_common_global_ref(void)
/*i_warning("CRYPTO_set_mem_functions() was called too late");*/
}

#ifdef HAVE_OPENSSL_init_ssl
OPENSSL_init_ssl(0, NULL);
#else
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
#endif
}

bool dovecot_openssl_common_global_unref(void)
Expand All @@ -103,29 +97,7 @@ bool dovecot_openssl_common_global_unref(void)
#endif
dovecot_openssl_engine = NULL;
}
#ifdef HAVE_OPENSSL_cleanup
OPENSSL_cleanup();
#else
/* OBJ_cleanup() is called automatically by EVP_cleanup() in
newer versions. Doesn't hurt to call it anyway. */
OBJ_cleanup();
# if !defined(OPENSSL_NO_COMP)
SSL_COMP_free_compression_methods();
# endif
ENGINE_cleanup();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
# ifdef HAVE_OPENSSL_thread_stop
/* no cleanup needed */
# elif defined(HAVE_ERR_remove_thread_state)
/* This was marked as deprecated in v1.1. */
ERR_remove_thread_state(NULL);
# elif defined(HAVE_ERR_remove_state)
/* This was deprecated by ERR_remove_thread_state(NULL) in v1.0.0. */
ERR_remove_state(0);
# endif
ERR_free_strings();
#endif
return FALSE;
}

Expand Down
Loading

0 comments on commit b24ed13

Please sign in to comment.