SecureBlackbox 16: Fine-Tuning the SSL Components
SSL/TLS is a complex multilayer protocol that relies on a variety of state-of-the-art cryptographic techniques. SSL by design hides much of this complexity, yet the very same simplicity often results in crucial settings of the SSL endpoints being ignored, overlooked, or configured incorrectly. Below, we will consider the most important factors that should be taken into account when configuring your SSL endpoint. These hints are equally applicable to SecureBlackbox-driven and third-party SSL implementations.
The article is split into two general sections: configuring your client-side SSL implementation and configuring your server.
Overview of SSL
Five versions of the protocol have been defined so far: SSL 2.0, SSL 3.0, TLS 1.0, TLS 1.1, and TLS 1.2. SSL 2.0 is derelict, old, and insecure and must not be used. SSL 3.0 is far better security-wise, but is also quite old and should only be used if you have serious reasons to do so, e.g., if you need to communicate with old and out-of-date SSL hardware. TLS 1.0 can be used with care, and TLS 1.2 is the recommended version. TLS 1.1 appeared halfway between TLS 1.0 and TLS 1.2; there are no specific reasons to use this particular version as it was fairly quickly superseded by TLS 1.2. We will only discuss TLS 1.0-1.2 below.
The security parameters of a particular connection are defined by a cipher suite - a combination of four cryptographic algorithms: the data encryption algorithm, key exchange algorithm, server authentication algorithm, and MAC algorithm. For example, the DHE- RSA-AES128-SHA cipher suite specifies the key exchange algorithm of DHE, server authentication algorithm of RSA, data encryption algorithm of AES128, and MAC algorithm of SHA(1) . More than a hundred different cipher suites are defined, offering different protection strengths. The cipher suite to be used during a particular session is selected by the server from a list offered by the client.
SSL specifies mandatory authentication of the server and optional authentication of the client. Authentication is based on public key cryptography and relies on X.509 certificates as key and identity information containers. Every authenticated party must thus have a valid X.509 certificate and a key pair associated with it.
Now that we know enough about the protocol, we can proceed to the main points of the article.
Content
- Configuring your client-side SSL implementation
- Configuring SSL versions
- Cipher suites
- Certificate validation
- Client certificates
- Renegotiation
- Miscellaneous
- Configuring your server-side SSL implementation
Configuring your client-side SSL implementation
The following sections lay out the configuration procedure in general and provide specifics on configuration with the SecureBlackbox components:
Configuring the SSL Version
Switch off SSL 2.0 and SSL 3.0, thus only leaving TLS 1.0, TLS 1.1, and TLS 1.2 enabled. With SecureBlackbox this can be done in the following way:
Client.Versions := [sbTLS1, sbTLS11, sbTLS12];
or
Client.Versions = SBSSLConstants.Unit.sbTLS1 | SBSSLConstants.Unit.sbTLS11 | SBSSLConstants.Unit.sbTLS12;
Cipher suites
While SecureBlackbox supports the majority of cipher suites ever defined for the SSL protocol, an average client application rarely needs to support all of them: There are certain cipher suites that provide an inadequate protection level. Other cipher suites are only usable in specific configurations (such as DH-, SRP-, or PSK-driven) and require special configuration. We recommend unconditionally disabling cipher suites that contain 'NULL', 'ANON', EXPORT', and 'DES' in their names. It is very likely that cipher suites with 'PSK' and 'SRP' suffixes can also be disabled without affecting the functionality of your application. The minimal list of cipher suites to support, which provides maximal compatibility, is given below:
Cipher suite |
Certificate type |
Comments |
SB_SUITE_RSA_AES128_SHA |
RSA |
A mandatory cipher suite required by the TLS specification (RFC 5246) |
SB_SUITE_RSA_AES256_SHA |
RSA |
|
SB_SUITE_DHE_RSA_AES128_SHA |
RSA |
Supports perfect forward secrecy (PFS) |
SB_SUITE_DHE_RSA_AES256_SHA |
RSA |
Supports PFS |
SB_SUITE_DHE_DSS_AES128_SHA |
DSA |
Supports PFS |
SB_SUITE_DHE_DSS_AES256_SHA |
DSA |
Supports PFS |
SB_SUITE_ECDH_ECDSA_AES128_SHA |
ECDSA |
|
SB_SUITE_ECDH_ECDSA_AES256_SHA |
ECDSA |
|
SB_SUITE_ECDHE_ECDSA_AES128_SHA |
ECDSA |
Supports PFS |
SB_SUITE_ECDHE_ECDSA_AES256_SHA |
ECDSA |
Supports PFS |
SB_SUITE_ECDH_RSA_AES128_SHA |
RSA |
|
SB_SUITE_ECDH_RSA_AES256_SHA |
RSA |
|
SB_SUITE_ECDHE_RSA_AES128_SHA |
RSA |
Supports PFS |
SB_SUITE_ECDHE_RSA_AES256_SHA |
RSA |
Supports PFS |
SB_SUITE_RSA_AES128_SHA256 |
RSA |
|
SB_SUITE_RSA_AES256_SHA256 |
RSA |
|
SB_SUITE_DHE_DSS_AES128_SHA256 |
DSA |
Supports PFS |
SB_SUITE_DHE_RSA_AES128_SHA256 |
RSA |
Supports PFS |
SB_SUITE_DHE_DSS_AES256_SHA256 |
DSA |
Supports PFS |
SB_SUITE_DHE_RSA_AES256_SHA256 |
RSA |
Supports PFS |
SB_SUITE_RSA_AES128_GCM_SHA256 |
RSA |
|
SB_SUITE_RSA_AES256_GCM_SHA384 |
RSA |
|
SB_SUITE_DHE_RSA_AES128_GCM_SHA256 |
RSA |
Supports PFS |
SB_SUITE_DHE_RSA_AES256_GCM_SHA384 |
RSA |
Supports PFS |
SB_SUITE_DHE_DSS_AES128_GCM_SHA256 |
DSA |
Supports PFS |
SB_SUITE_DHE_DSS_AES256_GCM_SHA384 |
DSA |
Supports PFS |
SB_SUITE_ECDHE_ECDSA_AES128_SHA256 |
ECDSA |
Supports PFS |
SB_SUITE_ECDHE_ECDSA_AES256_SHA384 |
ECDSA |
Supports PFS |
SB_SUITE_ECDH_ECDSA_AES128_SHA256 |
ECDSA |
|
SB_SUITE_ECDH_ECDSA_AES256_SHA384 |
ECDSA |
|
SB_SUITE_ECDHE_RSA_AES128_SHA256 |
RSA |
Supports PFS |
SB_SUITE_ECDHE_RSA_AES256_SHA384 |
RSA |
Supports PFS |
SB_SUITE_ECDH_RSA_AES128_SHA256 |
RSA |
|
SB_SUITE_ECDH_RSA_AES256_SHA384 |
RSA |
|
SB_SUITE_ECDHE_ECDSA_AES128_GCM_SHA256 |
ECDSA |
Supports PFS |
SB_SUITE_ECDHE_ECDSA_AES256_GCM_SHA384 |
ECDSA |
Supports PFS |
SB_SUITE_ECDH_ECDSA_AES128_GCM_SHA256 |
ECDSA |
|
SB_SUITE_ECDH_ECDSA_AES256_GCM_SHA384 |
ECDSA |
|
SB_SUITE_ECDHE_RSA_AES128_GCM_SHA256 |
RSA |
Supports PFS |
SB_SUITE_ECDHE_RSA_AES256_GCM_SHA384 |
RSA |
Supports PFS |
SB_SUITE_ECDH_RSA_AES128_GCM_SHA256 |
RSA |
|
SB_SUITE_ECDH_RSA_AES256_GCM_SHA384 |
RSA |
|
Cipher suites can be enabled and disabled with the following code:
// Disabling all cipher suites for I := SB_SUITE_FIRST to SB_SUITE_LAST do Client.CipherSuites[I] := false; // Enabling the DHE-RSA-AES256-SHA cipher Client.CipherSuites[SB_SUITE_DHE_RSA_AES256_SHA] := true;
or
// Disabling all cipher suites for (int i = SBSSLConstants.Unit.SB_SUITE_FIRST; i <= SBSSLConstants.Unit.SB_SUITE_LAST; i++) { client.set_CipherSuites(i, false); } // Enabling the DHE-RSA-AES256-SHA cipher client.set_CipherSuites(SBSSLConstants.Unit.SB_SUITE_DHE_RSA_AES256_SHA, true);
Certificate validation
This section shows how to configure server certificate validation, one of the most important aspects of the SSL client configuration. Improper or missing certificate validation procedures compromise the security of the negotiated secure connection.
The main goal of certificate validation is to establish the genuineness of the entity that provided the certificate. While the protocol itself does perform certain checks for you -- in particular it verifies that the presenter of the certificate has access to the corresponding private key -- certain checks are outside the scope of the protocol. They should be performed externally in accordance with local security policy. In a typical scenario of a client connecting to a broad range of publicly accessible servers, the client must ensure that the certificate's Common Name attribute references the correct domain name or IP address. It is also important to verify that the certificate was issued, either directly or indirectly, by a trusted certification authority (CA) and is appropriate for use as an SSL certificate.
SecureBlackbox provides a unified way to validate server SSL certificates suitable in the majority of typical client-server scenarios. Certificate validation should be performed inside the OnCertificateValidate event handler, and the validation result has to be returned back to the component via the Valid parameter of the event. Note that OnCertificateValidate may be thrown several times per connection, for each certificate returned by the server, including the CA and root certificates. The certificates are passed to the user in order from the root or CA certificate down to the server's end entity certificate. This feature is reflected in the code snippet below.
if (Certificate.Chain = nil) or Certificate.Chain.Certificates[0].Equals(Certificate) then begin // Certificate contains the end-entity certificate of the server: // performing chain validation CertificateValidator.ValidateForSSL(Certificate, Client.RemoteHost, Client.RemoteIP, hrServer, ChainCerts, true, false, UTCNow, Validity, Reason); Valid := Validity = cvOk; end else begin // Certificate contains an intermediate CA or root certificate: // caching it in ChainCerts storage for later use ChainCerts.Add(Certificate); Valid := true; end;
or
if ((certificate.Chain == null) || (certificate.Chain.get_Certificates(0).Equals(certificate))) { // certificate contains the end-entity certificate of the server: // performing chain validation certificateValidator.ValidateForSSL(certificate, client.RemoteHost, client.RemoteIP, TSBHostRole.hrServer, chainCerts, true, false, SBUtils.Unit.UTCNow(), ref validity, ref reason); valid = (validity == TSBCertificateValidity.cvOk); } else { // certificate contains an intermediate CA or root certificate: // caching it in ChainCerts storage for later use chainCerts.Add(certificate); valid = true; }
Client certificates
While not being a typical scenario for the web, client authentication is often used in intranets or restricted areas of public web sites to control user access.
The most important task in this scenario is to store your private key securely, as everyone who gains access to your private key can impersonate you before the server, and access it on your behalf. There are significant security concerns with keeping your private keys in files, even password-protected; consider using secure storages provided by the operating environment instead. This could be a hardware security device or (a cheaper solution) a Windows system store. The Windows CryptoAPI is capable of providing adequate software protection facilities for your private keys.
To configure the component to use your client SSL certificate, load the certificate into a TElMemoryCertStorage instance and assign the storage object to the ClientCertStorage property of your client-side SSL component.
Depending on the specifics of your environment, the server might be using PKI procedures when validating your certificate. In certain cases, it might require you to send not only your end-entity certificate, but also the entire chain up to the root certificate. With SecureBlackbox you can force the component to send the entire chain by putting all the certificates comprising it into the ClientCertStorage storage.
Renegotiation
In Autumn 2009 a serious flaw in the TLS protocol was discovered. The flaw has been given a nickname of 'renegotiation vulnerability' or 'renegotiation attack' due to the technique of the protocol used to exploit the flaw (secure renegotiation of the established key material). In short, a secure TLS conversation could be tampered with by an active adversary during session renegotiation due to a flaw in the renegotiation protocol. More details about the matter are available here.
Following the discovery of the flaw, the standard was revised and appropriate measures were put in place to get rid of the flaw. A new protocol extension was introduced to allow compatible clients and servers to renegotiate securely. Security software vendors were strongly advised to implement the workaround in their software.
Unfortunately, the only way to work around the vulnerability was to introduce changes to the protocol. As a result, older software that could not be updated (mostly, hardware clients and servers) still can be occasionally found on the market.
The SecureBlackbox components support three modes of operation with regard to the renegotiation problem (compatible/insecure, strictly secure, and automatic), which can be set via the RenegotiationAttackPreventionMode property. A new OnRenegotiationRequest event can also be used to reject the server's requests for renegotiation.
Please also note that following the discovery of the vulnerability, many SSL servers now reject renegotiation requests issued by clients. This may cause the OnError event to fire, with a nonfatal ERROR_SSL_NO_RENEGOTIATION error shortly after the RenegotiateCiphers call. A good practice for SSL clients is to refrain from initiating session renegotiations at all.
Miscellaneous
On shared hosting, SSL clients need to pass to the server the exact domain name they are connecting to so that the server can pick the appropriate certificate for the resource. This is achieved via the Server Name Indication extension to the TLS protocol. Remember to enable this extension to make your client-side SSL implementation work correctly with shared hosting services. Higher-level classes of SecureBlackbox 12 onwards, such as TElSimpleSSLClient, are capable of setting this extension automatically, provided that the ssloAutoAddServerNameExtension flag is included in the Options flag set of the component.
Other protocol extensions may be used to fine-tune the way in which SSL connection is negotiated. For instance, the client can use extensions to specify the algorithms it supports or prefers, set the maximal size of SSL packets, and set a variety of other communication parameters.
Configuring your server-side SSL implementation
Configuring a server may be substantially more complex than configuring a client, primarily due to the need to support a plethora of different client implementations. A requirement to accept older clients might reduce the level of security provided by the server, so the necessity of supporting every particular weak version or cipher suite should be carefully assessed.
Versions
It is recommended to avoid using SSL 2.0 and SSL 3.0 versions wherever possible and use TLS 1.0, TLS 1.1, and TLS 1.2. You can configure SecureBlackbox to use TLS 1.0, TLS 1.1, and TLS 1.2 with the following code:
Server.Versions := [sbTLS1, sbTLS11, sbTLS12];
or
server.Versions = SBSSLConstants.Unit.sbTLS1 | SBSSLConstants.Unit.sbTLS11 | SBSSLConstants.Unit.sbTLS12;
Cipher suites
We strongly recommend that only safe cipher suites given in the list above are activated. Yet, it is often not desirable / not achievable to narrow down the set of cipher suites supported by the server for compatibility reasons. In this case, we recommend a combined solution, which involves disabling all weaker cipher suites (those containing 'NULL', 'ANON', 'EXPORT' or 'DES' in their names) and arranging proper priorities for the others. It makes sense to assign higher priorities to stronger cipher suites (those providing perfect forward secrecy or designed on AES256 and/or SHA256 algorithms), and lower priorities to less secure ciphers (like RC4 and 3DES). Priorities can be assigned via the CipherSuitePriorities property. The server will then use the prioritized cipher suite list to choose the most secure one among those offered by the client.
Note: For a cipher suite to be usable by the server, the latter must have a certificate of the appropriate type assigned. For example, the SB_SUITE_RSA_AES256_SHA suite requires an RSA certificate to be available, and the SB_SUITE_ECDHE_ECDSA_AES256_SHA suite relies on a certificate with an ECDSA key. If a certificate of an appropriate type is not available, the server will not be able to use cipher suites relying on that type of certificate.
Example
The following example code shows how to configure cipher suites according to the recommendations above.
// Disabling all cipher suites for I := SB_SUITE_FIRST to SB_SUITE_LAST do Server.CipherSuites[I] := false; // Enabling the DHE-RSA-AES128-SHA and DHE-RSA-AES256-SHA ciphers Server.CipherSuites[SB_SUITE_DHE_RSA_AES128_SHA] := true; Server.CipherSuites[SB_SUITE_DHE_RSA_AES256_SHA] := true; // Assigning a higher priority to the AES256-based cipher Server.CipherSuitePriorities[SB_SUITE_DHE_RSA_AES128_SHA] := 50; Server.CipherSuitePriorities[SB_SUITE_DHE_RSA_AES256_SHA] := 100;
or
// Disabling all cipher suites for (int i = SBSSLConstants.Unit.SB_SUITE_FIRST; i <= SBSSLConstants.Unit.SB_SUITE_LAST; i++) { client.set_CipherSuites(i, false); } // Enabling the DHE-RSA-AES128-SHA and DHE-RSA-AES256-SHA ciphers client.set_CipherSuites(SBSSLConstants.Unit.SB_SUITE_DHE_RSA_AES128_SHA, true); client.set_CipherSuites(SBSSLConstants.Unit.SB_SUITE_DHE_RSA_AES256_SHA, true); // Assigning a higher priority to AES256-based ciphers Client.set_CipherSuitePriorities(SBSSLConstants.Unit.SB_SUITE_DHE_RSA_AES128_SHA, 50); Client.set_CipherSuitePriorities(SBSSLConstants.Unit.SB_SUITE_DHE_RSA_AES256_SHA, 100);
Server certificates
The server certificate is one of the key factors that affect the security of all SSL connections negotiated by the server. Improper certificate management procedures might compromise the security of the entire environment. All too often, a security flaw caused by mishandling of a server certificate goes unnoticed until it is too late.
The private key associated with the certificate should be kept safe. The recommended option is to use a cryptographic hardware device for storing the key. Alternatively, protected areas of the operating environment (e.g., CryptoAPI certificate stores) may be used. In either case, the key should be imported to its permanent place of storage with a nonexportability option.
If you became an unlucky victim of private key theft, or if you are just suspecting that the key might have been accessed by a third party, report the key loss to the CA immediately. Stop the server until you receive the replacement certificate and key.
In order for your server certificate to be validated correctly by the clients, they will often need to have the entire chain of certificates from your server's end-entity certificate up to the root CA certificate available. A chain typically consists of three or four certificates: the server's certificate, one or two intermediate CA certificates, and an explicitly trusted root certificate. Major CAs have their root and CA certificates included in the distributions of popular operating systems and can be easily retrieved should the client need to validate the chain they are part of. The others only ship the root certificate, which means that the intermediate certificates have to be provided by other means. This is why a good practice for an SSL server is to send the entire certificate chain to its clients. In case a client doesn't have intermediate certificates locally, it can use certificates provided by the server to reconstruct the chain.
To configure a SecureBlackbox-driven SSL server to send out the entire chain, put all the certificates comprising the chain into the certificate storage component assigned to the CertStorage property of the server, and then set the ForceCertificateChain property to true. The server will then complete the process.
Client authentication and certificates
Client authentication is optional and is typically used for identifying or authorizing clients and restricting access to certain protected areas of the web site. A typical validation of a client certificate therefore involves two major steps: (1) recognizing the certificate owner and acquiring their access rights details from a local user database, and (2) checking certificate integrity and validity. While the first step is outside the scope of SSL, the second step should be performed within the SSL module. Depending on the specifics of the environment, different validation approaches can be used. In the simplest case, the certificate received from the client is compared to its original copy stored locally. More complicated scenarios involve the use of certificate chains and full-fledged PKI procedures.
The SecureBlackbox server components return user certificates via the OnCertificateValidate event. It is the task of the user to perform the validation and return its outcome via the Valid parameter of the event. Switch the ClientAuthentication property on to make the server request a certificate from the client. The AuthenticationLevel property controls whether the server should require the certificate (and close the connection if the certificate was not provided) or request it.
Note that server and client authentication are completely independent to each other. The peers are not required to use the same approach for client- and server-side validation; neither are they required to use certificates from the same CA or to hold keys of the same type.
Session pooling
Session pooling is a convenient protocol mechanism most effective in environments where the same client needs to establish multiple secure connections to the same server. For multichannel scenarios SSL specifies a technique known as an abbreviated handshake, which ultimately reduces the number of cryptographic operations the peers need to perform for every new negotiation. Only the first negotiation is performed in full; encryption keys for all subsequent negotiations are simply cloned from that of the first connection.
In order to support abbreviated handshakes the server needs to maintain a persistent database of negotiated SSL connections. In SecureBlackbox such a database is implemented in the TElSessionPool class. A single instance of the TElSessionPool class should be shared among all SSL server objects (e.g., TElSSLServer) to propagate database information to them.
Renegotiation
SecureBlackbox server components throw the OnRenegotiationStart event, which alerts the developer to a renegotiation initiated by the client and whether it is safe (protected from the renegotiation issue). The event also allows the developer to cancel the renegotiation if they are unhappy with it.
Note that in most cases the client does not need to initiate session renegotiation, so disallowing client-originated renegotiations completely might make sense.
Handling errors
The complexity of the SSL protocol and its dependency on external certificate validation routines might occasionally lead to negotiation failures. Properly implemented error handling procedures will serve you well in troubleshooting.
The SecureBlackbox SSL components report errors via the OnError event (and in certain cases the OnSSLError event).The event passes three parameters to the developer: ErrorCode reports an identifier of the error, Fatal tells whether the error is a show-stopper for the current session, and Remote specifies whether it was the local or remote side which recognized and reported the error. It is a good idea to keep track of all invocations of the OnError event, as this may simplify the task of pinpointing the underlying reasons and speed up the investigation.
Error code |
Reason and steps to take |
ERROR_SSL_UNEXPECTED_MESSAGE |
A connection is made to/from a service that failed to meet the requirements proper SSL (e.g. a plain HTTP connection is made to an HTTPS port). Re-check that both client and server services are talking SSL. Unsupported version of the protocol. Try changing the Versions property of the SSL component. |
ERROR_SSL_BAD_RECORD_MAC, ERROR_SSL_DECRYPTION_FAILED, ERROR_SSL_DECODE_ERROR, ERROR_SSL_DECRYPT_ERROR
|
The peers failed to negotiate the shared key material. Try connecting with different cipher suites one by one. If neither does, try using a different protocol version. |
ERROR_SSL_RECORD_OVERFLOW |
Packet size too large. Try to decrease the maximal size of the packet by adjusting the MaxFragmentLength extension. |
ERROR_SSL_DECOMPRESSION_FAILURE |
Compression or decompression failure. Switch off compression with the CompressionAlgorithms property. |
ERROR_SSL_HANDSHAKE_FAILURE, ERROR_SSL_ILLEGAL_PARAMETER
|
Incompatible versions or cipher suite lists. Try changing the version and cipher suite sets. Check that the server certificate is provided and has an associated private key. |
ERROR_SSL_NO_CERTIFICATE, ERROR_SSL_BAD_CERTIFICATE, ERROR_SSL_UNSUPPORTED_CERTIFICATE, ERROR_SSL_CERTIFICATE_REVOKED, ERROR_SSL_CERTIFICATE_EXPIRED, ERROR_SSL_CERTIFICATE_UNKNOWN, ERROR_SSL_UNKNOWN_CA |
The certificate provided by the peer is not valid. |
ERROR_SSL_ACCESS_DENIED |
The requested application-layer resource cannot be accessed by the requestor. Check with the administrator of the remote resource. |
ERROR_SSL_EXPORT_RESTRICTION |
The peer is only configured to use exportable cipher suites. Switch on support for 'EXPORT' cipher suites. |
ERROR_SSL_PROTOCOL_VERSION |
|
ERROR_SSL_INSUFFICIENT_SECURITY |
|
ERROR_SSL_INTERNAL_ERROR |
|
ERROR_SSL_USER_CANCELED |
|
ERROR_SSL_NO_RENEGOTIATION |
|
ERROR_SSL_CLOSE_NOTIFY |
An SSL connection was closed gracefully and can be restored or cloned in future. This is actually a notification, not an error. |
Synchronous SSL-capable components, such as TElHTTPSClient, also use exceptions to report protocol issues. These should also be taken into account when investigating a problem. Please note that the issue mentioned in the exception might serve either as a reason or as a consequence of an SSL-layer problem.
Security is more process than pluggable. You should always keep monitoring your operating environment as a whole to be sure that every part of the environment is protected appropriately.
We appreciate your feedback. If you have any questions, comments, or suggestions about this article please contact our support team at support@nsoftware.com.