x509 certificate verification in C
Asked Answered
C

3

10

I do have certificates in DER and PEM format, my goal is to retrieve the fields of Issuer and Subject and verify the certificate with the CA public key and simultaneously verify CA certificate with the root public key. I am able to retrieve all the details of issuer and subject but unable to verify the certificate.
The API used:

x509 = d2i_X509_fp (fp, &x509); //READING DER Format
x509 = PEM_read_X509 (fp, &x509, NULL, NULL); //READING PEM Format
//to retrieve the Subject:
X509_NAME_oneline(X509_get_subject_name(x509), subject, sizeof (subject));
//to retrieve the Issuer:
X509_NAME_oneline(X509_get_issuer_name(x509), issuer, sizeof (issuer));

//To store the CA public key (in unsigned char *key) that will be used to verify the 
//certificate (in my case always sha1WithRSAEncryption):
RSA *x = X509_get_pubkey(x509)->pkey.rsa;
bn = x->n;
//extracts the bytes from public key & convert into unsigned char buffer
buf_len = (size_t) BN_num_bytes (bn);
stored_CA_pubKey = (unsigned char *)malloc (buf_len);
i_n = BN_bn2bin (bn, (unsigned char *)stored_CA_pubKey);
if (i_n != buf_len)
  LOG(ERROR," : key error\n");
if (key[0] & 0x80)
  LOG(DEBUG, "00\n");

stored_CA_pubKeyLen = EVP_PKEY_size(X509_get_pubkey(x509));

For Verification I went through different approaches but I am unable to verify:

a)

i_x509_verify = X509_verify(cert_x509, ca_pubkey);

b)

/* verify the signature */
int iRet1, iRet2, iReason;
iRet1 = EVP_VerifyInit(&md_ctx, EVP_sha1());
iRet2 = EVP_VerifyUpdate(&md_ctx, cert_code, cert_code_len);
rv = EVP_VerifyFinal(&md_ctx, (const unsigned char *)stored_CA_pubKey,
     stored_CA_pubKeyLen, cert_pubkey);

NOTE : cert_code and stored_CA_pubKey are unsigned char buffers.

Canaster answered 3/5, 2010 at 6:55 Comment(0)
A
12

I use following code for verifying a certificate

init CertStore:

X509_STORE* m_store = X509_STORE_new();
X509_LOOKUP* m_lookup = X509_STORE_add_lookup(m_store,X509_LOOKUP_file());    
X509_STORE_load_locations(m_store, "CAFile.pem", NULL);
X509_STORE_set_default_paths(m_store);
X509_LOOKUP_load_file(m_lookup,"CAFile.pem",X509_FILETYPE_PEM)
// alternative lookup by hashdir
// X509_LOOKUP* m_lookup=X509_STORE_add_lookup(m_store,X509_LOOKUP_hash_dir());

VerifyCert:

X509_STORE_CTX *storeCtx = X509_STORE_CTX_new();
X509_STORE_CTX_init(storeCtx,m_store,cert,NULL);
X509_STORE_CTX_set_flags(storeCtx, X509_V_FLAG_CB_ISSUER_CHECK);
if (X509_verify_cert(storeCtx) == 1)
{
  printf("success");
}
else
{
  printf("Verificatione rror: %s",X509_verify_cert_error_string(X509_STORE_CTX_get_error(storeCtx)));
}
X509_STORE_CTX_free(storeCtx);

you also need to cleanup m_store

if(m_store != NULL)
{
   X509_STORE_free(m_store);
   m_store = NULL;
}
Amieeamiel answered 3/5, 2010 at 7:10 Comment(4)
in init cert store 2 line llookup is used but declared in 5th line... how this code is working..? pls give the full codeIdio
thx Balamurugan, i copied just the relevant pieces of the code, the full code would be to complex. :) The second init of lookup is an alternative where the ca files are stored in an hash directory.Amieeamiel
You should use X509_STORE_CTX_get_error(storeCtx) instead of storeCtx->error; the latter is more fragile due to ABI changes.Darwin
You are right, X509_STORE_CTX_get_error(storeCtx) is the cleaner way of getting the error. I changed the code according to your suggestionAmieeamiel
M
5

Take a look at my self-answered question: https://mcmap.net/q/471616/-how-do-you-verify-a-public-key-was-issued-by-your-private-ca it goes a long way to doing what you need.

Mayberry answered 7/8, 2010 at 16:6 Comment(0)
C
2
X509_STORE* m_store = NULL;

X509_LOOKUP *m_lookup = NULL;
X509_STORE_CTX *storeCtx = NULL;
m_store = X509_STORE_new();
if(NULL == m_store) goto exit;
m_lookup = X509_STORE_add_lookup(m_store, X509_LOOKUP_file());
if(NULL == m_lookup) goto exit;
X509_STORE_load_locations(m_store, CA_CERT_PATH, NULL);
X509_STORE_set_default_paths(m_store);
X509_LOOKUP_load_file(m_lookup,CA_CERT_PATH, X509_FILETYPE_ASN1);
m_lookup = X509_STORE_add_lookup(m_store, X509_LOOKUP_hash_dir());
if(NULL == m_lookup) goto exit;
storeCtx = X509_STORE_CTX_new();
if(NULL == storeCtx) goto exit;
X509_STORE_CTX_init(storeCtx,m_store,cer_x509,NULL);
X509_STORE_CTX_set_flags(storeCtx, /*X509_V_FLAG_CHECK_SS_SIGNATURE*/0x4000);
if (X509_verify_cert(storeCtx) == 1)
{
printf("success\n");
}
else
{
printf("Verification error: %s\n",X509_verify_cert_error_string(storeCtx->error));
}
exit:
    if(NULL != storeCtx) X509_STORE_CTX_free(storeCtx);
    if(m_store != NULL)
    {
        X509_STORE_free(m_store);
        m_store = NULL;
    }

After Doing this also I am unable to verify Self signed certificate

Canaster answered 3/5, 2010 at 12:23 Comment(1)
I have tried something similar but the self-signed cert verification is not working. Even manually installed the cert in my machine using the "Manage Computer Certificates" snap-in. Any help would be appreciated. X509_STORE_CTX* ctx; ctx = X509_STORE_CTX_new(); X509_STORE* store = X509_STORE_new(); X509_STORE_add_cert(store, certificate); X509_STORE_CTX_init(ctx, store, certificate, NULL); X509_VERIFY_PARAM* param = NULL; param = X509_VERIFY_PARAM_new(); if (param) {X509_VERIFY_PARAM_set_flags(param,X509_V_FLAG_CHECK_SS_SIGNATURE);} status = X509_verify_cert(ctx);Marlowe

© 2022 - 2024 — McMap. All rights reserved.