John
John

Reputation: 1128

How do you verify a public key was issued by your private CA?

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++)?

Upvotes: 18

Views: 16074

Answers (2)

John
John

Reputation: 1128

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);
}

Upvotes: 22

sarnold
sarnold

Reputation: 104090

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..)

Upvotes: 2

Related Questions