14

I am using OpenSSL to verify a server's certificate. Since OpenSSL is shipped without any built-in root CAs, we must distribute the root CA certificate ourselves with our software (we statically-link OpenSSL). Ordinarily, the way to do this is to distribute a certificate file in PEM format and call SSL_CTX_load_verify_locations.

However, this function takes a file/directory path and reads the root certificate file(s) directly from the filesystem. We would really like to be able to hard-code the certificate into our binary instead of saving it to the filesystem.

In other words, we would really like to have a function like SSL_CTX_load_verify_locations that takes an X509* instead of a file-path.

Does something like this exist? or is there an easy way to hack it together ourselves? We can't seem to find much information about this.

Thank you very much for any suggestions!

DSII
  • 429
  • 6
  • 15
  • What prevents you from saving hardcoded root certificate on disk before calling SSL_CTX_load_verify_locations? – Alexei Polkhanov Feb 19 '11 at 20:14
  • Nothing prevents it: however, we're a security application and are concerned about malicious interference. In particular, if it's easy to locate and overwrite our root certificate file then you can obstruct any of our SSLed transactions. We will go this route if need be, but it would be great to be able to compile the root certificate into the binary itself. – DSII Feb 19 '11 at 20:33
  • It is not any more secure to have your root CA hardcoded than keeping it in a file. – Alexei Polkhanov Feb 20 '11 at 02:11
  • 1
    At least hard-coded it takes some non-trivial reverse engineering to locate it and manipulate it in the binary. Moreover, while I agree this is a debatable point, and I'm happy to discuss it with you, I'd also like to know if there happens to be an answer to my original question (an alternative to SSL_CTX_load_verify_locations that takes an X509* in memory rather than a file-path). – DSII Feb 20 '11 at 03:30

2 Answers2

23

The function SSL_CTX_get_cert_store() can be used to get a handle to the certificate store used for verification (X509_STORE *), and the X509_STORE_add_cert() function (in openssl/x509_vfy.h) can then be used to add a certificate directly to that certificate store.

caf
  • 233,326
  • 40
  • 323
  • 462
0

@caf's answer is correct, but perhaps some people are interested in loading an entire .pem file from memory (instead of a single X509*). Based on an answer to a similar question, we can implement it as follows:

load_cert_chain_from_shared_mem (SSL_CTX *context, const char *cert_buffer) {
    BIO *cbio = BIO_new_mem_buf((void*)cert_buffer, -1);
    if (!cbio) return false;

    X509_INFO *itmp;
    STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);

    if (!inf) {
        BIO_free(cbio);
        return false;
    }
    
    X509_STORE *ctx = SSL_CTX_get_cert_store(context);

    // Iterate over contents of the PEM buffer, and add certs.
    for (int i = 0; i < sk_X509_INFO_num(inf); i++) {
        itmp = sk_X509_INFO_value(inf, i);
        if (itmp->x509) {
            // Add intermediate cert to chain.
            if (!X509_STORE_add_cert (ctx, itmp->x509))
                goto Error;

            // Above function doesn't increment cert reference count. NULL the info
            itmp->x509 = NULL;
        }
    }

    sk_X509_INFO_pop_free(inf, X509_INFO_free);
    BIO_free(cbio);

    return true;

Error:
    sk_X509_INFO_pop_free(inf, X509_INFO_free);
    BIO_free(cbio);

    return false;
}

Here cert_buffer is the contents from your .pem file, e.g.

------BEGIN CERTIFICATE-----
....
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
....
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
....
-----END CERTIFICATE-----
Thomas Wagenaar
  • 6,489
  • 5
  • 30
  • 73