I am using RSA cipher for signing the certificate and SSL_CTX_set_tmp_ecdh_callback() api to set the ECDH parameters for key-exchange. The server always ends up choosing TLS_ECDHE_RSA_* cipher suite. If i make the client send only TLS_ECDH_* cipher suites in the clientHello, the server breaks the connection stating "no shared cipher".
Can someone tell me how to make a server choose a ECDH_* cipher over ECDHE_* ?
How is it that the server decides I should choose ECDH_* cipher over ECDHE_* ciphers ?
Now that this is moved where it's ontopic, and clarified enough, and the partying is over:
Ephemeral ECDH suites: TLS suites that use ephemeral ECDH key exchange (
ECDHE-*
) use at least nominally ephemeral ECDH keys, which OpenSSL calls 'temporary'. OpenSSL through 1.0.2 has 4-6 ways of setting these keys:SSL_CTX_set_tmp_ecdh
orSSL_set_tmp_ecdh
set (only) the 'curve' to be used; to be exact this is anEC_GROUP
or formally 'parameter set' that consists of an actual curve defined by a curve equation on an underlying field, plus a specified base point which generates a subgroup on the curve of sufficiently high order and low cofactor, but most of the time we ignore this detail and just call it a 'curve'. OpenSSL then generates a random key on that curve for and during each handshake.SSL_CTX_set_tmp_ecdh_callback
orSSL_set_tmp_ecdh_callback
sets a function that is called during each handshake and can either set a specific key, or set a curve and OpenSSL generates a random key on that curve.SSL_CTX_set_ecdh_auto
orSSL_set_ecdh_auto
new in 1.0.2 causes OpenSSL during each handshake to choose a curve based on the client hello, and generate a random key on that curve.Note that each ciphersuite using ECDHE also defines the type of key with matching certificate chain the server must use to authenticate:
ECDHE-RSA
must use an RSA key&cert whileECDHE-ECDSA
must use an ECDSA key&cert (or to be precise EC key and ECDSA cert, since the same EC key can be used for ECDSA, ECDH, ECIES, and more, but usually shouldn't). OpenSSL library can be configured with multiple key&cert pairs, one of each type, and commandlines_server
can do two static pairs using-cert -key -dcert -dkey
plus one for SNI-cert2 -key2
, but other programs may or may not.However, in 1.1.0 these functions are removed and it appears OpenSSL always does what was formerly
ecdh_auto
.Static ECDH suites: TLS suites that use static aka fixed ECDH key exchange (
ECDH-*
) use a static ECDH key and do not use an ephemeral or temporary ECDH key. Since they do not use a temporary key, the functions involved in setting a temporary curve or key are irrelevant and have no useful effect. Instead the static ECDH key must be in the server's configured key and certificate pair, and the certificate must allow ECDH i.e. it must not havekeyUsage
that excludeskeyAgreement
. In addition, in TLS 1.0 and 1.1 the configured certificate must be signed by a CA using a signature algorithm matching the ciphersuite:ECDH-ECDSA
ciphersuites must use an ECDH cert signed by an ECDSA CA, andECDH-RSA
ciphersuites must use an ECDH cert signed by an RSA CA; see rfc4492 section 5.3. For TLS 1.2 rfc 5246 section 7.4.2 and A.7 for ECC relaxes this requirement and allows the CA cert to be any algorithm permitted by the client's signature_algorithms extension. However on checking I found OpenSSL doesn't implement this relaxation, so part of my earlier comment is wrong; even for 1.2 it requires the CA signature algorithm match the ciphersuite.In addition for all protocol versions the key and (EE) cert must use a curve supported by the client in supported_curves extension, and the cert must express that key in 'named' form (using an OID to identify the curve rather than explicit parameters) and a point format supported by the client in supported_formats extension. With OpenSSL client this is never an issue because it supports all named curves and point formats, and in practice certificates don't use explicit curve parameters.
Thus to get static ECDH with OpenSSL:
configure the server with an EC key (
SSL_[CTX_]use_PrivateKey*
) and matching certificate (SSL_[CTX_]use_certificate[_chain]*
) that allows keyAgreement and is signed by a CA using RSA or ECDSA -- and like all PK-based ciphersuites also configure any chain certs needed by the client(s) to validate the certconfigure both ends to allow (which is true by default) and at least one end to require or the preference end to prefer ciphersuite(s) using
ECDH-xyz
wherexyz
isRSA
orECDSA
to match the CA signature on the server certignore
ecdh_tmp
andecdh_auto
entirely... except in 1.1.0, which on checking I found no longer implements any static-ECDH or static-DH ciphersuites -- even though the static-DH suites are still in the manpage for ciphers. This is not in the CHANGES file that I can find, and I haven't had time to go through the code yet.