how to validate ssl certificate with boost and openssl

43 views Asked by At

I need to push data to a server and the data needs to be transferred securely.

Iam using lib boost.

// The SSL context is required, and holds certificates
ssl::context ctx(ssl::context::tlsv13_client);

The issue that i have is that ctx.set_default_verify_paths(); does not validate the certificate of the server that i want to transmit the data to. But when you navigate with a browser to the server it works fine, no need to trust the certificate by the user. Which means its generated by a trusted entity.

I managed to make it work with using ctx.load_verify_file("cert-chain.pem"); But it wasn't working when i was using ctx.load_verify_file("cert.pem");

I digged a little bit more and found that the certificate is an intermediate certificate... And that's why boost (which rely on openssl under the hood) cannot validate the certificate. But how is the browser able to validate the certificate ??

I have started to implement my custom validation process but since my code is open source i thought it was pointless to implement the validation. Since someone could just read the code and generate a certificate with the values iam validating.


ctx.set_verify_callback(std::bind(&custom_verify_callback, std::placeholders::_1, std::placeholders::_2));

[...]

bool custom_verify_callback(bool preverified, boost::asio::ssl::verify_context& ctx)
{
    // Perform your custom verification logic here
    X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
    // Example: Check if the certificate is issued by a trusted CA
    // This is a simplistic example and may not cover all verification requirements
    if (preverified && cert != nullptr)
    {
        // Check if the certificate is issued by a trusted CA
        // You may need to implement more complex logic here depending on your requirements
        // For example, checking if the intermediate certificate is present in the chain
        // or verifying the hostname
        // Example: Check the issuer of the certificate
        X509_NAME* issuer = X509_get_issuer_name(cert);
        if (issuer != nullptr)
        {
            // Compare the issuer name with your trusted CA's name
            // For simplicity, this example assumes a specific issuer name
            if (X509_NAME_cmp(issuer, "") == 0)
            {
                return true;
            }
        }
    }
    return false;
}
1

There are 1 answers

4
sehe On

Which means its generated by a trusted entity.

The key part is: which trusted entity. These are known as CAs (certificate authorities) and your browser has a list of them that can (and usually is) separate from you operating system's list of trusted CAs.

The most typical to do for a proprietary application is to embed/distribute your own list of trusted CAs (which is frequently just 1). So instead of relying on the OS's list you can make sure your server's certificate issuer is trusted for your application.

I managed to make it work with using ctx.load_verify_file("cert-chain.pem");

That's exactly how you'd do that

But it wasn't working when i was using ctx.load_verify_file("cert.pem");

That's because if the root of the chain (the root CA) cannot be verified. You may be able to work around it with set_verify_depth but it seems natural to verify the entire chain.

I digged a little bit more and found that the certificate is an intermediate certificate... And that's why boost (which rely on openssl under the hood) cannot validate the certificate. But how is the browser able to validate the certificate ??

Because it has the entire chain in its own certificate store. Note that browsers have additional verifications (like certificate revocation lists and additional blacklists).

I have started to implement my custom validation process but since my code is open source i thought it was pointless to implement the validation. Since someone could just read the code and generate a certificate with the values iam validating.

The same goes for the checks implemented in openssl. Guarding against targeted hacks is entirely different from authenticating servers on the web. Guard against such attacks by hardening your system (e.g. make sure your custom certificate store cannot be tampered with). The most obvious solution is to have privilege separation (if an attacker can manipulate the code you are running your system is already compromised). Another typical method is to detect such tampering e.g. by using signed binaries (depending on your platform support).