Added support for Perfect Forward Secrecy (#331)
* Support for PFS is enabled with help of chiper suits that use ECDHE key exchange. OpenSSL added support for eliptic curve operations (EC) in version 0.9.8. Note that there are also some library distributions which don't support EC operations. * Added precompiler guards for builds with OpenSSL older than 0.9.8 and builds with '--enable-runtime-loading' configure script option. * Cleaned up some SSL related code.
This commit is contained in:
parent
477818e088
commit
f0437832d3
2 changed files with 73 additions and 20 deletions
|
@ -102,15 +102,18 @@ BIO * (*BIO_new)(BIO_METHOD *);
|
||||||
BIO * (*BIO_new_socket)(int, int);
|
BIO * (*BIO_new_socket)(int, int);
|
||||||
BIO * (*BIO_pop)(BIO *);
|
BIO * (*BIO_pop)(BIO *);
|
||||||
BIO * (*BIO_push)(BIO *, BIO *);
|
BIO * (*BIO_push)(BIO *, BIO *);
|
||||||
|
#if defined(HAVE_OPENSSL_EC)
|
||||||
|
void (*EC_KEY_free)(EC_KEY *);
|
||||||
|
EC_KEY * (*EC_KEY_new_by_curve_name)(int);
|
||||||
|
#endif
|
||||||
void (*ERR_clear_error)(void);
|
void (*ERR_clear_error)(void);
|
||||||
void (*ERR_clear_error)(void);
|
|
||||||
unsigned long (*ERR_peek_error)(void);
|
|
||||||
unsigned long (*ERR_peek_error)(void);
|
unsigned long (*ERR_peek_error)(void);
|
||||||
long (*SSL_CTX_callback_ctrl)(SSL_CTX *, int, void (*)(void));
|
long (*SSL_CTX_callback_ctrl)(SSL_CTX *, int, void (*)(void));
|
||||||
int (*SSL_CTX_check_private_key)(const SSL_CTX *);
|
int (*SSL_CTX_check_private_key)(const SSL_CTX *);
|
||||||
long (*SSL_CTX_ctrl)(SSL_CTX *, int, long, void *);
|
long (*SSL_CTX_ctrl)(SSL_CTX *, int, long, void *);
|
||||||
void (*SSL_CTX_free)(SSL_CTX *);
|
void (*SSL_CTX_free)(SSL_CTX *);
|
||||||
SSL_CTX * (*SSL_CTX_new)(SSL_METHOD *);
|
SSL_CTX * (*SSL_CTX_new)(SSL_METHOD *);
|
||||||
|
int (*SSL_CTX_set_cipher_list)(SSL_CTX *ctx, const char *str);
|
||||||
int (*SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int);
|
int (*SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int);
|
||||||
int (*SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *,
|
int (*SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *,
|
||||||
const unsigned char *, long);
|
const unsigned char *, long);
|
||||||
|
@ -136,7 +139,6 @@ int (*SSL_write)(SSL *, const void *, int);
|
||||||
SSL_METHOD * (*SSLv23_server_method)(void);
|
SSL_METHOD * (*SSLv23_server_method)(void);
|
||||||
X509 * (*d2i_X509)(X509 **px, const unsigned char **in, int len);
|
X509 * (*d2i_X509)(X509 **px, const unsigned char **in, int len);
|
||||||
void (*X509_free)(X509 *a);
|
void (*X509_free)(X509 *a);
|
||||||
int (*x_SSL_CTX_set_cipher_list)(SSL_CTX *ctx, const char *str);
|
|
||||||
void (*x_sk_zero)(void *st);
|
void (*x_sk_zero)(void *st);
|
||||||
void * (*x_SSL_COMP_get_compression_methods)(void);
|
void * (*x_SSL_COMP_get_compression_methods)(void);
|
||||||
#endif
|
#endif
|
||||||
|
@ -280,11 +282,16 @@ static void loadSSL(void) {
|
||||||
{ { &ERR_clear_error }, "ERR_clear_error" },
|
{ { &ERR_clear_error }, "ERR_clear_error" },
|
||||||
{ { &ERR_peek_error }, "ERR_peek_error" },
|
{ { &ERR_peek_error }, "ERR_peek_error" },
|
||||||
{ { &ERR_peek_error }, "ERR_peek_error" },
|
{ { &ERR_peek_error }, "ERR_peek_error" },
|
||||||
|
#ifdef HAVE_OPENSSL_EC
|
||||||
|
{ { &EC_KEY_free }, "EC_KEY_free" },
|
||||||
|
{ { &EC_KEY_new_by_curve_name }, "EC_KEY_new_by_curve_name" },
|
||||||
|
#endif
|
||||||
{ { &SSL_CTX_callback_ctrl }, "SSL_CTX_callback_ctrl" },
|
{ { &SSL_CTX_callback_ctrl }, "SSL_CTX_callback_ctrl" },
|
||||||
{ { &SSL_CTX_check_private_key }, "SSL_CTX_check_private_key" },
|
{ { &SSL_CTX_check_private_key }, "SSL_CTX_check_private_key" },
|
||||||
{ { &SSL_CTX_ctrl }, "SSL_CTX_ctrl" },
|
{ { &SSL_CTX_ctrl }, "SSL_CTX_ctrl" },
|
||||||
{ { &SSL_CTX_free }, "SSL_CTX_free" },
|
{ { &SSL_CTX_free }, "SSL_CTX_free" },
|
||||||
{ { &SSL_CTX_new }, "SSL_CTX_new" },
|
{ { &SSL_CTX_new }, "SSL_CTX_new" },
|
||||||
|
{ { &SSL_CTX_set_cipher_list }, "SSL_CTX_set_cipher_list" },
|
||||||
{ { &SSL_CTX_use_PrivateKey_file }, "SSL_CTX_use_PrivateKey_file" },
|
{ { &SSL_CTX_use_PrivateKey_file }, "SSL_CTX_use_PrivateKey_file" },
|
||||||
{ { &SSL_CTX_use_PrivateKey_ASN1 }, "SSL_CTX_use_PrivateKey_ASN1" },
|
{ { &SSL_CTX_use_PrivateKey_ASN1 }, "SSL_CTX_use_PrivateKey_ASN1" },
|
||||||
{ { &SSL_CTX_use_certificate_file },"SSL_CTX_use_certificate_file"},
|
{ { &SSL_CTX_use_certificate_file },"SSL_CTX_use_certificate_file"},
|
||||||
|
@ -312,7 +319,6 @@ static void loadSSL(void) {
|
||||||
{ { &SSLv23_server_method }, "SSLv23_server_method" },
|
{ { &SSLv23_server_method }, "SSLv23_server_method" },
|
||||||
{ { &d2i_X509 }, "d2i_X509" },
|
{ { &d2i_X509 }, "d2i_X509" },
|
||||||
{ { &X509_free }, "X509_free" },
|
{ { &X509_free }, "X509_free" },
|
||||||
{ { &x_SSL_CTX_set_cipher_list }, "SSL_CTX_set_cipher_list" },
|
|
||||||
{ { &x_sk_zero }, "sk_zero" }
|
{ { &x_sk_zero }, "sk_zero" }
|
||||||
};
|
};
|
||||||
for (unsigned i = 0; i < sizeof(symbols)/sizeof(symbols[0]); i++) {
|
for (unsigned i = 0; i < sizeof(symbols)/sizeof(symbols[0]); i++) {
|
||||||
|
@ -329,6 +335,7 @@ static void loadSSL(void) {
|
||||||
x_SSL_COMP_get_compression_methods = loadSymbol(path_libssl, "SSL_COMP_get_compression_methods");
|
x_SSL_COMP_get_compression_methods = loadSymbol(path_libssl, "SSL_COMP_get_compression_methods");
|
||||||
// ends
|
// ends
|
||||||
|
|
||||||
|
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
dcheck(!ERR_peek_error());
|
dcheck(!ERR_peek_error());
|
||||||
debug("Loaded SSL suppport");
|
debug("Loaded SSL suppport");
|
||||||
|
@ -596,28 +603,61 @@ static int sslSetCertificateFromFile(SSL_CTX *context,
|
||||||
}
|
}
|
||||||
|
|
||||||
static SSL_CTX *sslMakeContext(void) {
|
static SSL_CTX *sslMakeContext(void) {
|
||||||
|
|
||||||
SSL_CTX *context;
|
SSL_CTX *context;
|
||||||
check(context = SSL_CTX_new(SSLv23_server_method()));
|
check(context = SSL_CTX_new(SSLv23_server_method()));
|
||||||
SSL_CTX_set_options(context, SSL_OP_ALL);
|
|
||||||
SSL_CTX_set_options(context, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
|
long options = SSL_OP_ALL;
|
||||||
|
options |= SSL_OP_NO_SSLv2;
|
||||||
|
options |= SSL_OP_NO_SSLv3;
|
||||||
|
options |= SSL_OP_SINGLE_DH_USE;
|
||||||
|
|
||||||
#ifdef SSL_OP_NO_COMPRESSION
|
#ifdef SSL_OP_NO_COMPRESSION
|
||||||
SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
|
options |= SSL_OP_NO_COMPRESSION;
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAVE_DLOPEN)
|
|
||||||
|
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
|
||||||
|
options |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set default SSL options.
|
||||||
|
SSL_CTX_set_options(context, options);
|
||||||
|
|
||||||
|
// Workaround for SSL_OP_NO_COMPRESSION with older OpenSSL versions.
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
if (SSL_COMP_get_compression_methods) {
|
if (SSL_COMP_get_compression_methods) {
|
||||||
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
|
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
|
||||||
}
|
}
|
||||||
#elif OPENSSL_VERSION_NUMBER >= 0x00908000L
|
#elif OPENSSL_VERSION_NUMBER >= 0x00908000L
|
||||||
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
|
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
|
||||||
#endif
|
#endif
|
||||||
SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE);
|
|
||||||
#ifdef SSL_OP_SINGLE_ECDH_USE
|
// For Perfect Forward Secrecy (PFS) support we need to enable some additional
|
||||||
|
// SSL options, provide eliptic curve key object for handshake and add chipers
|
||||||
|
// suits with ECDHE handshake on top of the ciper list.
|
||||||
|
#ifdef HAVE_OPENSSL_EC
|
||||||
SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
|
SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
|
||||||
|
SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||||
|
|
||||||
|
EC_KEY *ecKey;
|
||||||
|
check(ecKey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
|
||||||
|
SSL_CTX_set_tmp_ecdh(context, ecKey);
|
||||||
|
EC_KEY_free(ecKey);
|
||||||
|
|
||||||
|
debug("SSL: support for PFS enabled...");
|
||||||
#endif
|
#endif
|
||||||
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
|
|
||||||
SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
check(SSL_CTX_set_cipher_list(context,
|
||||||
#endif
|
"ECDHE-RSA-AES256-GCM-SHA384:"
|
||||||
check(SSL_CTX_set_cipher_list(context, "HIGH:MEDIUM:!aNULL:!MD5"));
|
"ECDHE-RSA-AES128-GCM-SHA256:"
|
||||||
|
"ECDHE-RSA-AES256-SHA384:"
|
||||||
|
"ECDHE-RSA-AES128-SHA256:"
|
||||||
|
"ECDHE-RSA-AES256-SHA:"
|
||||||
|
"ECDHE-RSA-AES128-SHA:"
|
||||||
|
"ECDHE-RSA-DES-CBC3-SHA:"
|
||||||
|
"HIGH:MEDIUM:!RC4:!aNULL:!MD5"));
|
||||||
|
|
||||||
|
debug("SSL: server context succesfully initialized...");
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
#undef HAVE_OPENSSL
|
#undef HAVE_OPENSSL
|
||||||
typedef struct BIO BIO;
|
typedef struct BIO BIO;
|
||||||
typedef struct BIO_METHOD BIO_METHOD;
|
typedef struct BIO_METHOD BIO_METHOD;
|
||||||
|
typedef struct EC_KEY EC_KEY;
|
||||||
typedef struct SSL SSL;
|
typedef struct SSL SSL;
|
||||||
typedef struct SSL_CTX SSL_CTX;
|
typedef struct SSL_CTX SSL_CTX;
|
||||||
typedef struct SSL_METHOD SSL_METHOD;
|
typedef struct SSL_METHOD SSL_METHOD;
|
||||||
|
@ -69,6 +70,12 @@ typedef struct X509 X509;
|
||||||
#define SSL_ERROR_WANT_WRITE 3
|
#define SSL_ERROR_WANT_WRITE 3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// EC support was added to OpenSSL in 0.9.8, but it can be disabled in some
|
||||||
|
// distributions.
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL && !defined(OPENSSL_NO_EC)
|
||||||
|
# define HAVE_OPENSSL_EC
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_DLOPEN)
|
#if defined(HAVE_DLOPEN)
|
||||||
extern long (*x_BIO_ctrl)(BIO *, int, long, void *);
|
extern long (*x_BIO_ctrl)(BIO *, int, long, void *);
|
||||||
extern BIO_METHOD *(*x_BIO_f_buffer)(void);
|
extern BIO_METHOD *(*x_BIO_f_buffer)(void);
|
||||||
|
@ -77,15 +84,18 @@ extern BIO *(*x_BIO_new)(BIO_METHOD *);
|
||||||
extern BIO *(*x_BIO_new_socket)(int, int);
|
extern BIO *(*x_BIO_new_socket)(int, int);
|
||||||
extern BIO *(*x_BIO_pop)(BIO *);
|
extern BIO *(*x_BIO_pop)(BIO *);
|
||||||
extern BIO *(*x_BIO_push)(BIO *, BIO *);
|
extern BIO *(*x_BIO_push)(BIO *, BIO *);
|
||||||
|
#if defined(HAVE_OPENSSL_EC)
|
||||||
|
extern void (*x_EC_KEY_free)(EC_KEY *);
|
||||||
|
extern EC_KEY *(*x_EC_KEY_new_by_curve_name)(int);
|
||||||
|
#endif
|
||||||
extern void (*x_ERR_clear_error)(void);
|
extern void (*x_ERR_clear_error)(void);
|
||||||
extern void (*x_ERR_clear_error)(void);
|
|
||||||
extern unsigned long (*x_ERR_peek_error)(void);
|
|
||||||
extern unsigned long (*x_ERR_peek_error)(void);
|
extern unsigned long (*x_ERR_peek_error)(void);
|
||||||
extern long (*x_SSL_CTX_callback_ctrl)(SSL_CTX *, int, void (*)(void));
|
extern long (*x_SSL_CTX_callback_ctrl)(SSL_CTX *, int, void (*)(void));
|
||||||
extern int (*x_SSL_CTX_check_private_key)(const SSL_CTX *);
|
extern int (*x_SSL_CTX_check_private_key)(const SSL_CTX *);
|
||||||
extern long (*x_SSL_CTX_ctrl)(SSL_CTX *, int, long, void *);
|
extern long (*x_SSL_CTX_ctrl)(SSL_CTX *, int, long, void *);
|
||||||
extern void (*x_SSL_CTX_free)(SSL_CTX *);
|
extern void (*x_SSL_CTX_free)(SSL_CTX *);
|
||||||
extern SSL_CTX*(*x_SSL_CTX_new)(SSL_METHOD *);
|
extern SSL_CTX*(*x_SSL_CTX_new)(SSL_METHOD *);
|
||||||
|
extern int (*x_SSL_CTX_set_cipher_list)(SSL_CTX *ctx, const char *str);
|
||||||
extern int (*x_SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int);
|
extern int (*x_SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int);
|
||||||
extern int (*x_SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *,
|
extern int (*x_SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *,
|
||||||
const unsigned char *, long);
|
const unsigned char *, long);
|
||||||
|
@ -111,7 +121,6 @@ extern int (*x_SSL_write)(SSL *, const void *, int);
|
||||||
extern SSL_METHOD *(*x_SSLv23_server_method)(void);
|
extern SSL_METHOD *(*x_SSLv23_server_method)(void);
|
||||||
extern X509 * (*x_d2i_X509)(X509 **px, const unsigned char **in, int len);
|
extern X509 * (*x_d2i_X509)(X509 **px, const unsigned char **in, int len);
|
||||||
extern void (*x_X509_free)(X509 *a);
|
extern void (*x_X509_free)(X509 *a);
|
||||||
extern int (*x_SSL_CTX_set_cipher_list)(SSL_CTX *ctx, const char *str);
|
|
||||||
extern void (*x_sk_zero)(void *st);
|
extern void (*x_sk_zero)(void *st);
|
||||||
extern void *(*x_SSL_COMP_get_compression_methods)(void);
|
extern void *(*x_SSL_COMP_get_compression_methods)(void);
|
||||||
|
|
||||||
|
@ -122,15 +131,16 @@ extern void *(*x_SSL_COMP_get_compression_methods)(void);
|
||||||
#define BIO_new_socket x_BIO_new_socket
|
#define BIO_new_socket x_BIO_new_socket
|
||||||
#define BIO_pop x_BIO_pop
|
#define BIO_pop x_BIO_pop
|
||||||
#define BIO_push x_BIO_push
|
#define BIO_push x_BIO_push
|
||||||
|
#define EC_KEY_free x_EC_KEY_free
|
||||||
|
#define EC_KEY_new_by_curve_name x_EC_KEY_new_by_curve_name
|
||||||
#define ERR_clear_error x_ERR_clear_error
|
#define ERR_clear_error x_ERR_clear_error
|
||||||
#define ERR_clear_error x_ERR_clear_error
|
|
||||||
#define ERR_peek_error x_ERR_peek_error
|
|
||||||
#define ERR_peek_error x_ERR_peek_error
|
#define ERR_peek_error x_ERR_peek_error
|
||||||
#define SSL_CTX_callback_ctrl x_SSL_CTX_callback_ctrl
|
#define SSL_CTX_callback_ctrl x_SSL_CTX_callback_ctrl
|
||||||
#define SSL_CTX_check_private_key x_SSL_CTX_check_private_key
|
#define SSL_CTX_check_private_key x_SSL_CTX_check_private_key
|
||||||
#define SSL_CTX_ctrl x_SSL_CTX_ctrl
|
#define SSL_CTX_ctrl x_SSL_CTX_ctrl
|
||||||
#define SSL_CTX_free x_SSL_CTX_free
|
#define SSL_CTX_free x_SSL_CTX_free
|
||||||
#define SSL_CTX_new x_SSL_CTX_new
|
#define SSL_CTX_new x_SSL_CTX_new
|
||||||
|
#define SSL_CTX_set_cipher_list x_SSL_CTX_set_cipher_list
|
||||||
#define SSL_CTX_use_PrivateKey_file x_SSL_CTX_use_PrivateKey_file
|
#define SSL_CTX_use_PrivateKey_file x_SSL_CTX_use_PrivateKey_file
|
||||||
#define SSL_CTX_use_PrivateKey_ASN1 x_SSL_CTX_use_PrivateKey_ASN1
|
#define SSL_CTX_use_PrivateKey_ASN1 x_SSL_CTX_use_PrivateKey_ASN1
|
||||||
#define SSL_CTX_use_certificate_file x_SSL_CTX_use_certificate_file
|
#define SSL_CTX_use_certificate_file x_SSL_CTX_use_certificate_file
|
||||||
|
@ -154,13 +164,13 @@ extern void *(*x_SSL_COMP_get_compression_methods)(void);
|
||||||
#define SSLv23_server_method x_SSLv23_server_method
|
#define SSLv23_server_method x_SSLv23_server_method
|
||||||
#define d2i_X509 x_d2i_X509
|
#define d2i_X509 x_d2i_X509
|
||||||
#define X509_free x_X509_free
|
#define X509_free x_X509_free
|
||||||
#define SSL_CTX_set_cipher_list x_SSL_CTX_set_cipher_list
|
|
||||||
#define sk_zero x_sk_zero
|
#define sk_zero x_sk_zero
|
||||||
#define SSL_COMP_get_compression_methods x_SSL_COMP_get_compression_methods
|
#define SSL_COMP_get_compression_methods x_SSL_COMP_get_compression_methods
|
||||||
|
|
||||||
#undef BIO_set_buffer_read_data
|
#undef BIO_set_buffer_read_data
|
||||||
#undef SSL_CTX_set_tlsext_servername_arg
|
#undef SSL_CTX_set_tlsext_servername_arg
|
||||||
#undef SSL_CTX_set_tlsext_servername_callback
|
#undef SSL_CTX_set_tlsext_servername_callback
|
||||||
|
#undef SSL_CTX_set_tmp_ecdh
|
||||||
#undef SSL_get_app_data
|
#undef SSL_get_app_data
|
||||||
#undef SSL_set_app_data
|
#undef SSL_set_app_data
|
||||||
#undef SSL_set_mode
|
#undef SSL_set_mode
|
||||||
|
@ -175,6 +185,9 @@ extern void *(*x_SSL_COMP_get_compression_methods)(void);
|
||||||
(x_SSL_CTX_callback_ctrl(ctx, \
|
(x_SSL_CTX_callback_ctrl(ctx, \
|
||||||
SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, \
|
SSL_CTRL_SET_TLSEXT_SERVERNAME_CB, \
|
||||||
(void (*)(void))cb))
|
(void (*)(void))cb))
|
||||||
|
#define SSL_CTX_set_tmp_ecdh(ctx, ecdh) \
|
||||||
|
(x_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_ECDH, \
|
||||||
|
0, (char *)ecdh))
|
||||||
#define SSL_get_app_data(s) (x_SSL_get_ex_data(s, 0))
|
#define SSL_get_app_data(s) (x_SSL_get_ex_data(s, 0))
|
||||||
#define SSL_set_app_data(s, arg) (x_SSL_set_ex_data(s, 0, (char *)arg))
|
#define SSL_set_app_data(s, arg) (x_SSL_set_ex_data(s, 0, (char *)arg))
|
||||||
#define SSL_set_mode(ssl, op) (x_SSL_ctrl((ssl), SSL_CTRL_MODE, (op), NULL))
|
#define SSL_set_mode(ssl, op) (x_SSL_ctrl((ssl), SSL_CTRL_MODE, (op), NULL))
|
||||||
|
|
Loading…
Reference in a new issue