How to verify a X509 certificate in C - c

I have a certificate in X509 format. this a input parameters in a function.
What I would like to do is to verify the validity of the certificate.
How can it be done?
X509_verify_cert();
I found this function, but this does not accept a X509* certificate, it accepts X509_store and I only have a X509.
Thanks
best regards.

I am here just to post my answer as I found it with the above comments.
I had no certificate chain, so in the work I'm doing I only have a certificate generated by me programatically. I wanted to check the validity of it, so I created the following function, which checks the certificate against itself in other to verify the validity of it.
void check_certificate_validaty(X509* certificate)
{
int status;
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);
status = X509_verify_cert(ctx);
if(status == 1)
{
printf("Certificate verified ok\n");
}else
{
printf("%s\n", X509_verify_cert_error_string(ctx->error));
}
}
Hope this helps someone :)

See the documentation here.
You need to create a certificate store using X509_STORE_CTX_new.
Then add certificate chain using X509_STORE_CTX_set_chain. Add trusted root certificate using X509_STORE_CTX_trusted_stack.
Finally add certificate to be verified using X509_STORE_CTX_set_cert.
After that call X509_verify_cert.
I hope this will help you to start on this.

To verify a certificate signature, you need the public key of an issuer certificate. This issuer certificate's signature is verified with another issuing certificate (or trusted root certificate). Thus if a certificate's signature verifies all the way up a chain to a trusted root, then that certificate is considered trusted.
Self-signed certificates' signatures are verified using their own public key, like the example below:
int verify_cert(const char* pem_c_str)
{
BIO *bio_mem = BIO_new(BIO_s_mem());
BIO_puts(bio_mem, pem_c_str);
X509 * x509 = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL);
EVP_PKEY *pkey=X509_get_pubkey(x509);
int r= X509_verify(x509, pkey);
EVP_PKEY_free(pkey);
BIO_free(bio_mem);
X509_free(x509);
return r;
}
from: http://www.zedwood.com/article/openssl-c-verify-self-signed-certificate-signature

Related

Convert X509_STORE_load_locations() call to load data from Memory

How can I convert the code below to load the file "cabundle.pem" from memory? The code is used in certificate verification (Source)
const char ca_bundlestr[] = "./cabundle.pem";
ret = X509_STORE_load_locations(store, ca_bundlestr, NULL);`
So what I currently did is put the cabundle.pem in string array and then add the cert to the store but it doesnt work since what I think I need to do is add it to the store using X509_STORE_CTX_trusted_stack but I do not know how to use STACK_OF(X509) I tried searching but I cant find anything.
const char ca_bundle[] = "-----BEGIN CERTIFICATE-----\n"
"MIIImDCCCD2gAwIBAgIRAMch/W0685E2zrArUB/79kUwCgYIKoZIzj0EAwIwgZIx\n"
"MIIImDCCC...............................................AwIwgZIx\n"
"CzAJBgNVB..........................................0ZXIxEDAOBgNV\n"
"-----END CERTIFICATE-----\n";
BIO *bio;
X509 *cert;
bio = BIO_new(BIO_s_mem());
BIO_puts(bio, ca_bundle);
cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
X509_STORE_add_cert(store, cert);
So how can I load my string array ca_bundle into a STACK_OF(X509) variable? Or if there is another way to do this please let me know. Thanks
I asked too early. I just found the answer to my question. Since the cabundle.pem contains more than 1 certificate you need to do it in a loop and read the next certificate then add it again to the store. You do not need the X509_STORE_CTX_trusted_stack since adding all the certificates to the store acts the same way as calling X509_STORE_load_locations
while (cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) {
X509_STORE_add_cert(store, cert);
}

Openssl how to find out what the bit size of the public key in an X509 certificate is

If I have an X509* that openssl has provided me, what's the best way to figure out the bit-ness of the RSA public key in the certificate? I can't quite figure this out. I'm pretty sure that if I'm in the SSL certificate verification callback, I can get the X509 ptr with
X509 * cert = X509_STORE_CTX_get_current_cert(the_x509_store_ctx);
and I would surmise I get the public key like this
EVP_PKEY *public_key = X509_get_pubkey(cert);
and then I need to check whether it's RSA, presumably?
if (public_key && (EVP_PKEY_RSA == public_key->type))
and once I know that I got a public key back and that it's RSA, I'd like to do this:
int key_length = BN_num_bits(public_key->pkey.rsa->n);
but I've found that while this works quite nicely on openssl 0.9.8, on 1.0.1h it segfaults on Windows. The BIGNUM 'n' doesn't seem to be valid - the data ptr in it has a garbage pointer.
Any idea what's wrong?
As already suggested, to get the RSA modulus size in bytes (so not "bit size"...) use:
EVP_PKEY * public_key = X509_get_pubkey(cert);
RSA *rsa_key = EVP_PKEY_get1_RSA(public_key);
int key_length = RSA_size(rsa_key);
...
RSA_free(rsa_key);

Extracting the public certificate from a certificate

I would like to programmatically generate a certificate that contain only the public key using openssl.
So I basically need to do the following but using code.
openssl x509 -in certificate.crt -pubkey
Digging a bit it seem that I need to create a new certificate and copy all the information except the private key in it.
X509 * pNewKey = X509_new();
... Copy all the needed information ...
PEM_write_bio_X509(bioKey, &pNewKey, NULL, NULL);
Does someone have a better method?
I would like to programmatically generate a certificate that contain only the public key
To set the public key, take your public key in EVP_PKEY format and call X509_set_pubkey. Building upon your example code:
X509* x509 = X509_new();
EVP_PKEY* pkey = /***/;
int rc = X509_set_pubkey(x509, pkey);
ASSERT(rc == 1);
BIO* bio = BIO_new_file("filename.txt", "w");
ASSERT(bio != NULL);
rc = PEM_write_bio_X509(bio, x509, NULL, NULL);
ASSERT(rc == 1);
...
BIO_free(bio);
EVP_PKEY_free(pkey);
X509_free(x509);
For completeness, OpenSSL will save a certificate with no attributes, no version, no public key, and no signature.
So I basically need to do the following but using code.
openssl x509 -in certificate.crt -pubkey
OK, this is a different question. The above command will print the public key.
Use x509_get_pubkey:
EVP_PKEY* pkey = X509_get_pubkey(X509* x509);
Once you have the EVP_PKEY, you can get the type. You need to supply this function because OpenSSL does not provide it:
int EVP_PKEY_get_type(EVP_PKEY *pkey)
{
AC_ASSERT(pkey);
if (!pkey)
return NID_undef;
return EVP_PKEY_type(pkey->type);
}
Then, depending on the type, you can print the key:
if(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA2)
{
RSA* rsa = EVP_PKEY_get1_RSA(pkey);
RSA_print_fp(stdout, rsa, 0);
RSA_free(rsa);
}
...
You have to break out the keys by type and then call the respective XXX_print_fp because OpenSSL does not provide an EVP_PKEY_print_fp.
The get1 in EVP_PKEY_get1_RSA means the reference count on the key is bumped. So you have to call a *_free on it. A get0 does not bump the reference count, and does not need a call to *_free.

OpenSSL - find error depth in certificate chain

I am writing a C program to retrieve and verify an x509 certificate chain using OpenSSL. This is my first time programming in C and am relying heavily on the tutorial at http://www.ibm.com/developerworks/linux/library/l-openssl/
I am able to retrieve any error code from the connection using the code below:
if (SSL_get_verify_result(ssl) != X509_V_OK)
{
printf("\nError verifying certificate\n");
fprintf(stderr, "Error Code: %lu\n", SSL_get_verify_result(ssl));
}
however I also need to know which certificate is the offending one. Is there are way to determine the chain depth of the error like the command line s_client? Any example code would be greatly appreciated.
I found my answer in "Network Security with OpenSSL" by Chandra, Messier and Viega.
It uses SSL_CTX_set_verify to designate a callback function that gets run after the verification routine for each certificate in the chain.
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
int verify_callback(int ok, X509_STORE_CTX * store)
{
if (!ok) //if this particular cert had an error
{
int depth = X509_STORE_CTX_get_error_depth(store);
int err = X509_STORE_CTX_get_error(store);
}
}

Extracting client certificate & private key from .p12 file

Can anybody tell me how to use
PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12);
int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca);
any documenatation reference will also work.
Without error-checking:
FILE *p12_file;
PKCS12 *p12_cert = NULL;
EVP_PKEY *pkey;
X509 *x509_cert;
STACK_OF(X509) *additional_certs = NULL;
p12_file = fopen("foo.p12", "rb");
d2i_PKCS12_fp(p12_file, &p12_cert);
fclose(p12_file);
PKCS12_parse(p12_cert, "password", &pkey, &x509_cert, &additional_certs);
The private key is now in pkey, the certificate in x509_cert and any additional certificates in additional_certs.
Here is openssl's page for parse: PKCS12_parse.html
Here is Apple's link to using openssl libs: see PKCS#12, Section 2: I/O
From Apple's site, here are the descriptions:
int PKCS12_parse(PKCS12 *p12, char *pass, EVP_PKEY **pkey, X509 **cert,
STACK **ca);
This function takes a PKCS12 structure and a password (ASCII, null terminated)
and returns the private key, the corresponding certificate and any CA
certificates. If any of these is not required it can be passed as a NULL.
The 'ca' parameter should be either NULL, a pointer to NULL or a valid STACK
structure. Typically to read in a PKCS#12 file you might do:
p12 = d2i_PKCS12_fp(fp, NULL);
PKCS12_parse(p12, password, &pkey, &cert, NULL); /* CAs not wanted */
PKCS12_free(p12);

Resources