TLS is an Internet RFC (now at version 1.2) describing how to secure HTTP connections between clients and servers. It addresses two key issues: Authentication and Encryption.
TLS is an enhancement of SSL, previously created by Netscape for its browser. You can see the progression of it through these different versions:
- Transport Layer Security Version 1.2 (the current version)
- Transport Layer Security Version 1.1
- Transport Layer Security Version 1.0 (the IHE ATNA version, also known as SSL 3.1)
- Secure Sockets Layer Version 3.0
- Secure Sockets Layer Version 2.0
Use of TLS 1.0 is what is specified in the IHE ATNA Profile, and what is most widely available in computer products and platforms. TLS 1.0 with the necessary encryption protocol (AES 128) is supported on:
- Windows Version 7 and later products, as well as Windows Server 2003 (SP2) and later. If you have Windows XP, and are using .Net, you will need to upgrade [and no, Vista is not considered to be an upgrade ;-)].
- Java Release 1.4 and greater.
- IOS 4 and 5 (I'm told that IOS uses openSSL)
AuthenticationThe authentication layer is based upon X.509 certificates. Systems that want to prove that they are who they say they are use the private key associated with their certificate to encrypt data that can only be known to both parties. The ability of the receiver of the encrypted data to decrypt that data using the public key allows that receiver to be certain that the sender knows the encryption key (and is therefore highly likely to be the owner of the certificate because only the owner of the certificate should have that key).
Building certificates and creating stores is a common challenge for users. Fortunately, for those testing in connectathon, this is often done for you. When you need to deploy, I've put together some instructions for how to do this using freely available tools from openSSL.
Encryption between the two communicating systems is accomplished by agreeing on an encryption key, which is shared between the client and server in a block of information that is encrypted using a public key encryption method (very secure, but slow). That encryption key is then used in a faster cipher mechanism to encrypt the communications.
Debugging The Protocol
Microsoft has a great article that describes how the TLS protocol works in detail. You might also consider reading the IHE ATNA FAQ if you haven't already. The key to getting TLS right for connectathon is correct configuration. You want to support ONLY TLS Version 1.0, only using AES-128 encryption, and if your system is the server, to require client certificates. Configuring your system to user other versions of TLS or SSL, or other encryption suites is a common way to fail. Another source of failure is incorrect set up of your trust and key stores.
First, some important definitions:
- A certificate is a blob of data that identifies a server or client. It's structure is defined by the X.509 standand. It contains some information identifying the system, and includes the public encryption key associated with that system. A certificate is signed by a signer which may be the original system (a self-signed certificate), or another entity.
- Certificate Chain
- A certificate chain refers to the collection of certificates which identifies the certificate for a system, and includes the certificate for the signer of that certificate, and its signer, recursively until you reach a "root" level certificate. When a certificate is sent from one system to another, it is usually sent with the chain of signers.
- Key Store
- A key store is a place where a systems certificate and private encryption key are stored. It is used by clients and servers to locate the certificate used to identify the system, and to obtain the private encryption key to encrypt/decrypt certain messages in the TLS protocol (usually the shared session key). If your key store doesn't contain your encryption key, the certificates in it won't help you.
- Trust Store
- A trust store is the place where a system stores certificates of those systems that it trusts, or the certificates of the signers of certificates that it trusts (and their signers)
Client HelloThe first thing that happens in a TLS communication is that the client sends a client hello message to the server. This message should be a TLSv1 Client hello, and no other version. This message contains the highest version of SSL/TLS supported by the client, a seed containing some random data to initialize encryption keys, and a set of flags indicating what encryption algorithms are supported.
If the client hello indicates that the client only supports SSL Version 2.0 or 3.0, you've already got a problem. It means that the client hasn't been configured to use TLS Version 1.0 (or higher). If your system is the client, you need to fix it. If your system is the server, and you are rejecting the communications, you are fine. If you aren't rejecting it, you might be securing the channel, but you aren't conforming the IHE ATNA requirement of using TLS 1.0.
Now, because IHE ATNA profile specifies that the channel encryption must support TLS 1.0 you have to demonstrate that support. That doesn't mean that you cannot support a higher level of the protocol. So, the client hello message could indicate that the client supports TLS 1.1 or 1.2. A properly coded TLS 1.0 implementation would degrade gracefully to TLS 1.0 upon receipt of a higher version client hello; but not every implementation is properly constructed. That means that when you configure for connecthathon testing, you really should limit your system to TLS 1.0 as a client or as a server. In the production environment, if you want to bump it up to TLS 1.1 or 1.2, that's fine, but in the testing environment, you want to ensure maximum opportunity for success. So, configure your system for TLS 1.0 (and only that).
If the client hello doesn't indicate that it supports AES 128 bit encryption with SHA-1 hash, you also have a problem, because it means that the client does NOT support the IHE ATNA required encryption method. ATNA requires the use of AES-128 with SHA-1. If your system supports other encryption methods, that's great, but for connectathon, turn on AES-128, and turn everything else off. Systems supporting SSL and TLS negotiate the cipher by having the client indicate what it supports, and the server choosing from that list. If the only choice you offer is the IHE mandated cipher suite, and the server rejects your communication because it doesn't like that cipher, it's the server's problem.
Here's where the more complex failures show up. The server hello includes a response that indicates which version of SSL or TLS has actually been negotiated. It is supposed to be the highest version of the protocol supported by both the client and server assuming that when a system supports version X, it also supports any version prior to X (this is not always a valid assumption). In some secure socket stacks, when you turn on SSL V2, SSL V3, and TLS, and the client asks for TLSv1, the server might incorrectly choose SSL V3 or lower. That an implementation error in the stack. The way to control this behavior is to turn everything but TLSv1 off. And when I say that, I also mean turn off TLSv1.1 and TLSv1.2. Note, these days you do have to be careful, because asking for TLS means version 1.0, version 1.1 and version 1.2. Back when IHE started with this, there was only TLS version 1.0.
The next thing that the server does is return its certificate. The client system is going to need to verify this certificate, and when it does, it can do so a couple of different ways, and can add steps to the validation. There are two validation choices (The client has to be able to support both):
- It can simply compare the certificate to certificates it knows and likes.
- It can compare the signature on the certificate to signers that it approves of (all the way up the certificate chain).
There are extra verification steps that can be added, one of these being hostname verification. In common implementations, the receiver of a certificate also verifies that the identity asserted in the certificate matches the identity that the receiver knows the sender by. This is known as hostname verification. You'll find a line somewhere in each certificate that reads: CN=hostname (where hostname is the name of the system identified by the certificate). During hostname verification, the receiver of the certificate compares this value against the DNS name it used to access the host. You will need to disable hostname verification.
Why? My first response is because the profile says to do it that way. My second is to explain that hostname verification does not provide additional security, and introduces an additional failure mode during the setup of the secure communication channel (which is also in the profile). If you want a detailed explanation of why, you'll have to ask the ITI folks, who are much more versed in security that I am.
Next the server should ask for a certificate. When you configure TLS on the server, you can configure it to require a certificate, request but not require a certificate, or omit that step altogether. You want to require the client present a certificate. If you don't set it up that way, then you won't be certain that the clients that connect to you are those that are authorized, and you can fail to detect clients which aren't sending back an appropriate certificate.
When the server asks for a certificate, it identifies which certificates (or certificate signers) it will accept. This information is configured via the server's trust store. The trust store contains the certificates (or certificate signers) that the server trusts. There are sometimes (implementation) limits on the number of certificates that a server will send in the certificate request (which is another reason why trust chains are important). If you don't have your trust store appropriately configured, the client won't be able to find a matching certificate to send back to the server. If you have too many certificates in your trust store (e.g., more than 128), your server might also not work with some clients (those whose certificates don't get sent).
If the server response to the client hello doesn't include a certificate request, it hasn't been configured properly to require a certificate. If the certificates it sends in its request do not include either:
- The certificate your client is using, OR
- The certificate of the signer of one of the certificates in you client's certificate chain
Then either you are using the wrong certificate in your key store, or the server is not configured with the correct trust store.
The client then sends the appropriate certificate back to the server. One last point of failure at this stage can be when the certificate (or one in the chain) has expired , which sometimes isn't detected until the server attempts to validate it. That simply means you'll need a new certificate.
Hopefully this will help you debug your TLS communications