mirror of
https://github.com/openssl/openssl.git
synced 2024-11-24 10:34:12 +08:00
Tidy up CRL handling by checking for critical extensions when it is
loaded. Add new function X509_CRL_get0_by_serial() to lookup a revoked entry to avoid the need to access the structure directly. Add new X509_CRL_METHOD to allow common CRL operations (verify, lookup) to be redirected.
This commit is contained in:
parent
4ca7d975af
commit
010fa0b331
6
CHANGES
6
CHANGES
@ -4,6 +4,12 @@
|
||||
|
||||
Changes between 0.9.8d and 0.9.9 [xx XXX xxxx]
|
||||
|
||||
*) Add an X509_CRL_METHOD structure to allow CRL processing to be redirected
|
||||
to external functions. This can be used to increase CRL handling
|
||||
efficiency especially when CRLs are very large by (for example) storing
|
||||
the CRL revoked certificates in a database.
|
||||
[Steve Henson]
|
||||
|
||||
*) Overhaul of by_dir code. Add support for dynamic loading of CRLs so
|
||||
new CRLs added to a directory can be used. New command line option
|
||||
-verify_return_error to s_client and s_server. This causes real errors
|
||||
|
@ -113,3 +113,18 @@ struct evp_pkey_asn1_method_st
|
||||
int (*old_priv_encode)(const EVP_PKEY *pkey, unsigned char **pder);
|
||||
|
||||
} /* EVP_PKEY_ASN1_METHOD */;
|
||||
|
||||
/* Method to handle CRL access.
|
||||
* In general a CRL could be very large (several Mb) and can consume large
|
||||
* amounts of resources if stored in memory by multiple processes.
|
||||
* This method allows general CRL operations to be redirected to more
|
||||
* efficient callbacks: for example a CRL entry database.
|
||||
*/
|
||||
|
||||
struct x509_crl_method_st
|
||||
{
|
||||
int (*crl_init)(X509_CRL *crl);
|
||||
int (*crl_free)(X509_CRL *crl);
|
||||
int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *ser);
|
||||
int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk);
|
||||
};
|
||||
|
@ -58,6 +58,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "asn1_locl.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
@ -111,6 +112,9 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
void *exarg)
|
||||
{
|
||||
X509_CRL *crl = (X509_CRL *)*pval;
|
||||
STACK_OF(X509_EXTENSION) *exts;
|
||||
X509_EXTENSION *ext;
|
||||
int idx;
|
||||
|
||||
switch(operation)
|
||||
{
|
||||
@ -119,6 +123,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
crl->akid = NULL;
|
||||
crl->flags = 0;
|
||||
crl->idp_flags = 0;
|
||||
crl->meth = 0;
|
||||
break;
|
||||
|
||||
case ASN1_OP_D2I_POST:
|
||||
@ -132,9 +137,37 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
|
||||
crl->akid = X509_CRL_get_ext_d2i(crl,
|
||||
NID_authority_key_identifier, NULL, NULL);
|
||||
if (crl->meth && crl->meth->crl_init)
|
||||
return crl->meth->crl_init(crl);
|
||||
|
||||
/* See if we have any unhandled critical CRL extensions and
|
||||
* indicate this in a flag. We only currently handle IDP so
|
||||
* anything else critical sets the flag.
|
||||
*
|
||||
* This code accesses the X509_CRL structure directly:
|
||||
* applications shouldn't do this.
|
||||
*/
|
||||
|
||||
exts = crl->crl->extensions;
|
||||
|
||||
for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++)
|
||||
{
|
||||
ext = sk_X509_EXTENSION_value(exts, idx);
|
||||
if (ext->critical > 0)
|
||||
{
|
||||
/* We handle IDP now so permit it */
|
||||
if (OBJ_obj2nid(ext->object) ==
|
||||
NID_issuing_distribution_point)
|
||||
continue;
|
||||
crl->flags |= EXFLAG_CRITICAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ASN1_OP_FREE_POST:
|
||||
if (crl->meth && crl->meth->crl_free)
|
||||
return crl->meth->crl_free(crl);
|
||||
if (crl->akid)
|
||||
AUTHORITY_KEYID_free(crl->akid);
|
||||
if (crl->idp)
|
||||
@ -217,6 +250,44 @@ int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r)
|
||||
{
|
||||
if (crl->meth && crl->meth->crl_verify)
|
||||
return crl->meth->crl_verify(crl, r);
|
||||
return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO),
|
||||
crl->sig_alg, crl->signature,crl->crl,r));
|
||||
}
|
||||
|
||||
int X509_CRL_get0_by_serial(X509_CRL *crl,
|
||||
X509_REVOKED **ret, ASN1_INTEGER *serial)
|
||||
{
|
||||
X509_REVOKED rtmp;
|
||||
int idx;
|
||||
if (crl->meth && crl->meth->crl_lookup)
|
||||
return crl->meth->crl_lookup(crl, ret, serial);
|
||||
rtmp.serialNumber = serial;
|
||||
/* Sort revoked into serial number order if not already sorted.
|
||||
* Do this under a lock to avoid race condition.
|
||||
*/
|
||||
if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked))
|
||||
{
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_X509_CRL);
|
||||
sk_X509_REVOKED_sort(crl->crl->revoked);
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_X509_CRL);
|
||||
}
|
||||
idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
|
||||
/* If found assume revoked: want something cleverer than
|
||||
* this to handle entry extensions in V2 CRLs.
|
||||
*/
|
||||
if(idx >= 0)
|
||||
{
|
||||
if (ret)
|
||||
*ret = sk_X509_REVOKED_value(crl->crl->revoked, idx);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPLEMENT_STACK_OF(X509_REVOKED)
|
||||
IMPLEMENT_ASN1_SET_OF(X509_REVOKED)
|
||||
IMPLEMENT_STACK_OF(X509_CRL)
|
||||
|
@ -143,6 +143,8 @@ typedef struct ecdsa_method ECDSA_METHOD;
|
||||
typedef struct x509_st X509;
|
||||
typedef struct X509_algor_st X509_ALGOR;
|
||||
typedef struct X509_crl_st X509_CRL;
|
||||
typedef struct x509_crl_method_st X509_CRL_METHOD;
|
||||
typedef struct x509_revoked_st X509_REVOKED;
|
||||
typedef struct X509_name_st X509_NAME;
|
||||
typedef struct X509_pubkey_st X509_PUBKEY;
|
||||
typedef struct x509_store_st X509_STORE;
|
||||
|
@ -420,13 +420,13 @@ typedef struct x509_cert_pair_st {
|
||||
XN_FLAG_FN_LN | \
|
||||
XN_FLAG_FN_ALIGN)
|
||||
|
||||
typedef struct X509_revoked_st
|
||||
struct x509_revoked_st
|
||||
{
|
||||
ASN1_INTEGER *serialNumber;
|
||||
ASN1_TIME *revocationDate;
|
||||
STACK_OF(X509_EXTENSION) /* optional */ *extensions;
|
||||
int sequence; /* load sequence */
|
||||
} X509_REVOKED;
|
||||
};
|
||||
|
||||
DECLARE_STACK_OF(X509_REVOKED)
|
||||
DECLARE_ASN1_SET_OF(X509_REVOKED)
|
||||
@ -460,6 +460,7 @@ struct X509_crl_st
|
||||
#ifndef OPENSSL_NO_SHA
|
||||
unsigned char sha1_hash[SHA_DIGEST_LENGTH];
|
||||
#endif
|
||||
X509_CRL_METHOD *meth;
|
||||
} /* X509_CRL */;
|
||||
|
||||
DECLARE_STACK_OF(X509_CRL)
|
||||
@ -969,6 +970,8 @@ DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO)
|
||||
DECLARE_ASN1_FUNCTIONS(X509_CRL)
|
||||
|
||||
int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
|
||||
int X509_CRL_get0_by_serial(X509_CRL *crl,
|
||||
X509_REVOKED **ret, ASN1_INTEGER *serial);
|
||||
|
||||
X509_PKEY * X509_PKEY_new(void );
|
||||
void X509_PKEY_free(X509_PKEY *a);
|
||||
|
@ -937,60 +937,29 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
|
||||
/* Check certificate against CRL */
|
||||
static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
|
||||
{
|
||||
int idx, ok;
|
||||
X509_REVOKED rtmp;
|
||||
STACK_OF(X509_EXTENSION) *exts;
|
||||
X509_EXTENSION *ext;
|
||||
/* Look for serial number of certificate in CRL */
|
||||
rtmp.serialNumber = X509_get_serialNumber(x);
|
||||
/* Sort revoked into serial number order if not already sorted.
|
||||
* Do this under a lock to avoid race condition.
|
||||
*/
|
||||
if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked))
|
||||
{
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_X509_CRL);
|
||||
sk_X509_REVOKED_sort(crl->crl->revoked);
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_X509_CRL);
|
||||
}
|
||||
idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
|
||||
/* If found assume revoked: want something cleverer than
|
||||
int ok;
|
||||
/* Look for serial number of certificate in CRL
|
||||
* If found assume revoked: want something cleverer than
|
||||
* this to handle entry extensions in V2 CRLs.
|
||||
*/
|
||||
if(idx >= 0)
|
||||
if (X509_CRL_get0_by_serial(crl, NULL, X509_get_serialNumber(x)) > 0)
|
||||
{
|
||||
ctx->error = X509_V_ERR_CERT_REVOKED;
|
||||
ok = ctx->verify_cb(0, ctx);
|
||||
if (!ok) return 0;
|
||||
if (!ok)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
|
||||
return 1;
|
||||
|
||||
/* See if we have any critical CRL extensions: since we
|
||||
* currently only handle IDP the CRL must be rejected if any others
|
||||
* are present.
|
||||
* This code accesses the X509_CRL structure directly: applications
|
||||
* shouldn't do this.
|
||||
*/
|
||||
|
||||
exts = crl->crl->extensions;
|
||||
|
||||
for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++)
|
||||
if (crl->flags & EXFLAG_CRITICAL)
|
||||
{
|
||||
ext = sk_X509_EXTENSION_value(exts, idx);
|
||||
if (ext->critical > 0)
|
||||
{
|
||||
/* We handle IDP now so permit it */
|
||||
if (OBJ_obj2nid(ext->object) ==
|
||||
NID_issuing_distribution_point)
|
||||
continue;
|
||||
ctx->error =
|
||||
X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
|
||||
ok = ctx->verify_cb(0, ctx);
|
||||
if(!ok) return 0;
|
||||
break;
|
||||
}
|
||||
if (ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
|
||||
return 1;
|
||||
ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
|
||||
ok = ctx->verify_cb(0, ctx);
|
||||
if(!ok)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -83,12 +83,6 @@ int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r)
|
||||
a->sig_alg,a->signature,a->req_info,r));
|
||||
}
|
||||
|
||||
int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r)
|
||||
{
|
||||
return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO),
|
||||
a->sig_alg, a->signature,a->crl,r));
|
||||
}
|
||||
|
||||
int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r)
|
||||
{
|
||||
return(ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC),
|
||||
|
Loading…
Reference in New Issue
Block a user