OpenSSL let the server and client negotiate the method - ssl

Following a really outdated tutorial I managed to create an HTTPS server using OpenSSL with TLS1.2, and I'm very proud of it ;)
However TLS 1.2 is only supported in latest browsers and I would like to have some kind of negotiation of the protocol between the client and server, which I'm sure it can be done, but I'm not able to find how! So that if the client only supports TLS1.0, well use that. And if it only supports SSLv3, use that. Not sure about SSLv2, maybe better leave that...
The code I use right now is:
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ssl_method = TLSv1_2_server_method();
ssl_ctx = SSL_CTX_new(ssl_method);
Then the server certificates are loaded and the ssl_ctx is shared among all connections. When a client is accepted by the server socket it is encapsulated in an SSL object (whatever it represents):
ssl = SSL_new(ssl_ctx);
SSL_set_fd(ssl, client_socket);
SSL_accept(ssl);
So I guess that something has to be changed in the ssl_ctx creation to allow more methods... Any idea?
<rant> No decent, extensive documentation can be found for OpenSSL, the best available is a 10 years old tutorial! </rant>
Thanks in advance.

You do this by using SSLv23_method() (and friends) instead of a specific method (e.g. TLSv1_2_server_method() in your example). This sends the SSLv2 ClientHello but also specifies the highest protocol supported. The somewhat outdated man page says:
SSLv23_method(void), SSLv23_server_method(void), SSLv23_client_method(void)
A TLS/SSL connection established with these methods will understand
the SSLv2, SSLv3, and TLSv1 protocol. A client will send out SSLv2
client hello messages and will indicate that it also understands SSLv3
and TLSv1. A server will understand SSLv2, SSLv3, and TLSv1 client
hello messages. This is the best choice when compatibility is a
concern.
This online man page doesn't discuss the newer TLSv1_1 and TLSv1_2 protocols, but I verified in the 1.0.1g source of s23_clnt.c that SSLv23_method() includes them.
You then limit the protocols you actually accept with SSL_CTX_set_options():
The list of protocols available can later be limited using the
SSL_OP_NO_SSLv2, SSL_OP_NO_SSLv3, SSL_OP_NO_TLSv1 options of the
SSL_CTX_set_options() or SSL_set_options() functions. Using these
options it is possible to choose e.g. SSLv23_server_method() and be
able to negotiate with all possible clients, but to only allow newer
protocols like SSLv3 or TLSv1.
Note, however, that you can't enable arbitrary sets of protocols, only contiguous protocols in SSLv2, SSLv3, TLSv1, TLSv1_1, TLSv1_2. For example, you can't choose only SSLv3 and TLSv1_1, omitting TLSv1. This comment in the source explains why:
SSL_OP_NO_X disables all protocols above X if there are some protocols below X enabled. This is required in order to maintain "version capability" vector contiguous. So that if application wants to disable TLS1.0 in favour of TLS1>=1, it would be insufficient to pass SSL_NO_TLSv1, the answer is SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2.

Related

openSSL 1.1.1 API Doubts

I want to set up and run SSL client and server with TLS 1.2 using openSSL 1.1.1 for my project.
I have a few doubts and/or requirements with openSSL:
what is the right way to select TLS 1.2 as version? Currently I am using TLS_client_method(). the other methods seem to be deprecated. Is there a specific API for choosing particular version?
I need to run an SSL clinet with following handshake extensions.
ec_point_formats with "uncompressed" as value
supported_groups with list of "secp521r","secp384r1","secp256r1","secp224r1","secp192r1","secp160r1","ffdhe2048"
encrypt_then_mac with value 0
server_name
extended_master_secret without any value and length set to 0
I need to run an SSL server with following handshake extensions
encrypt_then_mac with value 0
extended_master_secret without any value and length set to 0
Apart from above header extension fields I want to disable everything else. How to accomplish that?
From client I want to provide only "TLS_PSK_WITH_AES_128_CBC_SHA256" cipher suite as option.
Is client certificate and key files (pem) necessary for successful connection establishment and communication when PSK cipher is used?
Is there any example or open source client-server implementation with PSK authentication?
what is the right way to select TLS 1.2 as version? Currently I am using TLS_client_method(). the other methods seem to be deprecated. Is there a specific API for choosing particular version?
TLS_client_method() is the correct method to use. To specify that no version below TLSv1.2 is used you should do this:
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
Where ctx is your SSL_CTX object.
If you also want to prevent anything higher than TLSv1.2 from being used then do this:
SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);
See this page for information on these calls:
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_min_proto_version.html
I need to run an SSL clinet with following handshake extensions.
ec_point_formats with "uncompressed" as value
supported_groups with list of "secp521r","secp384r1","secp256r1","secp224r1","secp192r1","secp160r1","ffdhe2048"
These extensions aren't used if you specify the PSK ciphersuite that you've selected so OpenSSL won't send them (assuming you've restricted the max TLS protocol version as described above, and have configured only that ciphersuite). Doing so would be pointless. Even if it did, OpenSSL 1.1.1 does not support "ffdhe2048". It does support all the others.
encrypt_then_mac with value 0
Not sure what you mean by "with value 0" since this extension is always empty and has no value. I assume you mean with length 0. This extension is sent by default so you don't need to do anything.
server_name
You should call:
SSL_set_tlsext_host_name(ssl, "hostname of the server");
Where ssl is your SSL object, and replacing "hostname of the server" with the server's real hostname.
See this page for information on this call:
https://www.openssl.org/docs/man1.1.1/man3/SSL_set_tlsext_host_name.html
extended_master_secret without any value and length set to 0
This extension is sent by default so you don't need to do anything.
I need to run an SSL server with following handshake extensions
encrypt_then_mac with value 0
extended_master_secret without any value and length set to 0
If the client sent them, then the server will echo them back by default. You don't need to do anything.
Apart from above header extension fields I want to disable everything else. How to accomplish that?
An OpenSSL client will additionally send the session_ticket extension. Its harmless, but if you really want to disable it you can do this:
SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET);
See this page for further information:
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_options.html
An OpenSSL server will additionally send the "renegotiate" extension. You must not disable this (in fact you cannot). Ignore it. Its harmless.
From client I want to provide only "TLS_PSK_WITH_AES_128_CBC_SHA256" cipher suite as option.
That is the official IANA name for the ciphersuite. OpenSSL knows it as "PSK-AES128-CBC-SHA256".
Configure it on both the client and the server like this:
SSL_CTX_set_cipher_list(ctx, "PSK-AES128-CBC-SHA256");
See this page for further information:
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_cipher_list.html
In addition you will need to provide PSK callbacks to tell OpenSSL what the PSK is that you want to use.
On the client you need to call SSL_CTX_set_psk_client_callback(). On the server you must call SSL_CTX_set_psk_server_callback().
See these pages for further information:
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_psk_client_callback.html
https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_psk_server_callback.html
TLSv1.3 ciphersuites will still automatically be sent unless you have additionally restricted the max TLS protocol version to TLSv1.2 as described above. Finally you will also see a ciphersuite called "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" being sent. This isn't actually a real ciphersuite at all. It is always sent and cannot be suppressed. It will never be negotiated and is harmless. Ignore it.
Is client certificate and key files (pem) necessary for successful connection establishment and communication when PSK cipher is used?
No.
Is there any example or open source client-server implementation with PSK authentication?
You can look at how s_client and s_server do it:
https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/apps/s_client.c
https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/apps/s_server.c

Block HTTP/2 at the firewall level

I'm having trouble blocking the use of HTTP/2 in order to force browsers to use HTTP/1 as the protocol inside https. TLS MITM is out of the question, NFQUEUE-like usermode packet filtering may be considered at most, depending on processing overhead.
From reading the ALPN RFC it's not clear if providing an alert response or dropping the connection when I see a ClientHello that contains ALPN:http/2 will make the browser retry without ALPN.
If I understand correctly, modifying the ClientHello is out of the question as it results in a checksum error when the server responds with the ServerHello because changing the ClientHello invalidates the MAC for that packet.
Is the behavior for blocked handshakes w.r.t. ALPN the same as for handling TLS version fallback, i.e. TLS_FALLBACK_SCSV ?
EDIT: according to t1_lib.c from openssl, if the server doesn't know about ALPN, it ignores it. So if the server returns Alert for a ClientHello containing ALPN, it's probably only because it doesn't support TLS1.2, there is no way to signal to the client "please retry without ALPN" other than "alert" which results in the client trying TLS1.1.
HTTP/2 over TLS is negotiated via ALPN.
Browsers will tell to servers that they support it.
If you don't want to use HTTP/2, then you just have to modify the server configuration in a way that it doesn't have h2 as one of the protocols that it can negotiate via ALPN.
The ALPN negotiation will then fall back to HTTP/1.1 and the client will use HTTP/1.1.

WebSphere Multiple SSL Version Support

I'm running a web application that communicates with various APIs. One API requires TLSv1.2 while another will not support something that current (TLSv1 or TLSv1.1).
Does Websphere support multiple SSL versions?
I've found documentation about successfully changing the version of SSL, however I really need to be able to run TLSv1.1 and 1.2 together (if that's even possible) or run one version for one application while another for another application.
According to documentation for setting up SSL in WebSphere, to support the use of TLS 1.0, 1.1 and 1.2, I need to enable SSL_TLSv2:
Question: WAS is act SSL client, What does remote SSL server support
only TLSv1.0 or TLSv1.1 and Similar WAS is act SSL Server, What does
Remote SSL client does support only TLSv1.0 or TLSv1.1 or TLSv1.2.
What to do in order to work such environments?
Answer: There is an alternative option, SSL_TLSv2, which will enable
support for TLSv1.0, TLSv1.1, and TLSv1.2 in the environment. Please
use this setting SSL_TLSv2 in environments where support for multiple
TLS protocols is required, or if you are not sure whether your WAS
environment interacts with other servers or clients using non-TLSv1.2
protocols then, you can configure WAS to use SSL_TLSv2 using same
steps as given in the above.
Note:
Without poddle fix and configured WAS to use SSL_TLSv2
SSL_TLSv2 ==> Enables all SSL v3.0 and TLS v1.0, v1.1 and v1.2
protocols. Accepts SSLv3 or TLSv1 hello encapsulated in an SSLv2
format hello.
If you installed Poddle fix (will disable SSLv3 ) and configured WAS
to use SSL_TLSv2
SSL_TLSv2 ==> Enables these three TLS v1.0, v1.1 and v1.2 protocols.
So, changing the QoS settings to SSL_TLSv2 allows SSL Handshakes to multiple TLS versions when required.

Can a TLS 1.2 server/client get by with just TLS_RSA_WITH_AES_128_CBC_SHA?

I'm updating an embedded TLS 1.0 implementation to TLS 1.2 (devices with 1MB of code space or less, and no OS). At this point, I have AES-128 and AES-256 CBC ciphers working with SHA-1 and SHA-256 digests for a minimal implementation. The library cannot negotiate an SSLv2, SSLv3, TLS 1.0 or TLS 1.1 connection.
I felt this would be sufficient, given that RFC 5246 states, "TLS_RSA_WITH_AES_128_CBC_SHA is now the mandatory to implement cipher suite."
Yet as I read various postings on security blogs, I'm seeing recommendations that would have users disable that suite, and (for example) only allow the ECDHE_RSA or DHE_RSA variants.
So my question is whether devices using our library will interoperate with modern web browsers (as a server) and modern https/smtps/pop servers (as a client). Are there TLS 1.2 clients/servers that fail to negotiate a TLS_RSA_WITH_AES_128_CBC_SHA connection?
I am not sure there are currently many servers supporting TLS that would fail negotiating TLS_RSA_WITH_AES_128_CBC_SHA with TLSv1.2 as it is THE mandatory cipher suite for TLSv1.2.
However there are things to keep in mind:
TLS_RSA_WITH_3DES_EDE_CBC_SHA is mandatory for TLSv1.0 and TLSv1.1 but due to security reasons it is no longer supported by every server,
Mozilla recommends (and it is not the only one) to favor AES128 instead of AES256,
Perfect Forward Secrecy (PFS), allowed by DHE or ECDHE is now a must-have feature.
So if I can provide you with 4 cipher suites (the same number than you have), I would say these ones from the strongest to the weakest:
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
I would say that these 4 cipher suites bring enough security and compatibility with TLSv1.2 servers.
Now the question of supporting only TLSv1.2 is another question, but if you have enough space, I recommend you to add TLSv1.0 too (TLSv1.1 does not provide extra compatibility).
PS: The reason why AES128 is favored instead of AES256 is that some people think the extra security added by AES256 is (for now) worthless and that AES128 seems to be more resistant to timing attacks.
"So my question is whether devices using our library will interoperate with modern web browsers (as a server) and modern https/smtps/pop servers (as a client). Are there TLS 1.2 clients/servers that fail to negotiate a TLS_RSA_WITH_AES_128_CBC_SHA connection?"
Yes there are plenty implementations that fail.
Most common:
Clients that still send a SSL2.0 Client Hello
Clients/Servers that only support PFS cipher suite
Servers that still not support TLS 1.2
Servers that no longer support TLS 1.2 - since those only support TLS 1.3
My recommendation is:
also support TLS 1.3 (not that hard to implement, I did it)
also support DHE
Or use a tool/site like https://www.ssllabs.com/ssltest/index.html and test the compatibility/security of your server until it's sufficient for you.

How to set up SSL protocols priority in OpenSSL

I am implementing an SSL Client using OpenSSL which
(1) only "speaks" TLS 1.2, TLS 1.1 and TLS 1.0,
(2) set exactly this priority: TLS 1.2. If communication is not possible, use TLS 1.1. If not, TLS 1.0. If not, refuse connection.
I achieve (1) by using
SSL_CTX_set_options(m_ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
But I don't know any way to achieve (2). Is there any "elegant" way to do this in OpenSSL or do I have to attempt several connections checking if communication was possible and, if not, attempt a lower protocol version?
Thanks.
There is no protocol priority setting. The client will announce the best version it can do to the server and the server will pick this or a lower version. If the version picked by the server is not supported by the client then the handshake will fail. This is not specific to OpenSSL but this is how SSL/TLS works.
Don't confuse this handshake between client and server with the TLS downgrading mechanism most browsers use. In this case browsers retry the SSL handshake on a new TCP connection with a lower version if the handshake with the better version failed. This behavior is to work around broken SSL/TLS implementations. These downgrades are mostly restricted to browsers, simpler TLS stacks are less tolerant and fail permanently if the first handshake failed.