Read certificate files from memory instead of a file using OpenSSL

Viewed 24908

I have a server which would listen on HTTPS using OpenSSL. For this, I have to provide the certificate to use. However, the current implementation uses a filename to be provided to the OpenSSL API.

I want the certificate information to be read from memory, so that I don't have to ship the certificate file opening. I tried to google, but I didn't come up with any options.

Is is possible? If so, how do I read certificate files from memory instead of a file using OpenSSL?


EDIT: The following was moved from the comments to the question.

// CURRENT
void start_server()
{
    const char *fileName = "cert_and_key.pem";
    set_server_ssl_file(fileName);
}
set_server_ssl_file(const char *fileName)
{
    //initialize context
    SSL_CTX_use_certificate_file(CTX, pem, SSL_FILETYPE_PEM); 
    SSL_CTX_use_PrivateKey_file(CTX, pem, SSL_FILETYPE_PEM);
}

//REQUIRED
void start_server()
{
    const char *cert = "--BEGIN CERTIFICATE--............";
    const char *key = "--BEGIN RSA PRIVATE KEY--.......";
    set_server_ssl_options(cert, key);
}
set_server_ssl_options(const char *cert, const char *key)
{
    //IMPLEMENTATION REQUIRED
}
4 Answers

There is another response that uses X509_STORE_add_cert, which is up-voted but incorrect. That answer is a way to do SSL_CTX_load_verify_locations in memory, but does not load the server certificate chain. Replies to that comment also indicate that it does not work.

The following code is a load-from-memory implementation of SSL_CTX_use_certificate_chain_file based on the implementation of that function in OpenSSL:

bool 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;
    int i, count = 0, type = X509_FILETYPE_PEM;
    STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL);

    if (!inf)
    {
        BIO_free(cbio);
        return false;
    }

    /* Iterate over contents of the PEM buffer, and add certs. */
    BOOL first = TRUE;
    for (i = 0; i < sk_X509_INFO_num(inf); i++) {
        itmp = sk_X509_INFO_value(inf, i);
        if (itmp->x509)
        {
            /* First cert is server cert. Remaining, if any, are intermediate certs. */
            if (first)
            {
                first = FALSE;

                /*
                 * Set server certificate. Note that this operation increments the
                 * reference count, which means that it is okay for cleanup to free it.
                 */
                if (!SSL_CTX_use_certificate(context, itmp->x509))
                    goto Error;

                if (ERR_peek_error() != 0)
                    goto Error;

                /* Get ready to store intermediate certs, if any. */
                SSL_CTX_clear_chain_certs(context);
            }
            else
            {
                /* Add intermediate cert to chain. */
                if (!SSL_CTX_add0_chain_cert(context, itmp->x509))
                    goto Error;

                /*
                 * Above function doesn't increment cert reference count. NULL the info
                 * reference to it in order to prevent it from being freed during cleanup.
                 */
                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;
}
Related