Initial chain verify code: not tested probably not working
at present. However nothing enables it yet so this doesn't matter :-)
This commit is contained in:
parent
6d3724d3b0
commit
1126239111
17
CHANGES
17
CHANGES
@ -4,8 +4,21 @@
|
||||
|
||||
Changes between 0.9.4 and 0.9.5 [xx XXX 1999]
|
||||
|
||||
*) Support for the authority information access extension. Not
|
||||
very well tested yet.
|
||||
*) Very preliminary certificate chain verify code. Currently just tests
|
||||
the untrusted certificates for consistency with the verify purpose
|
||||
(which is set when the X509_STORE_CTX structure is set up) and checks
|
||||
the pathlength. Totally untested at present: needs some extra
|
||||
functionality in the verify program first. There is a
|
||||
NO_CHAIN_VERIFY compilation option to keep the old behaviour: this is
|
||||
because when it is finally working it will reject chains with
|
||||
invalid extensions whereas before it made no checks at all.
|
||||
|
||||
Also added X509_STORE_CTX_new() and X509_STORE_CTX_free() functions
|
||||
which should be used for version portability: especially since the
|
||||
verify structure is likely to change more often now.
|
||||
[Steve Henson]
|
||||
|
||||
*) Support for the authority information access extension.
|
||||
[Steve Henson]
|
||||
|
||||
*) Modify RSA and DSA PEM read routines to transparently handle
|
||||
|
@ -381,6 +381,17 @@ X509_OBJECT *X509_OBJECT_retrieve_by_subject(LHASH *h, int type,
|
||||
return(tmp);
|
||||
}
|
||||
|
||||
X509_STORE_CTX *X509_STORE_CTX_new(void)
|
||||
{
|
||||
return (X509_STORE_CTX *)Malloc(sizeof(X509_STORE_CTX));
|
||||
}
|
||||
|
||||
void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
|
||||
{
|
||||
X509_STORE_CTX_cleanup(ctx);
|
||||
Free(ctx);
|
||||
}
|
||||
|
||||
void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
||||
STACK_OF(X509) *chain)
|
||||
{
|
||||
@ -389,6 +400,8 @@ void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
||||
ctx->cert=x509;
|
||||
ctx->untrusted=chain;
|
||||
ctx->last_untrusted=0;
|
||||
ctx->chain_purpose=0;
|
||||
ctx->trust_purpose=0;
|
||||
ctx->valid=0;
|
||||
ctx->chain=NULL;
|
||||
ctx->depth=9;
|
||||
|
@ -120,6 +120,12 @@ const char *X509_verify_cert_error_string(long n)
|
||||
return("certificate chain too long");
|
||||
case X509_V_ERR_CERT_REVOKED:
|
||||
return("certificate revoked");
|
||||
case X509_V_ERR_INVALID_CA:
|
||||
return ("invalid CA certificate");
|
||||
case X509_V_ERR_PATH_LENGTH_EXCEEDED:
|
||||
return ("path length constraint exceeded");
|
||||
case X509_V_ERR_INVALID_PURPOSE:
|
||||
return ("unsupported certificate purpose");
|
||||
case X509_V_ERR_APPLICATION_VERIFICATION:
|
||||
return("application verification failure");
|
||||
default:
|
||||
|
@ -67,9 +67,11 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/objects.h>
|
||||
|
||||
static int null_callback(int ok,X509_STORE_CTX *e);
|
||||
static int check_chain_purpose(X509_STORE_CTX *ctx);
|
||||
static int internal_verify(X509_STORE_CTX *ctx);
|
||||
const char *X509_version="X.509" OPENSSL_VERSION_PTEXT;
|
||||
|
||||
@ -290,6 +292,11 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
|
||||
if (!ok) goto end;
|
||||
}
|
||||
|
||||
/* We have the chain complete: now we need to check its purpose */
|
||||
if(ctx->chain_purpose > 0) ok = check_chain_purpose(ctx);
|
||||
|
||||
if(!ok) goto end;
|
||||
|
||||
/* We may as well copy down any DSA parameters that are required */
|
||||
X509_get_pubkey_parameters(NULL,ctx->chain);
|
||||
|
||||
@ -308,6 +315,47 @@ end:
|
||||
return(ok);
|
||||
}
|
||||
|
||||
/* Check a certificate chains extensions for consistency
|
||||
* with the supplied purpose
|
||||
*/
|
||||
|
||||
static int check_chain_purpose(X509_STORE_CTX *ctx)
|
||||
{
|
||||
#ifdef NO_CHAIN_VERIFY
|
||||
return 1;
|
||||
#else
|
||||
int i, ok=0;
|
||||
X509 *x;
|
||||
int (*cb)();
|
||||
cb=ctx->ctx->verify_cb;
|
||||
if (cb == NULL) cb=null_callback;
|
||||
/* Check all untrusted certificates */
|
||||
for(i = 0; i < ctx->last_untrusted; i++) {
|
||||
x = sk_X509_value(ctx->chain, i);
|
||||
if(!X509_check_purpose(x, ctx->chain_purpose, i)) {
|
||||
if(i) ctx->error = X509_V_ERR_INVALID_CA;
|
||||
else ctx->error = X509_V_ERR_INVALID_PURPOSE;
|
||||
ctx->error_depth = i;
|
||||
ctx->current_cert = x;
|
||||
ok=cb(0,ctx);
|
||||
if(!ok) goto end;
|
||||
}
|
||||
/* Check pathlen */
|
||||
if((i > 1) && (x->ex_pathlen != -1)
|
||||
&& (i > (x->ex_pathlen + 1))) {
|
||||
ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
|
||||
ctx->error_depth = i;
|
||||
ctx->current_cert = x;
|
||||
ok=cb(0,ctx);
|
||||
if(!ok) goto end;
|
||||
}
|
||||
}
|
||||
ok = 1;
|
||||
end:
|
||||
return(ok);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int internal_verify(X509_STORE_CTX *ctx)
|
||||
{
|
||||
int i,ok=0,n;
|
||||
@ -648,6 +696,16 @@ void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
|
||||
ctx->untrusted=sk;
|
||||
}
|
||||
|
||||
void X509_STORE_CTX_chain_purpose(X509_STORE_CTX *ctx, int purpose)
|
||||
{
|
||||
ctx->chain_purpose = purpose;
|
||||
}
|
||||
|
||||
void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose)
|
||||
{
|
||||
ctx->trust_purpose = purpose;
|
||||
}
|
||||
|
||||
IMPLEMENT_STACK_OF(X509)
|
||||
IMPLEMENT_ASN1_SET_OF(X509)
|
||||
|
||||
|
@ -202,6 +202,8 @@ struct x509_store_state_st /* X509_STORE_CTX */
|
||||
/* The following are set by the caller */
|
||||
X509 *cert; /* The cert to check */
|
||||
STACK_OF(X509) *untrusted; /* chain of X509s - untrusted - passed in */
|
||||
int chain_purpose; /* purpose to check untrusted certificates */
|
||||
int trust_purpose; /* trust setting to check */
|
||||
|
||||
/* The following is built up */
|
||||
int depth; /* how far to go looking up certs */
|
||||
@ -258,6 +260,9 @@ struct x509_store_state_st /* X509_STORE_CTX */
|
||||
#define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21
|
||||
#define X509_V_ERR_CERT_CHAIN_TOO_LONG 22
|
||||
#define X509_V_ERR_CERT_REVOKED 23
|
||||
#define X509_V_ERR_INVALID_CA 24
|
||||
#define X509_V_ERR_PATH_LENGTH_EXCEEDED 25
|
||||
#define X509_V_ERR_INVALID_PURPOSE 26
|
||||
|
||||
/* The application is not happy */
|
||||
#define X509_V_ERR_APPLICATION_VERIFICATION 50
|
||||
@ -285,6 +290,8 @@ void X509_OBJECT_free_contents(X509_OBJECT *a);
|
||||
X509_STORE *X509_STORE_new(void );
|
||||
void X509_STORE_free(X509_STORE *v);
|
||||
|
||||
X509_STORE_CTX *X509_STORE_CTX_new(void);
|
||||
void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
|
||||
void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store,
|
||||
X509 *x509, STACK_OF(X509) *chain);
|
||||
void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
|
||||
@ -340,6 +347,8 @@ X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
|
||||
STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
|
||||
void X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x);
|
||||
void X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk);
|
||||
void X509_STORE_CTX_chain_purpose(X509_STORE_CTX *ctx, int purpose);
|
||||
void X509_STORE_CTX_trust_purpose(X509_STORE_CTX *ctx, int purpose);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user