Sunday, March 9, 2014

SSL for Beginners, A Primer

Overview

The Secure Socket Layer (SSL) is used to encrypt communications between a client and a server.  There are two flavors of SSL one-way aka server-side and mutual aka bi-lateral.  As you might have guessed, mutual SSL makes use, in part, of server side SSL.

Mechanics

When the client establishes a connection with the server the client determines if the communication will occur over SSL.  For example, HTTP is unsecure and HTTPS is HTTP traffic over an SSL connection (really it could be SSL or TLS, but lets not get into that).

First off the client will call the server to open the connection.  They will negotiate to agree on an encryption algorithm (if they can't find one that they both use then you may see 'negotiation' failures).  Then the server will send it's certificate, which the client will validate in the following ways:

  1. The server certificate's subject name (or one of it's subject alternative names) must match the hostname requested by the client or you will get a hostname mismatch error.
  2. The client must trust the issuer of the server certificate, normally a third party like Verisign, Entrust, etc.  In some cases clients may be configured to trust the specific certificate of the server they are connecting to or trust the certificate by virtue of it's issuer and also require that it have a specific subject DN.  If the server's certificate does not meet the expectations of the client then the error will be something like 'could not establish trust', which is normally corrected by adding the appropriate third party issuer to the client's trusted root authorities list.
  3. If the client is configured to check for certificate revocations then it will reach out to the issuer of the server's certificate to verify that it has not been revoked.
  4. Of course the certificate must also not be expired.
The difference between the subject name (Subject CN) and the subject DN is that the CN is the name i.e. server.domain.com and the DN looks more like "CN=server.domain.com,DN=domain,DN=com" which will look familiar if you have worked with LDAP.

At this point your server side SSL connection can move forward, however if you are using mutual authentication then the client certificate is the next step.  Some clients may be configured to not send their certificate until they receive an authentication challenge while some servers expect that the clients send their certificates without being challenged and therefore will not send one, this failure mode can be difficult to recognize.  In the layer 7 environment it is fairly easy to see if a request is coming in without being signed by a client certificate, the problem becomes confirming that request is from the client you are troubleshooting and not from someone else.  The incoming IP address of the request will help you with this, unless you are behind a network architecture that is not providing an x-forwarded-for header.

If you are using mutual SSL then the server should validate the client certificate in a similar manner to the way the client validated the server's certificate, the point of which is to restrict traffic to only be accepted from known clients.  The best way to do this is to have a copy of the client certificate's public key on file for the server to use for validation.  You can use the client's issuer and/or the client's subject name (or even more properties), but even if you use the name and the issuer then another certificate with the same name from the same issuer would be able to get in.  I can understand the temptation because this means that you would not have to make any changes when the client renews their certificate, but it is not as secure as the 'shared secret' of an explicit client certificate.

Anatomy of a Certificate

This is important to understand and I have seen a lot of confusion regarding Public and Private key pairs.  When you create a certificate you generate a key which uses a random number and a password of your choosing.  You should then generate a 'Certificate Signing Request' which you hand off to the issuing authority and they give you back your public certificate (cer, crt, or other extension), you can then merge your key with the certificate to get your private certificate.  The process differs greatly from one issuer (signing authority) to another.

Think of the private key like your drivers license or debit card, when combined with your social or pin (the password) someone else can impersonate you and gain access to sensitive information.  In other words, don't give anyone that private key that should not have it.  Even if you don't give them the password; giving anyone else that key compromises it's security.

The public key on the other hand is much more innocuous.  Its more like your drivers license number, without the card itself there is not much they can do beyond confirming that they are being presented with your card when they see it and it lets them know some information about you (which is what the public key is for), but most importantly they cannot use it to impersonate you.

Both server and client certificates have private and public keys.

  • The private server certificate gets installed on the server to host the site or service
  • The public server certificate is delivered to clients connecting to the secured URL
  • The client certificate private key is used to sign requests outgoing to a secured URL
  • The client certificate public key is used by the server to verify the signature of the incoming request from the client
A single certificate can be used for both (as well as other) purposes, but the private key would have to be implemented on a client and a server in order to actually act as both.  When you examine the properties of a certificate you can see what it can be used for in the 'enhanced key usage' (multi-value) property.

Trust Relationships

A third party issuer will have a self-signed root authority.  This means that the certificate does not have an issuer, if you trust it that is because you trust who owns it.  As an issuer they can use it to sign other certificates, such as server, client, and intermediate authorities.  For example the third party trusted authority may issue your company a intermediate authority, and then your company could use that intermediate authority to sign your own server and client certificates.  Then when others look at your certificate public key (because you wouldn't be handing out the private keys) they would see your server certificate's trust chain consists of server.domain.com issued by your.intermediate.authority which is issued by third.party.authority.  Then when they have third.party.authority in their trusted root list they can accept the connection to your server.

In reality if they do not have the third party root in their trusted root authorities list and your intermediate authority in their trusted intermediate authorities list then they may not see your trust chain properly while examining your certificate as that information is populated by the local system unless the certificate is configured to send the entire chain with it.  Also, in order for them to trust a certificate that has an intermediate authority they must either have that authority in their trust lists or trust the root authority and have the certificate delivered with it's complete trust chain.

Certificates issued by the trusted third party are trusted by extension because the third party is expected to have performed due diligence in verifying the identity of those requesting that the third party issue certificates to them.  That is really what you are trusting the third party to do when you add their self-signed issuing root into your trusted root authorities list.  Though if there are intermediate authorities you still need them delivered at some point in order to make that connection between the server or client certificate and the trusted root.