Commit 2f043896 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

*BIG* verify code reorganisation.

The old code was painfully primitive and couldn't handle
distinct certificates using the same subject name.

The new code performs several tests on a candidate issuer
certificate based on certificate extensions.

It also adds several callbacks to X509_VERIFY_CTX so its
behaviour can be customised.

Unfortunately some hackery was needed to persuade X509_STORE
to tolerate this. This should go away when X509_STORE is
replaced, sometime...

This must have broken something though :-(
parent 29eb7d9c
Loading
Loading
Loading
Loading
+52 −1
Original line number Diff line number Diff line
@@ -4,6 +4,57 @@

 Changes between 0.9.5a and 0.9.6  [xx XXX 2000]
  
   *) Phase 2 verify code reorganisation. The certificate
      verify code now looks up an issuer certificate by a
      number of criteria: subject name, authority key id
      and key usage. It also verifies self signed certificates
      by the same criteria. The main comparison function is
      X509_check_issued() which performs these checks.
 
      Lot of changes were necessary in order to support this
      without completely rewriting the lookup code.
 
      Authority and subject key identifier are now cached.
 
      The LHASH 'certs' is X509_STORE has now been replaced
      by a STACK_OF(X509_OBJECT). This is mainly because an
      LHASH can't store or retrieve multiple objects with
      the same hash value.

      As a result various functions (which were all internal
      use only) have changed to handle the new X509_STORE
      structure. This will break anything that messed round
      with X509_STORE internally.
 
      The functions X509_STORE_add_cert() now checks for an
      exact match, rather than just subject name.
 
      The X509_STORE API doesn't directly support the retrieval
      of multiple certificates matching a given criteria, however
      this can be worked round by performing a lookup first
      (which will fill the cache with candidate certificates)
      and then examining the cache for matches. This is probably
      the best we can do without throwing out X509_LOOKUP
      entirely (maybe later...).
 
      The X509_VERIFY_CTX structure has been enhanced considerably.
 
      All certificate lookup operations now go via a get_issuer()
      callback. Although this currently uses an X509_STORE it
      can be replaced by custom lookups. This is a simple way
      to bypass the X509_STORE hackery necessary to make this
      work and makes it possible to use more efficient techniques
      in future. A very simple version which uses a simple
      STACK for its trusted certificate store is also provided
      using X509_STORE_CTX_trusted_stack().
 
      The verify_cb() and verify() callbacks now have equivalents
      in the X509_STORE_CTX structure.
 
      X509_STORE_CTX also has a 'flags' field which can be used
      to customise the verify behaviour.
      [Steve Henson]
 
  *) Add new PKCS#7 signing option PKCS7_NOSMIMECAP which 
     excludes S/MIME capabilities.
     [Steve Henson]
+1 −1
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ my %table=(
"debug-rse","cc:-DTERMIOS -DL_ENDIAN -pipe -O -g -ggdb3 -Wall::(unknown)::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}",
"debug-bodo",	"gcc:-DL_ENDIAN -DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG_ALL -DBIO_PAIR_DEBUG -g -m486 -pedantic -Wshadow -Wall::-D_REENTRANT::BN_LLONG ${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}",
"debug-ulf",	"gcc:-DL_ENDIAN -DREF_CHECK -DCONF_DEBUG -DBN_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG_ALL -g -O2 -m486 -Wall -Werror -Wshadow -pipe::-D_REENTRANT::${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}",
"debug-steve",	"gcc:-DL_ENDIAN -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG_ALL -DPEDANTIC -g -O2 -m486 -pedantic -Wall -Werror -Wshadow -pipe::-D_REENTRANT::${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}",
"debug-steve",	"gcc:-DL_ENDIAN -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DDEBUG_SAFESTACK -DCRYPTO_MDEBUG_ALL -DPEDANTIC -g -O2 -m486 -pedantic -Wall -Werror -Wshadow -pipe::-D_REENTRANT::${x86_gcc_des} ${x86_gcc_opts}:${x86_elf_asm}",
"debug-levitte-linux-elf","gcc:-DUSE_ALLOCATING_PRINT -DRL_DEBUG -DREF_CHECK -DCONF_DEBUG -DBN_CTX_DEBUG -DCRYPTO_MDEBUG -DNO_ASM -DL_ENDIAN -DTERMIO -D_POSIX_SOURCE -ggdb -g3 -m486 -pedantic -ansi -Wall -Wshadow -Wid-clash-31 -pipe::-D_REENTRANT:-ldl:::::::::::dlfcn",
"dist",		"cc:-O::(unknown):::::",

+21 −6
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@
#define PROG	verify_main

static int MS_CALLBACK cb(int ok, X509_STORE_CTX *ctx);
static int check(X509_STORE *ctx,char *file, STACK_OF(X509)*other, int purpose);
static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, int purpose);
static STACK_OF(X509) *load_untrusted(char *file);
static int v_verbose=0;

@@ -81,8 +81,8 @@ int MAIN(int argc, char **argv)
	int i,ret=1;
	int purpose = -1;
	char *CApath=NULL,*CAfile=NULL;
	char *untfile = NULL;
	STACK_OF(X509) *untrusted = NULL;
	char *untfile = NULL, *trustfile = NULL;
	STACK_OF(X509) *untrusted = NULL, *trusted = NULL;
	X509_STORE *cert_ctx=NULL;
	X509_LOOKUP *lookup=NULL;

@@ -132,6 +132,11 @@ int MAIN(int argc, char **argv)
				if (argc-- < 1) goto end;
				untfile= *(++argv);
				}
			else if (strcmp(*argv,"-trusted") == 0)
				{
				if (argc-- < 1) goto end;
				trustfile= *(++argv);
				}
			else if (strcmp(*argv,"-help") == 0)
				goto end;
			else if (strcmp(*argv,"-verbose") == 0)
@@ -179,10 +184,18 @@ int MAIN(int argc, char **argv)
		}
	}

	if (argc < 1) check(cert_ctx, NULL, untrusted, purpose);
	if(trustfile) {
		if(!(trusted = load_untrusted(trustfile))) {
			BIO_printf(bio_err, "Error loading untrusted file %s\n", trustfile);
			ERR_print_errors(bio_err);
			goto end;
		}
	}

	if (argc < 1) check(cert_ctx, NULL, untrusted, trusted, purpose);
	else
		for (i=0; i<argc; i++)
			check(cert_ctx,argv[i], untrusted, purpose);
			check(cert_ctx,argv[i], untrusted, trusted, purpose);
	ret=0;
end:
	if (ret == 1) {
@@ -197,10 +210,11 @@ end:
	}
	if (cert_ctx != NULL) X509_STORE_free(cert_ctx);
	sk_X509_pop_free(untrusted, X509_free);
	sk_X509_pop_free(trusted, X509_free);
	EXIT(ret);
	}

static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, int purpose)
static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, int purpose)
	{
	X509 *x=NULL;
	BIO *in=NULL;
@@ -242,6 +256,7 @@ static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain, int purpos
		goto end;
		}
	X509_STORE_CTX_init(csc,ctx,x,uchain);
	if(tchain) X509_STORE_CTX_trusted_stack(csc, tchain);
	if(purpose >= 0) X509_STORE_CTX_set_purpose(csc, purpose);
	i=X509_verify_cert(csc);
	X509_STORE_CTX_free(csc);
+8 −3
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@
#include <openssl/evp.h>
#include <openssl/asn1_mac.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>

static int x509_meth_num = 0;
static STACK_OF(CRYPTO_EX_DATA_FUNCS) *x509_meth = NULL;
@@ -114,11 +115,13 @@ X509 *X509_new(void)
	ASN1_CTX c;

	M_ASN1_New_Malloc(ret,X509);
	ret->references=1;
	ret->valid=0;
	ret->references=1;
	ret->name = NULL;
	ret->ex_flags = 0;
	ret->ex_pathlen = -1;
	ret->name=NULL;
	ret->skid = NULL;
	ret->akid = NULL;
	ret->aux = NULL;
	M_ASN1_New(ret->cert_info,X509_CINF_new);
	M_ASN1_New(ret->sig_alg,X509_ALGOR_new);
@@ -152,6 +155,8 @@ void X509_free(X509 *a)
	X509_ALGOR_free(a->sig_alg);
	M_ASN1_BIT_STRING_free(a->signature);
	X509_CERT_AUX_free(a->aux);
	ASN1_OCTET_STRING_free(a->skid);
	AUTHORITY_KEYID_free(a->akid);

	if (a->name != NULL) OPENSSL_free(a->name);
	OPENSSL_free(a);
+20 −0
Original line number Diff line number Diff line
@@ -864,6 +864,26 @@ STACK_OF(type) \
#define sk_X509_NAME_ENTRY_pop(st) SKM_sk_pop(X509_NAME_ENTRY, (st))
#define sk_X509_NAME_ENTRY_sort(st) SKM_sk_sort(X509_NAME_ENTRY, (st))

#define sk_X509_OBJECT_new(st) SKM_sk_new(X509_OBJECT, (st))
#define sk_X509_OBJECT_new_null() SKM_sk_new_null(X509_OBJECT)
#define sk_X509_OBJECT_free(st) SKM_sk_free(X509_OBJECT, (st))
#define sk_X509_OBJECT_num(st) SKM_sk_num(X509_OBJECT, (st))
#define sk_X509_OBJECT_value(st, i) SKM_sk_value(X509_OBJECT, (st), (i))
#define sk_X509_OBJECT_set(st, i, val) SKM_sk_set(X509_OBJECT, (st), (i), (val))
#define sk_X509_OBJECT_zero(st) SKM_sk_zero(X509_OBJECT, (st))
#define sk_X509_OBJECT_push(st, val) SKM_sk_push(X509_OBJECT, (st), (val))
#define sk_X509_OBJECT_unshift(st, val) SKM_sk_unshift(X509_OBJECT, (st), (val))
#define sk_X509_OBJECT_find(st, val) SKM_sk_find(X509_OBJECT, (st), (val))
#define sk_X509_OBJECT_delete(st, i) SKM_sk_delete(X509_OBJECT, (st), (i))
#define sk_X509_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_OBJECT, (st), (ptr))
#define sk_X509_OBJECT_insert(st, val, i) SKM_sk_insert(X509_OBJECT, (st), (val), (i))
#define sk_X509_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_OBJECT, (st), (cmp))
#define sk_X509_OBJECT_dup(st) SKM_sk_dup(X509_OBJECT, st)
#define sk_X509_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(X509_OBJECT, (st), (free_func))
#define sk_X509_OBJECT_shift(st) SKM_sk_shift(X509_OBJECT, (st))
#define sk_X509_OBJECT_pop(st) SKM_sk_pop(X509_OBJECT, (st))
#define sk_X509_OBJECT_sort(st) SKM_sk_sort(X509_OBJECT, (st))

#define sk_X509_PURPOSE_new(st) SKM_sk_new(X509_PURPOSE, (st))
#define sk_X509_PURPOSE_new_null() SKM_sk_new_null(X509_PURPOSE)
#define sk_X509_PURPOSE_free(st) SKM_sk_free(X509_PURPOSE, (st))
Loading