boost asio SSL two way authentication
Asked Answered
A

2

5

I need a snippet of code for a program i am writing with Boost Asio SSL. I have a system of two clients, that connect with each other. I require them to do a mutual authentication, so, that at the end of the handshake() command, both clients can be certain that the other client has the private key to the certificate they supplied. Both clients have a context object, lets call them ctx1and ctx2 and each client has a public certificate and a private key.

Is it possible to set up the context objects so, that when i call socket.handshake() the clients will do a two-way authentication. If not, what would be the correct way to go about to achieve my goal ?

Apollinaire answered 16/8, 2014 at 19:2 Comment(1)
I don't think it is a concern if the other client has the private key. If the other client hasn't, he can't decode your message anyway. If both clients do X.509 authentication, maybe on a shared authentication provider, they can just share public keys.Towage
F
15

It looks like boost just uses the OpenSSL interface. I don't know boost much but I've implemented lots of OpenSSL internals for Perl and came to the following conclusions after reading the relevant parts of the boost source code:

To have mutual authentication with OpenSSL you have to use SSL_VERIFY_PEER on the client side and SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT on the server side. If you use only SSL_VERIFY_PEER on the server side it will only send the certificate request to the client, but silently accept if the client sends no certificate back.

With boost this would probably be:

ctx.set_verify_mode(ssl::verify_peer); // client side
ctx.set_verify_mode(ssl::verify_peer|ssl::verify_fail_if_no_peer_cert); // server side

If you set verify_mode this way it will verify the certificates against the configured trusted CAs (set with ctx.load_verify_file or ctx.load_verify_path).

If you have full control over the CA which signed the certificates (i.e. its your own CA) it might be enough for you to accept any certificates signed by this CA. But if you use a CA which also signed certificates you don't want to accept, like typically the case with public CAs, you also need to verify the contents of the certificate. Details how to do this depends on your protocol, but for the usual internet protocols like HTTP or SMTP this involves checking commonName and/or subjectAltNames of the certificate. Details like wildcard handling vary between the protocols.

Boost provides rfc2818_verification to help you with HTTP-style validation, although from reading the code I think the implementation is slightly wrong (multiple wildcards accepted, IDN wildcards allowed - see RFC6125 for requirements).

I don't know of any standards for verifying client certificates. Often just any certificate signed by a specific (private) CA will be accepted. Other times certificates from a public CA matching a specific e-mail pattern. It looks like boost does not help you much in this case, so you probably have to get OpenSSL SSL* handle with sock.native_handle() and then use OpenSSL functions to extract certificate (SSL_get_peer_certificate) and to check the contents of the certificate (various X509_* functions).

At least if public CAs are involved you should also check the revocation status of the certificates. It looks like boost does not provide a direct interface to CRL (certificate revocation list) so you have to use ctx.native_handle() with the appropriate OpenSSL functions (X509_STORE_add_crl etc). Using OCSP (online status revocation protocol) is way more complex and relevant OpenSSL functions are mostly undocumented, which means you have to read the OpenSSL source code to use them :(

Fraya answered 17/8, 2014 at 8:6 Comment(2)
So if I call verify_peer on both ends client1 can be sure that client2 has the private key to the certificate he supplied, and vice versa ?Apollinaire
You can be sure that both have the key to the certificate they provide. But, you need also verify_fail_if_no_peer_cert on the server side to fail if the client has not provided a certificate.Fraya
B
1

One cant force other side to authenticate against you, it is up to protocol, Ieach side autenticate only against other side. Just follow manuals as http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/overview/ssl.html

ssl::context ctx(ssl::context::sslv23);
ctx.set_verify_mode(ssl::verify_peer);
ctx.load_verify_file("ca.pem");
Bogusz answered 16/8, 2014 at 19:10 Comment(3)
You need verify_peer|verify_fail_if_no_peer_cert to enforce mutual authentication. With only verify_peer the server will request the certificate from the client but continue without error if no certificate was provided. At the client side verify_peer is enough.Fraya
@Steffen make your comment an answerOmsk
I specifically asked to use identifying names like client1.crt or client2.pem or something like that, because Asio-s documentation is confusing enough, but it's still the best answer so far, thxApollinaire

© 2022 - 2024 — McMap. All rights reserved.