During handshake of TLS connection where does the client fetch the list of cipher suites from? - ssl

From where does the client fetches the list of cipher suites that it is going to propose to server?
For example, it looks like that on same machine, clients of two different applications can propose the different list of cipher suits.
To limit the scope of question, I want to understand it for RabbitMQ Client and TLS1.2.
More clarification
So I have RabbitMQ service installed on my machine and then in C# code I try to connect (Ex. var connection = factory.CreateConnection()) to it without any cipher suits configuration.
So here my C# application could be considered as Client.
please note that I am asking about the ciphers that client sends in 'Client Hello' message.
P.S. somewhere I read that rabbitmq internally uses openssl, so when I ran the command 'openssl ciphers -s -tls1_2' I got a list that is different when I see rabbitmq client hello's cipher suits in wireshark. Also I don't have any group policy on machine that overrides the ciphers.

See https://tls13.ulfheim.net/ for a nice graphical representation of a TLS 1.3 exchange.
In the second message, ClientHello, the client gives among other things a list of ciphers it supports. Where it gets it? Either hard-coded in the application or computed dynamically once decided to connect, etc. this all depends on the application, so you need to investigate its code source/its configuration.
If you take for example openssl s_client as TLS client, you have -cipher and -ciphersuites configuration options to specify which specific ciphers to announce when connecting.
If you look later in the exchange, there is a ServerHello where the server announces which cipher suite will be used.
How that happens? Typically, the server has its own list of preferred ciphers ordered by "quality" (cryptographic strength like preferring 256bits over 128bits and/or other properties like preferring PFS over non PFS), and based on what it got from the client, it tries to select the "best" one that is supported on both side, which is not necessarily always possible.
Now as you put in comments a specific application (Google Chrome), you can see at https://source.chromium.org/chromium/chromium/src/+/main:third_party/boringssl/src/ssl/ssl_cipher.cc;l=1152?q=cipher&ss=chromium%2Fchromium%2Fsrc the definition of a function called "ssl_create_cipher_list" whose goal is to build the cipher list, starting from all compiled ones, and then applying various rules to enable/disable some and sorting them in an order that makes sense. This is of course highly dependent on the application for how it is done, but you can certainly find similar operations in other toolkits.
Finally, do note that there is a big difference between TLS 1.2 (ciphers) and TLS 1.3 (ciphersuites). They are disjoint sets, and when TLS 1.2 has "myriad" of ciphers in the wild (see for example https://www.openssl.org/docs/man1.1.1/man1/ciphers.html for lots of them), TLS 1.3 defines only 5 ciphersuites (see https://datatracker.ietf.org/doc/html/rfc8446#appendix-B.4) with one being mandatory to implement, so the whole question of auto-negotiation between client and server becomes almost moot.
As you mention explicitly tls1.2 as tag, do note there is no real reason today not to use 1.3 instead (which is why my first link is on purpose specially for 1.3 - the handshake routine is different in 1.2 but identical for things related to your question of ciphers), you will gain a lot of benefits, from simplified operations, better cryptography all around, and fewer holes.

Related

How long is an established SSL connection valid?

Suppose I am sending "hello" to an api over ssl. My understanding is there would be a symmetric key exchange established over ssl and then the message "hello" will be encrypted using that symmetric key and sent over to the other server.
Now my question is, the next time I send a "hello 2", does the symmetric key exchange happen again? My guess would be that if it's a persistent connection, there would be no need for the key exchange again. Can someone confirm?
Meta: this doesn't appear to me to be programming, although it might be development and is mostly dupe How long does SSL connection between a client and a server persist? .
It depends on the application protocol used on top of SSL (which since 1999 is really TLS, although many things e.g. implementation classes still use the old name) and usually the implementations at both ends. For example, HTTP/1.1 defaults to connection persistence (which was often done in 1.0 as an extension called keep-alive), but either endpoint can change this by specifying connection: close, and even if the connection is kept open can choose to close it anytime later, perhaps after a minute or two, perhaps after a day or a week. The HTTPS implementation in browsers usually keeps connections open for a little while but has limits on the total connections open so those that haven't been used recently may need to be closed when others are opened. Other applications, libraries, and platforms vary. Other protocols also vary; for example an email agent using SMTPS would normally make a connection, transmit one or more emails, and then disconnect.
In addition, SSL-now-TLS through 1.2 supports session resumption, which allows the keyexchange (and other handshake results) performed on one connection to be saved (at both endpoints, or with the 'ticket' option, at client only) and reused on a new connection, for as long as the endpoint(s) agree; implementations usually call this session caching. See e.g. RFC 5246 section 7.3 specifically the part starting in the middle of page 36, and for one fairly common server (Apache) see SessionCache and SessionCacheTimeout directives. Resumption uses a new handshake but not a full keyexchange on that handshake.
However, this creates a security vulnerability if an endpoint's sesssion cache is compromised, so TLS 1.3 replaces it with a different method using dynamically created PSKs; see RFC 8446 section 2.2. This allows either a partial handshake (doing the actual keyexchange with [EC]DHE but authentication tied to the previous session by the PSK rather than full certificate-based authentication) which provides forward secrecy, or a minimal handshake (using the PSK both as the new initial secret and for authentication) which does not.
If you want an answer for specific software, and specific server(s), you need to look at the capabilities and configuration, and often also the current status, of that software and those server(s).

Different communicating patterns in TLS 1.2

I used Wireshark to monitor packages of some websites, but found that there are such many communicating patterns of TLS 1.2.
The first one is a generic one:
Client: Client Hello
Server: Server Hello, Certificate, Server Hello Done
Client: Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
Server: Change Cipher Spec, Encrypted Handshake Message
Second one is as followed:
Wireshark1
I'm just confused with why Certificate and Server Hello Done was in another package. Who demand server to do that? For what reasons?
After multiply refreshing page, I got the third one:
Wireshark2
Only 3 packages in handshake? A lot of processes were missed, was it because the information was cached? And how about the pre-master key?
Thanks for the answering!
TLS is a protocol over TCP, i.e. over a streaming transport protocol. For transport the data stream gets split into packets and thus it can happen that the ServerHelloDone is contained in one packet or in another or even split over two packets. Since the sizes are visible in your second example but not in the first it is unknown why the difference is exactly but it might be caused by the size of the certificate(s) contained in the handshake.
As for the third example: this is simple a TLS session reuse, i.e. it continues an older session and thus no sending of server certificate or similar is needed.

How to enable TLS Renegotiation in Tomcat?

I want to enable SSL keys renegotiation in Tomcat as described in https://www.rfc-editor.org/rfc/rfc5746. Tomcat will use JSSE implementation for SSL. Which cipher suite should I use to enable the same?
Tomcat Version: 6.0.44
Java version: Java 1.8
Protocol - TLS 1.2
Meta: I'm not sure this is ontopic here, but security is on-hold. Migrate if necessary.
All Java 8 and 7, and 6 from 6u22 up, enable secure renegotiation per 5746. See the documentation. By default, it is used if the peer offers or accepts it; if the peer does not, the connection is still made but renegotiation is not done because it would/could be insecure. This can be varied two ways:
set system property sun.security.ssl.allowLegacyHelloMessages false. JSSE will not make the connection if the peer does not agree to 5746. This is not actually more secure, but it is more visibly secure to simple minded basic scanners, and people who care about simple minded basic scanners like auditors
set system property sun.security.ssl.allowUnsafeRenegotiation true. This is less secure if the application depends on peer credentials checked after a message. Since client always checks server before any data, this means if server requests (not requires) client authentication, and checks auth status after a request, it can wrongly accept a forged-prefix request.
The protocol implementation of 5746 sometimes uses a fake "ciphersuite" (officially SCSV -- Signalling Cipher Suite Value) in ClientHello. JSSE client can be configured using the "ciphersuite" name TLS_EMPTY_RENEGOTIATION_INFO_SCSV whether to use this SCSV or the extension. All servers always use the extension, and thus this configuration has no effect on JSSE server.

Can I detect the SSL version that a browser supports?

I would like to display a message to customers who's browser's highest level of encryption is SSLv3. Is it possible for me to target browser settings of SSLv3 and lower? Client or Server code? We will be allowing lower versions of SSL to use our site during a certain grace period. During this grace period, we would like to display a message only to those users that have browser settings of SSL3 or lower.
Not easily. The browser's supported SSL versions are not detectable until the SSL handshake is in progress, and even then only if the browser uses an SSLv2 handshake to allow dynamic version negotiation. If an unsupported version were detected, you would not be able to send a message back since the handshake failed and the connection would be closed before you could send any message. However, SSL itself has an error packet that gets sent during handshaking, and it can specify a version mismatch error.
The best you can do in your own code is support all SSL versions on the server side, let the client complete a handshake normally, and then detect which version was actually used and send back a message if the SSL version is too low.
Or, you could simply enable TLSv1 or higher only, and simply refuse to let older clients connect at all. They just would not get a nice error message unless the browser decided to detect the SSL version mismatch error and display its own pretty message about it.
Firstly, nowadays, you can generally forget about clients that don't support at least SSLv3. SSLv3 has been widely available for many years.
The TLS Client Hello message, sent when the connection is initiated by the browser, should contain the highest TLS version it supports:
client_version
The version of the TLS protocol by which the client wishes to
communicate during this session. This SHOULD be the latest
(highest valued) version supported by the client. For this
version of the specification, the version will be 3.3 (see
Appendix E for details about backward compatibility).
Appendix E is of course worth looking at.
(The Client Hello message will also contain the list of cipher suites the client supports, which is possibly relevant for the general idea of your question.)
Of course, this specification is just a "SHOULD", so a client supporting TLS 1.2 could still send a Client Hello for TLS 1.1, but what would be the point? By doing so it would have no chance ever to use TLS 1.2 anyway. It could be a preference box that is turned off, but that would effectively make it a client that doesn't support the highest version anyway. (If you want anything more subtle, you'd need to build a database of known user agents, which will be partly unreliable, and for which you'd need to analyse the full user agent string to know everything possible about the platform.)
Now, how to convey the content of the Client Hello message to your application is another matter, and depends very much on which SSL/TLS stack you use. It might not even be directly possible without modifying that SSL/TLS library or the server you're using.
This being said, you can generally get the negotiated TLS version during the current session quite easily. Since that version is the "lower of that suggested by the client in the client hello and the highest supported by the server" (i.e. "min(max(client), max(server))"). If your server supports SSLv3, TLS 1.0, TLS 1.1 and TLS 1.2, and since the latest version is TLS 1.2 anyway, what you'll get during your current connection will also be the max currently supported by the client. As long as your server supports the latest version, you should be able to know what the client supports at best from any live connection.
If you're behind Apache HTTP server's mod_ssl, you should be able to get that from the SSL_PROTOCOL environment variable. You should also be able to get the protocol from the SSLSession in Java.
(If you are willing to write a more bespoke service, you could pass further details like the cipher suites more directly to your application, like this service from Qualys SSL Labs does, although I'm not sure if it's meant to be widely available or just a test service.)
I'd have to agree with Remy about it being a bit challenging.
However, a good starting point may be to retrieve some SSL (certificate) information.
Something similar to this:
X509Certificate certChain[] =
(X509Certificate[]) req.getAttribute("javax.net.ssl.peer_certificates");
Another way of getting more information is to retrieve the cipher_suite attribute (similar to the code snippet above).
javax.net.ssl.cipher_suite
I hope this (at least) gets you closer.
Good luck.

In mono, how to control the SSL/TLS cipher suite?

I would like to configure the server to refuse negotation of DES, RC4, MD5, etc. The mono 3.4 release notes say "Network Stack Now allows developers to control which cipher suites to use with TLS/SSL." ... But how?
(Thanks to Sebastien Pouliot for this answer)
You can set a callback for either ClientCipherSuitesCallback or ServerCipherSuitesCallback SSL/TLS. That will allow you to control which ciphers can be used and the selection order (in general most server select the first cipher suites they support).
Sample code is part of the documentation.
And also, since it will likely be difficult for some people to find the valid enumerations, see CipherSuiteFactory.cs