16

I have created a CA cert, and used it to issue a public key. At a date in the future, I need to verify that the certificate loaded was issued by my CA.

How do I do that with the OpenSSL API (c++)?

Étienne
  • 4,773
  • 2
  • 33
  • 58
John
  • 1,058
  • 1
  • 11
  • 21

2 Answers2

20

I've reduced verify.c (in openssl/apps/) to the minimum functions required. Assumptions: cert and CA cert are both PEM format files. There are no CRLS or trusted list checks required.

Call verify() with the path to your cert and CA PEM files.

static int verify(const char* certfile, const char* CAfile);
static X509 *load_cert(const char *file);
static int check(X509_STORE *ctx, const char *file);

int verify(const char* certfile, const char* CAfile)
{
    int ret=0;
    X509_STORE *cert_ctx=NULL;
    X509_LOOKUP *lookup=NULL;

    cert_ctx=X509_STORE_new();
    if (cert_ctx == NULL) goto end;

    OpenSSL_add_all_algorithms();

    lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_file());
    if (lookup == NULL)
        goto end;

    if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM))
        goto end;

    lookup=X509_STORE_add_lookup(cert_ctx,X509_LOOKUP_hash_dir());
    if (lookup == NULL)
        goto end;

    X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);

    ret = check(cert_ctx, certfile);
end:
    if (cert_ctx != NULL) X509_STORE_free(cert_ctx);

    return ret;
}

static X509 *load_cert(const char *file)
{
    X509 *x=NULL;
    BIO *cert;

    if ((cert=BIO_new(BIO_s_file())) == NULL)
        goto end;

    if (BIO_read_filename(cert,file) <= 0)
        goto end;

    x=PEM_read_bio_X509_AUX(cert,NULL, NULL, NULL);
end:
    if (cert != NULL) BIO_free(cert);
    return(x);
}

static int check(X509_STORE *ctx, const char *file)
{
    X509 *x=NULL;
    int i=0,ret=0;
    X509_STORE_CTX *csc;

    x = load_cert(file);
    if (x == NULL)
        goto end;

    csc = X509_STORE_CTX_new();
    if (csc == NULL)
        goto end;
    X509_STORE_set_flags(ctx, 0);
    if(!X509_STORE_CTX_init(csc,ctx,x,0))
        goto end;
    i=X509_verify_cert(csc);
    X509_STORE_CTX_free(csc);

    ret=0;
end:
    ret = (i > 0);
    if (x != NULL)
        X509_free(x);

    return(ret);
}
John
  • 1,058
  • 1
  • 11
  • 21
  • 5
    can you explain the code with comments i am not able to understand the logic of this verification process – Balamurugan Jul 07 '11 at 05:50
  • Is it possible to use memory instead of file? I would like to have A send certificate to B, and verify. Anyone like to share the code? Thanks a lot. – user180574 Jan 08 '13 at 22:54
  • user180574 - I think you need to use BIO_new_mem_buf – John Jan 20 '13 at 19:29
  • 2
    You don't need the calls to `X509_STORE_add_lookup(... X509_LOOKUP_hash_dir());` and `X509_LOOKUP_add_dir(NULL, ...);` since you provide your CA file. – jww Mar 02 '14 at 10:32
  • 3
    You can add flags to the context at `X509_STORE_set_flags(ctx, 0);`. `X509_V_FLAG_X509_STRICT | X509_V_FLAG_CHECK_SS_SIGNATURE | X509_V_FLAG_POLICY_CHECK` might be good choices. Be sure to stay away from `X509_V_FLAG_ALLOW_PROXY_CERTS`. – jww Mar 02 '14 at 10:33
  • If the call to `X509_verify_cert(csc);` fails, I believe you can get the error code from `csc.error`. (The value from `ERR_get_error()` is worthless as it always appears to be `0`). – jww Mar 02 '14 at 10:37
  • @John - Even with BIO_new_mem_buf I get a BIO, but X509_LOOKUP_load_file requires are file-path char*.. is there any other function to achieve the same result? – yashdosi Jun 13 '14 at 10:06
2

The openssl verify -CAfile <CA_cert_filename> <unknown_cert_filename> command will do what you want -- it's miserable to try to find the API that will do what you want, so I'd suggest finding the source code for the openssl verify routine.

(If you have choice of implementations, gnutls looks promising:

   #include <gnutls/x509.h>

   int gnutls_x509_crt_verify(gnutls_x509_crt_t cert, const  gnutls_x509_crt_t
   * CA_list, int CA_list_length, unsigned int flags, unsigned int * verify);

But OpenSSL is installed everywhere..)

sarnold
  • 102,305
  • 22
  • 181
  • 238