Hello,
As a new user of openssl, I am trying to figure out the certificate verification process. For this purpose, I created a self-signed "root" CA, put it in a "trusted" directory and used it to sign a user certificate. I then used the following command to test the validity of the user certificate and obtained the response below. Everything seems OK till this point. >openssl verify -verbose -CApath trusted -purpose any alicecert.pem alicecert.pem: OK Now I would like to write a C program doing the same. For this, I used Viega and Messier's Secure Programming Cookbook, recipe 10.5 (BTW, I am not sure the workaround they propose there is still necessary with latest versions of openssl – any hint welcome). The problem is that, when verifying the same certificate as before, I now get a "certificate signature failure" error message, and cannot figure out what the problem is. I append my code below (OK, I hate posting long code for review, because I understand it represents significant work for the reader, but most of it is simply borrowed from the cookbook, my (apparently bad) contribution is in the main() function. Any help would be greatly appreciated. Of course, feel free to ask any additional information I should provide (like the certificates themselves, for example). And apologies for this newbie question: I am afraid the lack of documentation makes the newcomer's life a bit tricky. -------------------------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/evp.h> #include <openssl/x509.h> #include <openssl/pem.h> #include <openssl/err.h> #define PATH "certificates\\" typedef int (*spc_x509verifycallback_t)(int,X509_STORE_CTX *); typedef struct { char *cafile; char *capath; char *crlfile; spc_x509verifycallback_t callback; STACK_OF(X509) *certs; STACK_OF(X509_CRL) *crls; char *use_certfile; STACK_OF(X509) *use_certs; char *use_keyfile; EVP_PKEY *use_key; int flags; } spc_x509store_t; void spc_init_x509store(spc_x509store_t *spc_store) { spc_store->cafile=0; spc_store->capath=0; spc_store->crlfile=0; spc_store->callback=0; spc_store->certs=sk_X509_new_null(); spc_store->crls=sk_X509_CRL_new_null(); spc_store->use_certfile=0; spc_store->use_certs=sk_X509_new_null(); spc_store->use_keyfile=0; spc_store->use_key=0; spc_store->flags=0; } void spc_cleanup_x509store(spc_x509store_t *spc_store) { if (spc_store->cafile) free(spc_store->cafile); if (spc_store->capath) free(spc_store->capath); if (spc_store->crlfile) free(spc_store->crlfile); if (spc_store->use_certfile) free(spc_store->use_certfile); if (spc_store->use_keyfile) free(spc_store->use_keyfile); if (spc_store->use_key) free (spc_store->use_key); sk_X509_free(spc_store->certs); sk_X509_free(spc_store->crls); sk_X509_free(spc_store->use_certs); } void spc_x509store_setcafile(spc_x509store_t *spc_store, char *cafile) { if (spc_store->cafile) free(spc_store->cafile); spc_store->cafile=(cafile ? strdup(cafile) : 0); } void spc_x509store_setcapath(spc_x509store_t *spc_store, char *capath) { if (spc_store->capath) free(spc_store->capath); spc_store->capath=(capath ? strdup(capath) : 0); } void spc_x509store_setcrlfile(spc_x509store_t *spc_store, char *crlfile) { if (spc_store->crlfile) free(spc_store->crlfile); spc_store->crlfile=(crlfile ? strdup(crlfile) : 0); } void spc_x509store_addcert(spc_x509store_t *spc_store,X509 *cert) { sk_X509_push(spc_store->certs,cert); } void spc_x509store_addcrl(spc_x509store_t *spc_store,X509_CRL *crl) { sk_X509_CRL_push(spc_store->crls,crl); } void spc_x509store_setcallback(spc_x509store_t *spc_store,spc_x509verifycallback_t callback) { spc_store->callback=callback; } #define SPC_X509STORE_NO_DEFAULT_CAFILE 0X01 #define SPC_X509STORE_NO_DEFAULT_CAPATH 0X02 void spc_x509store_setflags(spc_x509store_t *spc_store,int flags) { spc_store->flags|=flags; } void spc_x509store_clearflags(spc_x509store_t *spc_store,int flags) { spc_store->flags&=~flags; } int spc_verify_callback(int ok, X509_STORE_CTX *store) { if (!ok) { fprintf(stderr,"Error: %s\n",X509_verify_cert_error_string(store->error)); printf("Error: %s\n",X509_verify_cert_error_string(store->error)); } return ok; } X509_STORE *spc_create_x509store(spc_x509store_t *spc_store) { int i; X509_STORE *store; X509_LOOKUP *lookup; store=X509_STORE_new(); if (spc_store->callback) X509_STORE_set_verify_cb_func(store,spc_store->callback); else X509_STORE_set_verify_cb_func(store,spc_verify_callback); if (!(lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file()))) goto error_exit; if (!spc_store->cafile) { if (!(spc_store->flags & SPC_X509STORE_NO_DEFAULT_CAFILE)) X509_LOOKUP_load_file(lookup,0,X509_FILETYPE_DEFAULT); } else if(!X509_LOOKUP_load_file(lookup,spc_store->cafile,X509_FILETYPE_PEM)) goto error_exit; if (spc_store->crlfile) { if(!X509_load_crl_file(lookup,spc_store->crlfile,X509_FILETYPE_PEM)) goto error_exit; X509_STORE_set_flags(store,X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } if (!(lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir()))) goto error_exit; if (!spc_store->capath) { if (!(spc_store->flags & SPC_X509STORE_NO_DEFAULT_CAPATH)) X509_LOOKUP_add_dir(lookup,0,X509_FILETYPE_DEFAULT); } else if(!X509_LOOKUP_add_dir(lookup,spc_store->capath,X509_FILETYPE_PEM)) goto error_exit; for (i=0;i<sk_X509_num(spc_store->certs);i++) if(!X509_STORE_add_cert(store,sk_X509_value(spc_store->certs,i))) goto error_exit; for (i=0;i<sk_X509_CRL_num(spc_store->crls);i++) if(!X509_STORE_add_crl(store,sk_X509_CRL_value(spc_store->crls,i))) goto error_exit; return store; error_exit: if (store) X509_STORE_free(store); return 0; } int spc_verify_cert(X509 *cert, spc_x509store_t *spc_store) { int result=-1; X509_STORE *store=0; X509_STORE_CTX *ctx=0; if (!(store=spc_create_x509store(spc_store))) return -1; if ((ctx=X509_STORE_CTX_new())!=0) { if (X509_STORE_CTX_init(ctx,store,cert,0)==1) result=(X509_verify_cert(ctx)==1); X509_STORE_CTX_free(ctx); } X509_STORE_free(store); return result; } int main() { FILE* fd; X509* cert=NULL; X509_NAME *name=NULL; char buf [5000],filename[5000],capath[5000]; spc_x509store_t spc_store; int res; strcpy(filename,PATH); strcat(filename,"alicecert.pem "); fd=fopen(filename,"r"); if (!fd) {printf("Error\n");return -1;} cert=PEM_read_X509(fd,NULL,0,NULL); if (cert == NULL) {ERR_print_errors_fp (stderr);return -1;} fclose (fd); spc_init_x509store(&spc_store); strcpy(capath,PATH); strcat(capath,"trusted"); spc_x509store_setcapath(&spc_store,capath); spc_x509store_setflags(&spc_store,SPC_X509STORE_NO_DEFAULT_CAFILE); spc_x509store_setcallback(&spc_store,spc_verify_callback); res=spc_verify_cert(cert,&spc_store); spc_cleanup_x509store(&spc_store); return 0; }