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;

}

Reply via email to