This is very similar to other questions but the ones I've looked at either don't have an answer or don't quite ask the same question. I have a self-signed CA certificate, and two other certificates that are signed with that CA certificate. I'm fairly sure the certificates are correct, because 'openssl verify' works:
$ openssl verify -CAfile ca.pem server.pem
server.pem: OK
(The above is from memory, I don't have them in front of me, so it may be slightly off).
Now I want to verify the certificates programatically. I have a utility function with pseudocode below:
int verify_cert(X509 *cert, X509 *cacert)
{
int ret;
X509_STORE *store;
X509_STORE_CTX *ctx;
store = X509_STORE_new();
X590_STORE_add_cert(store, cacert);
ctx = X509_STORE_CTX_new();
X509_STORE_CTX_init(ctx, store, cert, NULL);
ret = X590_verify_cert(ctx);
/* check for errors and clean up */
}
My problem is that the above code always returns 'failed to find issuer certificate'. What have I done wrong? I believe I am creating a new store, adding the cacert, creating a new context, and adding the child cert to be verified to the context with a pointer to the store which contains the CA. I'm pretty obviously doing something wrong, but I'm unsure what.
Any ideas?
Update: I'm aware I can save these certs to disk and use something like X509_LOOKUP_file or something similar. I'm looking for a solution that doesn't touch the disk unnecessarily.
You can use the normal validation routines (see How do you verify a public key was issued by your private CA?), like the -verify function in OpenSSL does. You need to create a lookup method (X509_LOOKUP_METHOD) like X509_LOOKUP_file(), but which works with a character string instead of a filename. The code for X509_LOOKUP_buffer() is as follows.
Header file by_buffer.h:
The c program by_buffer.c:
Routine in C++ which calls the above routines:
I encountered this problem myself and started off with code very close to the OP. My certificate chain included 3 certificates: Certificate 1 (root-ca) Issuer: root-ca Subject: root-ca Certificate 2 (signing-ca) Issuer: root-ca Subject: signing-ca Certificate 3 (device) Issuer: signing-ca Subject: device
I wanted to verify the device certificate. My ca.pem equivalent (wrt OP) contained the root-ca and signing-ca.
The X509_verify_cert function needs the entire certificate chain all the way to the root (root-ca & signing-ca) in the X509_store.
Below is my code that works for me. Checks on return values were omitted to lean the code down.
I didn't need to create any lookup methods. The key for me was looping through my certificates from my string in memory so I had all the certificates I need to complete the chain. The string is equivalent to what I would have fed into openssl verify for the option -CAfile.
Also, make sure your X509 pointers are not null when the are used.
I think, you can use "X509_STORE_set_verify_cb" to add a callback to identify the actual error:
Unless we know the error code it is difficult to guess the actual problem. The code otherwise looks OK.
A possible answer (don't have the rep points to add a comment, sorry): the manpage for
SSL_CTX_load_verify_locations(3)
says,(Failure to match parens theirs, not mine.)
Which seems to mean that, as an alternative to
SSL_CTX_load_verify_locations(3)
, it should be possible to useSSL_CTX_add_extra_chain_cert(3)
orSSL_CTX_use_certificate(3)
-- both of which take aX509 *
arg. Thus obviating the need for Mr Ed's solution as seen above.Please take a look at
SSL_CTX_load_verify_locations ()
function: http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.htmlYou can generate a CA certificate file containing both ca.pem server.pem:
And then set
CAfile
variable to point toCAfile.pem
file.Hope it helps !