1

I’m working on boost::beast based application on macOS platform, and I wonder how I can provide a client-side certificate to authenticate against the server ?

basically , in macOS the certificates are stored in keychain, and cannot be exported (backed by dedicated hardware called secured-enclave for better security)…

So I wonder if there’s any callback suitable to sign server’s challenge manually with native macOS native code that send the challenge to the keychain/secure-enclave for signing.

basically, I'm looking for a callback that have roughly the following signature :

bool validate_client_side_certificate(const std::string& challenge) 

So basically What I've got right not is the ability to provide the certificate + private key from file


boost::asio::ssl::context ctx_;
std::string client_cert_ = read_pem_file(client_cert_path);
std::string client_cert_private_key_ = read_pem_file(private_key_path);

ctx_.use_certificate(
   boost::asio::buffer(client_cert_.c_str(), client_cert_.length()),
   boost::asio::ssl::context::pem);
ctx_.use_private_key(
   boost::asio::buffer(client_cert_key_.c_str(),                                            client_cert_key_.length()),
   boost::asio::ssl::context::pem);

This flow works perfectly, but if I want to use the certificates that are inside the keychain (macOS storage for crypto data) I cannot get the private key but only a reference (because it's protected).

So in macOS we cannot just provide the private key to ctx_ do that the challenge will be signed automatically. instead, we need to get the callback that occur when client-side authentication is required, along with the challenge... and use macOS native code to sign the challenge inside the keychain hardware, using the key reference.

Zohar81
  • 4,554
  • 5
  • 29
  • 82
  • I didn't think `ssl::context` had a default constructor? I was specifically hoping for the sample code to answer those kind of questions with concrete information. – sehe Mar 21 '22 at 10:02

1 Answers1

1

See set_verify_callback

There are examples here:

  • asio/example/cpp11/ssl/client.cpp
  • asio/example/cpp03/ssl/client.cpp

You can see it integrated in Beast's ssl_stream: https://www.boost.org/doc/libs/1_78_0/libs/beast/doc/html/beast/ref/boost__beast__ssl_stream/set_verify_callback/overload2.html

sehe
  • 374,641
  • 47
  • 450
  • 633
  • PS. In case of client certificates you will already have been using [set_verify_mode](https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/reference/ssl__stream/set_verify_mode.html) – sehe Mar 20 '22 at 17:43
  • Hi and thanks for the answer. I was thinking that this method is used to validate server certificate by client. are you sure it's the other way around ? because 'verify' may hint that it's verified from client perspective. I'd expect to find the word 'authenticate' in the method, which may hint that the server is the verifier in this relationship... besides, where do I find the challenge, in `net::verify_context` ? – Zohar81 Mar 20 '22 at 17:46
  • It's both. "Verify" hints that it verifies :) Yeah, I suppose that you're going to have to use the `native_handle`s to get some openssl specific details, I admit I don't have an example off-hand. – sehe Mar 20 '22 at 17:49
  • Ok thanks, so first I'll try to extract the challenge out of this structure `asio::ssl::verify_context`... I guess there's where the challenge should be – Zohar81 Mar 20 '22 at 17:54
  • But I think something is still missing here, because the callback signature returns a boolean, instead of the signed challenge (which is much longer than that) .. so I guess the verifier relate to the client as the verifier and the server as being verified. – Zohar81 Mar 20 '22 at 17:57
  • Can you show a more complete example? I can try to make it work, but right now it's not completely clear what you have and which side of the communications you're implementing. – sehe Mar 20 '22 at 21:59
  • Hi, I've added my current flow to perform client-side authentication. please let me know if it can be done manually using callback that get the challenge and suppose to sign it explicitly. – Zohar81 Mar 21 '22 at 08:54
  • I'm missing what code you need to sign the challenge. Are you saying OpenSSL cannot do the challenge either? What input parameters do you require to allow the Mac specific API to sign the challenge? (The Asio bits are known to me, I do not have a Mac, nor do I know how to find the API you're using) – sehe Mar 21 '22 at 10:01