Skip to content

Commit 3164721

Browse files
committed
SSL: Support ECDH key exchange
This sets up ECDH key exchange, when compiling against OpenSSL that supports EC. Then the ECDHE-RSA and ECDHE-ECDSA cipher suites can be used for SSL connections. The latter one means that EC keys are now usable. The reason for EC key exchange is that it's faster than DHE and it allows to go to higher security levels where RSA will be horribly slow. There is also new GUC option ssl_ecdh_curve that specifies the curve name used for ECDH. It defaults to "prime256v1", which is the most common curve in use in HTTPS. From: Marko Kreen <markokr@gmail.com> Reviewed-by: Adrian Klaver <adrian.klaver@gmail.com>
1 parent 9148440 commit 3164721

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

doc/src/sgml/config.sgml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,24 @@ include 'filename'
907907
</listitem>
908908
</varlistentry>
909909

910+
<varlistentry id="guc-ssl-ecdh-curve" xreflabel="ssl_ecdh_curve">
911+
<term><varname>ssl_ecdh_curve</varname> (<type>string</type>)</term>
912+
<indexterm>
913+
<primary><varname>ssl_ecdh_curve</> configuration parameter</primary>
914+
</indexterm>
915+
<listitem>
916+
<para>
917+
Specifies the name of the curve to use in ECDH key exchanges. The
918+
default is <literal>prime256p1</>.
919+
</para>
920+
921+
<para>
922+
The list of available curves can be shown with the command
923+
<literal>openssl ecparam -list_curves</literal>.
924+
</para>
925+
</listitem>
926+
</varlistentry>
927+
910928
<varlistentry id="guc-password-encryption" xreflabel="password_encryption">
911929
<term><varname>password_encryption</varname> (<type>boolean</type>)</term>
912930
<indexterm>

src/backend/libpq/be-secure.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@
6969
#if SSLEAY_VERSION_NUMBER >= 0x0907000L
7070
#include <openssl/conf.h>
7171
#endif
72+
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_ECDH)
73+
#include <openssl/ec.h>
74+
#endif
7275
#endif /* USE_SSL */
7376

7477
#include "libpq/libpq.h"
@@ -112,6 +115,9 @@ static bool ssl_loaded_verify_locations = false;
112115
/* GUC variable controlling SSL cipher list */
113116
char *SSLCipherSuites = NULL;
114117

118+
/* GUC variable for default ECHD curve. */
119+
char *SSLECDHCurve;
120+
115121
/* GUC variable: if false, prefer client ciphers */
116122
bool SSLPreferServerCiphers;
117123

@@ -774,6 +780,31 @@ info_cb(const SSL *ssl, int type, int args)
774780
}
775781
}
776782

783+
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_ECDH)
784+
static void
785+
initialize_ecdh(void)
786+
{
787+
EC_KEY *ecdh;
788+
int nid;
789+
790+
nid = OBJ_sn2nid(SSLECDHCurve);
791+
if (!nid)
792+
ereport(FATAL,
793+
(errmsg("ECDH: unrecognized curve name: %s", SSLECDHCurve)));
794+
795+
ecdh = EC_KEY_new_by_curve_name(nid);
796+
if (!ecdh)
797+
ereport(FATAL,
798+
(errmsg("ECDH: could not create key")));
799+
800+
SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_ECDH_USE);
801+
SSL_CTX_set_tmp_ecdh(SSL_context, ecdh);
802+
EC_KEY_free(ecdh);
803+
}
804+
#else
805+
#define initialize_ecdh()
806+
#endif
807+
777808
/*
778809
* Initialize global SSL context.
779810
*/
@@ -853,6 +884,9 @@ initialize_SSL(void)
853884
SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb);
854885
SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2);
855886

887+
/* set up ephemeral ECDH keys */
888+
initialize_ecdh();
889+
856890
/* set up the allowed cipher list */
857891
if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1)
858892
elog(FATAL, "could not set the cipher list (no valid ciphers available)");

src/backend/utils/misc/guc.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ extern char *temp_tablespaces;
127127
extern bool ignore_checksum_failure;
128128
extern bool synchronize_seqscans;
129129
extern char *SSLCipherSuites;
130+
extern char *SSLECDHCurve;
130131
extern bool SSLPreferServerCiphers;
131132

132133
#ifdef TRACE_SORT
@@ -3150,6 +3151,21 @@ static struct config_string ConfigureNamesString[] =
31503151
NULL, NULL, NULL
31513152
},
31523153

3154+
{
3155+
{"ssl_ecdh_curve", PGC_POSTMASTER, CONN_AUTH_SECURITY,
3156+
gettext_noop("Sets the curve to use for ECDH."),
3157+
NULL,
3158+
GUC_SUPERUSER_ONLY
3159+
},
3160+
&SSLECDHCurve,
3161+
#ifdef USE_SSL
3162+
"prime256v1",
3163+
#else
3164+
"none",
3165+
#endif
3166+
NULL, NULL, NULL
3167+
},
3168+
31533169
{
31543170
{"application_name", PGC_USERSET, LOGGING_WHAT,
31553171
gettext_noop("Sets the application name to be reported in statistics and logs."),

src/backend/utils/misc/postgresql.conf.sample

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
#ssl_ciphers = 'DEFAULT:!LOW:!EXP:!MD5:@STRENGTH' # allowed SSL ciphers
8383
# (change requires restart)
8484
#ssl_prefer_server_ciphers = on # (change requires restart)
85+
#ssl_ecdh_curve = 'prime256v1' # (change requires restart)
8586
#ssl_renegotiation_limit = 512MB # amount of data between renegotiations
8687
#ssl_cert_file = 'server.crt' # (change requires restart)
8788
#ssl_key_file = 'server.key' # (change requires restart)

0 commit comments

Comments
 (0)