添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In OpenSSL, the ciphersuite 0xc02b (OpenSSL name: ECDHE-ECDSA-AES128-GCM-SHA256 / IANA name: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) is broken.
So much so, that not even openssl.exe can connect to itself using just that cipher (see below).

I've checked various 1.1.1 versions and even some 1.0.2 versions, oldest was 1.0.2q from various sources (inhouse built and 3rd-party built). They all show the same behavior of being unable to connect employing the above cipher.

Steps to Reproduce:

- have openssl.exe
- generate key pair (e.g. openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes)
- start openssl server limited to TLS 1.2 and above chiper (e.g. openssl s_server -key key.pem -cert cert.pem -accept 5555 -tls1_2 -cipher "ECDHE-ECDSA-AES128-GCM-SHA256" -www)
- connect with openssl client employing same cipher (e.g. openssl s_client -tls1_2 -cipher "ECDHE-ECDSA-AES128-GCM-SHA256" -connect localhost:5555)
- notice client will issue handshake failure
- notice server will issue error regarding no shared cipher
          

I'm no ciphersuite expert, but isn't it simply that you are trying to use an RSA key with a ciphersuite that has ECDSA authentication?

The connection works just fine with an EC key (tried with 1.0.2p on SLES 12 and 1.1.1k on RHEL 8).

openssl genpkey -genparam -algorithm EC -out ec_params.pem -pkeyopt ec_paramgen_curve:prime256v1 -pkeyopt ec_param_enc:named_curve
openssl req -x509 -newkey ec:ec_params.pem -keyout ec_key.pem -out ec_cert.pem -days 365 -nodes
          

Take care to choose most secure ec_paramgen_curve.
Bug: if you choose too secure, it will not work.
OpenSSL allows to generate what it itself does not accept.
You have to test which it accepts.
s_client() accepts more than s_server(). Does not refuse any Curve. Does offer it to s_server(). s_server() rejects it. Hence, s_server() determines the limit.
Bug: man SSL_CONF_cmd lists 10 Curves (Groups) that it accepts with TLS1.3. Fails to explain whether they mean signatures, key exchange, or both. Specifies that signatures are for TLS1.2 and earlier. This may exclude TLS1.3. Maybe for TLS1.3 Groups sets only key exchange.

openssl ecparam -list_curves
Bug: -help claims it lists "short" names. Actually, most names are long.
No way to list "long". You can hack from source code, or from binary openssl().
Once you produce file of parameters, you may view in it both names. But of the specific curve that you produce, not all.
openssl ecparam -text -in file
It terms them "ASN1 OID" for "short",
"NIST CURVE" for "long".
Bug: fails to list parameters SM2 from file that itself generates.

Still, you use less ciphers than available.
You may want to use complete set, for every possible client.

To complete the list, generate key DSA. openssl ciphers() terms it DSS.
It needs a file of DH parameters. Generate that too; strongest possible.

There are 5 types of ciphers: RSA, ECDSA, DSA (DSS), PSK, None. Non-encrypting - eNULL - ciphers are these types too.
A cipher does not apply, if key of same type is missing.
Make certificates of each type. So that server can present them to client.
Perhaps, keys would not work without certificates.
Pre Shared Keys (PSK) seem not to use certificate, and file for key. Key is simply a number on command line -psk. See man openssl-s_client, openssl-s_server. OpenSSL does not document PSK. Provides only functions.
None applies when no other cipher does. Does not require a key.
So, you only need to make 3 types: RSA, ECDSA, DSA (DSS).

Bug: s_server ignores multiple -cert. Takes the last.
Yet, refuses to run without one. Have to specify at least, and at most, 1 on command line.
List extra in openssl.cnf, section that server = there refers to.
Bug: ignores DHParameters in openssl.cnf.
Load that on command line: -dhparam.
Load openssl.cnf with -ssl_config server.
Bug: -ssl_config is undocumented for s_server(). Documented only for s_client(). And that is poorly.
From application load by SSL_CTX_config(). Does not ignore DHParameters.
RSA.Certificate = file
RSA.PrivateKey = file
2.Certificate = file
2.PrivateKey = file
RSAweak.Certificate = file
RSAweak.PrivateKey = file
RSASHA1.Certificate = file
RSASHA1.PrivateKey = file
DSA.Certificate = file
DSA.PrivateKey = file
ECDSA.Certificate = file
ECDSA.PrivateKey = file
Bug: In the example I provide 4 certificates of same type RSA. One numbered. 2 for weak clients. As they may fail to use strong key from server. SHA1 is weak too. Perhaps, this would not work. Because man SSL_CTX_use_certificate states that new certificate replaces all previous of same type. Fails to specify what type means. If it means RSA, ECDSA, DSA, then result is 3 certificates, rather than 6. - 1 for each type.
Bug: man config states it loads only last option.
It states that in order to specify multiple options, you have to prefix their names, with dot (period) ".".
Fails to specify which options can have prefix.
Mistake: as if openssl.cnf ignores name after dot:

is preceded with a period

Actually - before. Should read: "precede with period"
Mistake: as if purpose of prefix is to specify multiple options. Actually, it is but to comment on purpose of the option.
But you may comment on lines that begin with #. No need to use part of name as comment.
openssl.cnf should accept multiple options without the need for prefix.
If you do not prefix, combination of the 2 bugs causes s_server() to have 2 certificates at most: -cert on command line, and Certificate in openssl.cnf.
An application, that calls OpenSSL as library, can have more, by SSL_CTX_use_certificate_file(), SSL_CTX_use_certificate_chain_file(), SSL_CTX_use_PrivateKey_file().
It may still load but 1 certificate from openssl.cnf by SSL_CTX_config(). Unless you prefix extra names.

It may not suffice to have keys for all ciphers. In order to use all, you have to specify them in openssl.cnf, section that system_default = refers to.
See man config.
For TLS1.3 add 2 ciphers. Words ALL, DEFAULT do not apply. Have to specify entire list explicitly. - Both default 3, and extra 2. In order of preference.
Ciphersuites = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256
For TLS1.2, and previous:
CipherString = ALL
Or for really all ciphers. Mind that @SECLEVEL=1 still disables eNULL. You would need to set level 0. See below.
CipherString = ALL:eNULL
I am not sure whether this includes PSK. Because openssl ciphers -s ALL does not list them without -psk.

More ciphers do not weaken security. They allow choice to client. OpenSSL still chooses the most secure from list that client suggests. - In the order of preference by client.
You may use order of preference by server in openssl.cnf: Options = ServerPreference.
On command line: openssl s_server -serverpref
Better than reject client. One may not go away. Instead, one may panic, and use plain text.
OpenSSL needlessly hides many ciphers. Instead, it should warn, and teach that some are weak. Maybe it hides them not for weakness. Maybe for no reason.

Make a list of ciphers. Try 1 by 1 to see if server still fails to accept any.
openssl ciphers -V
Capital -V shows numeric identifiers. So, you may definitely identify ciphers in log.
Bug: -psk claims to "enable" PSK. But actually it affects only display. Does not affect server.
-s restricts the list to "supported". Though, it is not clear what it means.
man claims it reflects OPENSSL_TLS_SECURITY_LEVEL (@SECLEVEL). This is false. Level outside connection of TLS is 0. And you can not call this program on command line during TLS. That is, while your application runs, with its own OPENSSL_TLS_SECURITY_LEVEL. Default is 2.
So, -s means not particular server, or client. Does not inspect them as they run, and not in the way you configure. Does not show exclusion of ciphers by missing keys. Rather, it means properties of ciphers in general, only as you specify on command line.
List default ciphers, at default @SECLEVEL=2. - That application would get, if you do not change configuration. @SECLEVEL alone fails. Needs extra strings. DEFAULT fails as suffix. Works only as prefix. -s is necessary in order to exclude ciphers by @SECLEVEL.
openssl ciphers -s -V "DEFAULT:@SECLEVEL=2"
List all. ALL is not really all. Have to add eNULL. Specify level 0 to see really all.
Without -s ignores @SECLEVEL, lists all anyway. With @SECLEVEL=0 lists all too, regardless of -s. So, you may omit both. Especially that level 0 is default outside TLS, anyway.
openssl ciphers -s -V "@SECLEVEL=0:ALL:eNULL"

In order to use all available ciphers, you have to disable default OPENSSL_TLS_SECURITY_LEVEL (@SECLEVEL).
Specify it as part of CipherString = @SECLEVEL=0:... in openssl.cnf.
Or in calls to functions from your application.
Or compile OpenSSL with #define OPENSSL_TLS_SECURITY_LEVEL 0 in include/openssl/tls1.h
Name of file suggests as if OPENSSL_TLS_SECURITY_LEVEL pertains only to ciphers of TLS1. But it can exclude ciphers of TLS1.2, TLS1.3 as well. Exclude 3 of TLS1.3. Select only 2:
openssl ciphers -s -V "@SECLEVEL=4:eNULL"
Same. And exclude 38 of TLS1.2. Select 23 of TLS1.2:
openssl ciphers -s -V "@SECLEVEL=4:ALL"
Here eNULL is but placeholder for @SECLEVEL to work. It does add to list of ciphers. But level 4 excludes those weak ciphers anyway. So, the list is pure TLS1.3. Can not instead use DEFAULT, or ALL. They would add to list ciphers of TLS1.2, and prior. Level 4 would include some. Not pure TLS1.3. Would not act as dummy to allow @SECLEVEL work alone.
Bug: unlike Ciphersuites in openssl.cnf above, you can not use explicit list of 5 ciphers TLS1.3. There is no string for it, like there is TLSv1.2. So, you can not restrict list to this protocol. Could use -s -tls1_3. But that is not the same.

See man SSL_CONF_cmd for name CipherString. It is for TLS1.2, and prior.
man openssl-ciphers for its format.
Ciphersuites is straightforward, simply explicit list. It is for TLS1.3.