Hi,
I have following set of certificates with X509 extensions defined for code
signing in PKCS7 format.
Root CA - Key usage (critical): Certificate Sign, CRL Sign
CVC Sub-CA - Key usage (critical): Certificate Sign, CRL Sign
CVC cert - Key usage(critical): Digital Signature, Key Encipherment. Extended
Key Usage(critical): Code Sigining
PKCS#7 signature includes CVC sub-CA and CVC certs. When I verify the signature
using PKCS7_verify() I am getting
error: "unsupported certificate purpose"
As a work-around suggested by Dr.Stephen I tried setting purpose to any and it
works fine using following command line:
openssl smime -verify -CAfile Root-CA -purpose any -inform PEM -in pk7blob
-content data-signed
But fails when using Openssl API's and the error is
X509_STORE_CTX_purpose_inherit: unknown purpose id.
Following is the code snippet. Most of it is taken from PKCS7_verify() itself
in pkcs7_smime.c
void my_verify_api(PKCS7 *pkcs7, unsigned char *signed_data, int s_len)
{
/* Root CA */
static unsigned char my_root_ca[900]={......};
BIO *bio_t;
const unsigned char *der_cert = my_root_ca;
X509_STORE *cert_store = NULL;
X509 *x509 = NULL;
STACK_OF(X509) *signers;
X509 *signer;
X509_STORE_CTX cert_ctx;
int i, k, num_signers;
if (!bio_t = BIO_new_mem_buf((void *)signed_data, s_len))) {
printf("BIO_new_mem_buf failed\n\n");
goto end;
}
OpenSSL_add_all_algorithms();
x509 = d2i_X509(NULL, &der_cert, sizeof(my_root_ca));
if (x509 == NULL) {
printf("x509 is NULL.\n");
goto end;
}
cert_store=X509_STORE_new();
if (cert_store == NULL) {
printf("Failed to create new cert store using X509_STORE_new().\n");
goto end;
}
X509_STORE_add_cert(cert_store,x509);
signers = PKCS7_get0_signers(pkcs7, NULL, 0);
if (!signers) {
printf("Error getting signers--\n");
goto end;
}
num_signers = sk_X509_num(signers);
printf("num_signers: %d\n", num_signers);
for (k = 0; k < num_signers; k++) {
signer = sk_X509_value(signers, k);
if (!X509_STORE_CTX_init(&cert_ctx, cert_store, signer,
pkcs7->d.sign->cert)) {
printf("X509_STORE_CTX_init failed.\n");
sk_X509_free(signers);
goto end;
}
X509_STORE_CTX_set_purpose(&cert_ctx, X509_PURPOSE_ANY);
i = X509_verify_cert(&cert_ctx);
X509_STORE_CTX_cleanup(&cert_ctx);
if (i <= 0) {
unsigned long e;
const char *file = NULL, *data = NULL;
int line, flgs;
while ((e = ERR_get_error_line_data(&file, &line, &data, &flgs))) {
printf("Error: %d\nError String: %s\n", e, ERR_error_string(e,
NULL));
if (data) {
printf("data: %s\n", data);
}
}
ERR_clear_error();
sk_X509_free(signers);
goto end;
} else {
printf("Certificate got verified--\n\n");
}
}
sk_X509_free(signers);
end:
if (x509 != NULL) {
X509_free(x509);
}
if (cert_store != NULL) {
X509_STORE_free(cert_store);
}
if (bio_t) {
BIO_flush(bio_t);
BIO_free_all(bio_t);
}
EVP_cleanup();
}
Am I doing something wrong here?
Any help is appreciated.
Thanks,
Prkj