3

Usually 2 way ssl aka mutual auth includes generating a server ca key & certs, etc.Then the client generates a csr, gives it to you and you sign their csr and provide them with a client cert.

However,

I have encountered a case where the client requires that I implement "mutual auth" by exchanging each others x509 public certs. Is this heard of? Perhaps called something other than "2 way SSL" or "Mutual Authentication".

I am struggling to find any documentation or information on this with openssl.

jww
  • 97,681
  • 90
  • 411
  • 885
cosbor11
  • 14,709
  • 10
  • 54
  • 69
  • In this case (when all is working as intended), the client always provide a x509 certificate when using mutual authentication. The server advertises its support for certificate based authentication by advertising the CA's it accepts as issuers. Note: there are other mutual auth schemes, like TLS-PSK and TLS-SRP. – jww May 04 '16 at 01:35

3 Answers3

5

I have encountered a case where the client requires that I implement "mutual auth" by exchanging each others x509 public certs. Is this heard of?

I believe its still called mutual authentication.

Generally, certificate based mutual authentication falls into one of two models. The first is the enterprise model with a CA hierarchy, and the organization's CA signs both the client and server certificate.

The second model is clients using self-signed certificates in what is called Origin Bound Certificates. Its called Origin Bound because each site (origin) that needs a certificate gets the client to provide one. Origin bound certificates are the basis of the IETF's Token Binding protocol.

Its not clear to me if token binding has the same security properties as origin bound certificates. You see, we can use origin bound certificates to thwart man-in-the-middle attacks by making authentication part of channel setup. Token binding decouples the binding and moves it up in the stack. I believe it allows the MitM to act as an intermediary.


Enterprise Certificates

In the enterprise model, here's what you do with OpenSSL.

At the server perform the following. The server will handle the client certificate validation:

  • Call SSL_CTX_set_verify with SSL_VERIFY_PEER and SSL_VERIFY_FAIL_IF_NO_PEER_CERT.
  • Call CTX_set_client_CA_list to set the list of issuer CA the server will accept. This causes the appropriate SSL/TLS message to be sent to the client prompting for the certificate. This only sends a list of names to the client; they still must be trusted at the server
  • Call SSL_CTX_load_verify_locations with issuers the server accepts. This adds the trust on the server side.

At the client, perform the following:

  • Call SSL_CTX_use_certificate_file to load the client certificate
  • Call SSL_CTX_use_certificate_chain_file as needed
  • Call SSL_CTX_use_PrivateKey to load the private key

Origin Bound Certificates

Origin bound and self signed certificates are a little different because there's no CA hierarchy.

At the server perform the following. The server does not call SSL_CTX_load_verify_locations or CTX_set_client_CA_list because its a self signed certificate.

  • Call SSL_CTX_set_verify with SSL_VERIFY_PEER and SSL_VERIFY_FAIL_IF_NO_PEER_CERT.
  • Call SSL_get_peer_certificate after key exchange. Validate the client certificate presented to the server.

At the client, perform the following. Its the same as the enterprise model.

  • Call SSL_CTX_use_certificate_file to load the client certificate
  • Call SSL_CTX_use_certificate_chain_file as needed
  • Call SSL_CTX_use_PrivateKey to load the private key

The lack of an enterprise CA means the client's self signed certificate needs to be communicated out-of-band to the server. Then the server needs to keep some sort of directory for looking up client certificates based on distinguished names and serial numbers. What you really care about here is the client's public key. In this case the X509 certificate is a presentation detail. Its just packaging because it usually binds the identity to a public key though an authority's signature (but not in this model).

The attack in this model - the 500-lb gorilla in the room - is the bad guy impersonating a user by using the same Distinguished Name and Serial Number because there is no Registration Authority (RA). You will need some measures to ensure you are not duped, like sending an email to a user to confirm their public key changes are expected.

The attack means that when you enroll a user, you need three or four things:

  • Unique {Distinguished Name, Serial Number} pair
  • Public key (part of the X509 certificate)
  • A confirmation/recovery email address

To muddy the waters further, the user may have 3 or 4 devices, so they create a new origin bound certificate for each device. You will need to handle that enrollment gracefully, too.

To collectively take it full circle, what really matters is the email address and the different public keys/identities associated with the email address. The identities are housed in a X509 certificate with a unique {Distinguished Name, Serial Number} pair. You probably want them unique for auditing purposes, but there will likely be some copy/pasting going on among devices.


I am struggling to find any documentation or information on this with openssl.

You are probably having trouble finding information because this is a higher level, security architecture and design problem. To help with some references, start by reading Dietz, Czeskis, Balfanz and Wallach's Origin-Bound Certificates: A Fresh Approach to Strong Client Authentication for the Web. Also visit Peter Gutmann's Engineering Security and Ross Anderson's Security Engineering.

Origin Bound Certificates can be used to replace nearly every password based authentication system. It applies to nearly all the systems, from username/password based authentication to API keys used in web services. The password is still used to protect the local private key, but the password is not put on the wire.

When data sensitivity levels warrant stronger security controls, client certificates is one of the first things we turn to stop the mishandling of the password and botched authentication and authorization controls. Don't buy into Apple, Microsoft, Google (et al) use and handling of passwords. Its been defective for years. Its simply companies making it easy on users so they can capture business.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
1

The traditional client certificate method leverages a CA and digital signatures to verify the authenticity of the certificate.

In your case, it seems like what you want is to exchange certificates in a trusted channel beforehand. What you need to do in this case, is to store the fingerprint of this certificate, and on incoming requests verify that the signature is correct.

Here's an example in Node.JS:

const https = require('https');
const fs = require('fs');

const options = {
    key: fs.readFileSync('/tmp/server.key'),
    cert: fs.readFileSync('/tmp/server.crt'),
    requestCert: true,
    rejectUnauthorized: false
};

https.createServer(options, (req, res) => {
    // We use snake oil certificates and no CA, so we will have an unauthorized cert.
    console.log(req.socket.authorized);
    var cert = req.connection.getPeerCertificate();
    // Here's the cert fingerprint, validate that it's the one you expected
    console.log(cert.fingerprint);

    res.writeHead(200);
    res.end('hello world\n');
}).listen(8000);

A ruby script to generate the certs and keys:

require "openssl"

keypair = OpenSSL::PKey::RSA.new(2048)
cert = OpenSSL::X509::Certificate.new
cert.not_before = Time.now
cert.subject = OpenSSL::X509::Name.new([
    ["C", "NO"],
    ["ST", "Oslo"],
    ["L", "Oslo"],
    ["CN", "Root CA"]
                                               ])
cert.issuer = cert.subject
cert.not_after = Time.now + 1000000000 # 40 or so years
cert.public_key = keypair.public_key
cert.sign(keypair, OpenSSL::Digest::SHA256.new)

File.open("/tmp/client.key", "w+") do |f|
  f << keypair.to_pem
end

File.open("/tmp/client.crt", "w+") do |f|
  f << cert.to_pem
end


snakeoil_keypair = OpenSSL::PKey::RSA.new(2048)
snakeoil_cert = OpenSSL::X509::Certificate.new
snakeoil_cert.not_before = Time.now
snakeoil_cert.subject = OpenSSL::X509::Name.new([
    ["C", "NO"],
    ["ST", "Oslo"],
    ["L", "Oslo"],
    ["CN", "Root CA"]
                                               ])
snakeoil_cert.issuer = snakeoil_cert.subject
snakeoil_cert.not_after = Time.now + 1000000000 # 40 or so years
snakeoil_cert.public_key = snakeoil_keypair.public_key
snakeoil_cert.sign(snakeoil_keypair, OpenSSL::Digest::SHA256.new)

File.open("/tmp/server.key", "w+") do |f|
  f << snakeoil_keypair.to_pem
end

File.open("/tmp/server.crt", "w+") do |f|
  f << snakeoil_cert.to_pem
end

Test with curl:

curl --insecure --cert /tmp/client.crt --key /tmp/client.key https://localhost:8000

Note that an important layer of security is left out - anyone with that fingerprint will be a valid user, you don't get the nice crypto checks of a CA setup.

August Lilleaas
  • 54,010
  • 13
  • 102
  • 111
  • Lilleass, Thank you for taking the time to answer. Is there a name for this strategy that distinguishes it from traditional 2 way SSL? – cosbor11 May 04 '16 at 16:43
  • I'm not sure. If I had to come up with a name, I'd maybe choose "certificate fingerprint validation" or something like that. – August Lilleaas May 04 '16 at 21:09
  • I think this is something entirely different. The SSL handshake in my case is doing the same exact verification process as typical SSL. There is no fingerprint involved. Rather my question is more about the setup process rather than the authentication process – cosbor11 May 04 '16 at 21:13
  • 1
    @cosbor11 - they are roughly called *[Origin Bound Certificates](https://www.usenix.org/system/files/conference/usenixsecurity12/sec12-final162.pdf)* when they are self-signed. The browsers despise them because their security model embraces Man-in-the-Middle. Its one of the reason the `` tag is going away (and a reason they don't discuss, other than to vaguely say *"it breaks legitimate use cases*). You can use Origin Bound Certificates in non-browser web services. – jww May 05 '16 at 07:39
1

Mutual authentication in a TLS (or SSL) handshake requires exchange of certificate of both peers.

The client authenticates the server it's connecting to by verifying the server certificate (an its certificate chain it was issued from).

This is done for example when you browse to any https website. Your browser will check that the certificate received is trusted (by looking up its certificate store) and will also check, among other properties, the dns name of the website matches the common name of the certificate.

In a TLS mutual authentication, the server will also check that the client is trusted by verifying the client certificate. This less common type of authentication requires the following conditions:

  1. The client propose in the TLS handshake a suitable cipher that requires certificate authentication
  2. The server selects one of the client cipher based on its cipher configuration
  3. The server has in its certificate store at least the client root CA (possible also intermediate client CA)
  4. The client also needs the server root CA (and possibly intermediate CA)

To meet the first condition the openssl cipher list of the client has to include for example authentication using RSA based ciphers like RSA-AES128-SHA256. You can see the client cipher list using wireshark by looking at the client hello message. To define (or restrict) the number of ciphers, you can use openssl ciphers command, and play with the cipher string.

On the server side, the cipher must also be configured, and selected. This selection is dependent on the implementation. Often the server will select the first suitable cipher seen in the client hello (even if the RFC says the server can select any cipher from the list). So in some cases putting the wanted cipher on top of the client cipher list will help.

Regarding certificate, both server and client root CA must be provisioned respectively in the client and server certificate store. Now if any side has a certificate chain, it's sometimes required to also put the intermediate CA in the certificate store.

oliv
  • 12,690
  • 25
  • 45