Search code examples
sslopensslssl-certificatecertificatex509certificate

openssl: try to load local ca store


I try to understand the concept of CA store, and test with my own certificate chain without system-wide effect.

I have a ca_store directory under my local home directory with one root and one intermediate CA.

$ ls /home/my/ca_store
root_ca.crt  intermediate_ca.crt

I also have a server certificate. The verification is successful using openssl command. I just want to do it using C code, and preferably the concept of CA store.

The following code does not verify server.crt correctly, but is it possible to make it work?

SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_CTX* ctx = SSL_CTX_new(TLS_server_method());
SSL_CTX_load_verify_locations(ctx, NULL, "/home/my/ca_store");
BIO* bio = BIO_new_file("server.crt", "rb");
X509* cert = X509_new();
PEM_read_bio_X509(bio, &cert, NULL, NULL);
X509_STORE_CTX* store_ctx = X509_STORE_CTX_new();
X509_STORE_CTX_init(store_ctx, SSL_CTX_get_cert_store(ctx), cert, NULL);
int ret = X509_verify_cert(store_ctx);
if (ret != 1)
{
   int error = X509_STORE_CTX_get_error(store_ctx);
   const char *error_str = X509_verify_cert_error_string(error);
   printf("Certificate verification failed. Error code: %d, Error message: %s\n", error, error_str);
   ERR_print_errors_fp(stdout);
}
else
{
   printf("Certificate verification successful\n");
}

Below is the output.

Certificate verification failed. Error code: 20, Error message: unable to get local issuer certificate

Solution

  • Your file names are wrong. Per OpenSSL's documentation for SSL_CTX_load_verify_locations() (bolding mine):

    If CApath is not NULL, it points to a directory containing CA certificates in PEM format. The files each contain one CA certificate. The files are looked up by the CA subject name hash value, which must hence be available. If more than one CA certificate with the same name hash value exist, the extension must be different (e.g. 9d66eef0.0, 9d66eef0.1 etc). The search is performed in the ordering of the extension number, regardless of other properties of the certificates. Use the c_rehash utility to create the necessary links.

    It'd be easier to combine the files into one and use the CAfile argument:

    cat root_ca.crt  intermediate_ca.crt > truststore.pem
    

    then

    SSL_CTX_load_verify_locations(ctx, "/home/my/ca_store/truststore.pem", NULL);