Various X509 fixes. Disable broken certificate workarounds
when X509_V_FLAG_X509_STRICT is set. Check for CRLSign in CRL issuer certificates. Reject CRLs with unhandled (any) critical extensions.
This commit is contained in:
parent
91180d45f9
commit
bc50157010
8
CHANGES
8
CHANGES
@ -617,6 +617,14 @@
|
|||||||
|
|
||||||
Changes between 0.9.7c and 0.9.7d [xx XXX XXXX]
|
Changes between 0.9.7c and 0.9.7d [xx XXX XXXX]
|
||||||
|
|
||||||
|
*) X509 verify fixes. Disable broken certificate workarounds when
|
||||||
|
X509_V_FLAGS_X509_STRICT is set. Check CRL issuer has cRLSign set if
|
||||||
|
keyUsage extension present. Don't accept CRLs with unhandled critical
|
||||||
|
extensions: since verify currently doesn't process CRL extensions this
|
||||||
|
rejects a CRL with *any* critical extensions. Add new verify error codes
|
||||||
|
for these cases.
|
||||||
|
[Steve Henson]
|
||||||
|
|
||||||
*) When creating an OCSP nonce use an OCTET STRING inside the extnValue.
|
*) When creating an OCSP nonce use an OCTET STRING inside the extnValue.
|
||||||
A clarification of RFC2560 will require the use of OCTET STRINGs and
|
A clarification of RFC2560 will require the use of OCTET STRINGs and
|
||||||
some implementations cannot handle the current raw format. Since OpenSSL
|
some implementations cannot handle the current raw format. Since OpenSSL
|
||||||
|
@ -147,6 +147,12 @@ const char *X509_verify_cert_error_string(long n)
|
|||||||
case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
|
case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
|
||||||
return("unhandled critical extension");
|
return("unhandled critical extension");
|
||||||
|
|
||||||
|
case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
|
||||||
|
return("key usage does not include CRL signing");
|
||||||
|
|
||||||
|
case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
|
||||||
|
return("unhandled critical CRL extension");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BIO_snprintf(buf,sizeof buf,"error number %ld",n);
|
BIO_snprintf(buf,sizeof buf,"error number %ld",n);
|
||||||
return(buf);
|
return(buf);
|
||||||
|
@ -383,6 +383,7 @@ static int check_chain_purpose(X509_STORE_CTX *ctx)
|
|||||||
/* Check all untrusted certificates */
|
/* Check all untrusted certificates */
|
||||||
for (i = 0; i < ctx->last_untrusted; i++)
|
for (i = 0; i < ctx->last_untrusted; i++)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
x = sk_X509_value(ctx->chain, i);
|
x = sk_X509_value(ctx->chain, i);
|
||||||
if (!(ctx->flags & X509_V_FLAG_IGNORE_CRITICAL)
|
if (!(ctx->flags & X509_V_FLAG_IGNORE_CRITICAL)
|
||||||
&& (x->ex_flags & EXFLAG_CRITICAL))
|
&& (x->ex_flags & EXFLAG_CRITICAL))
|
||||||
@ -393,7 +394,10 @@ static int check_chain_purpose(X509_STORE_CTX *ctx)
|
|||||||
ok=cb(0,ctx);
|
ok=cb(0,ctx);
|
||||||
if (!ok) goto end;
|
if (!ok) goto end;
|
||||||
}
|
}
|
||||||
if (!X509_check_purpose(x, ctx->purpose, i))
|
ret = X509_check_purpose(x, ctx->purpose, i);
|
||||||
|
if ((ret == 0)
|
||||||
|
|| ((ctx->flags & X509_V_FLAG_X509_STRICT)
|
||||||
|
&& (ret != 1)))
|
||||||
{
|
{
|
||||||
if (i)
|
if (i)
|
||||||
ctx->error = X509_V_ERR_INVALID_CA;
|
ctx->error = X509_V_ERR_INVALID_CA;
|
||||||
@ -537,6 +541,14 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
|
|||||||
|
|
||||||
if(issuer)
|
if(issuer)
|
||||||
{
|
{
|
||||||
|
/* Check for cRLSign bit if keyUsage present */
|
||||||
|
if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
|
||||||
|
!(issuer->ex_kusage & KU_CRL_SIGN))
|
||||||
|
{
|
||||||
|
ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN;
|
||||||
|
ok = ctx->verify_cb(0, ctx);
|
||||||
|
if(!ok) goto err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Attempt to get issuer certificate public key */
|
/* Attempt to get issuer certificate public key */
|
||||||
ikey = X509_get_pubkey(issuer);
|
ikey = X509_get_pubkey(issuer);
|
||||||
@ -611,17 +623,46 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
|
|||||||
{
|
{
|
||||||
int idx, ok;
|
int idx, ok;
|
||||||
X509_REVOKED rtmp;
|
X509_REVOKED rtmp;
|
||||||
|
STACK_OF(X509_EXTENSION) *exts;
|
||||||
|
X509_EXTENSION *ext;
|
||||||
/* Look for serial number of certificate in CRL */
|
/* Look for serial number of certificate in CRL */
|
||||||
rtmp.serialNumber = X509_get_serialNumber(x);
|
rtmp.serialNumber = X509_get_serialNumber(x);
|
||||||
idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
|
idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
|
||||||
/* Not found: OK */
|
/* If found assume revoked: want something cleverer than
|
||||||
if(idx == -1) return 1;
|
|
||||||
/* Otherwise revoked: want something cleverer than
|
|
||||||
* this to handle entry extensions in V2 CRLs.
|
* this to handle entry extensions in V2 CRLs.
|
||||||
*/
|
*/
|
||||||
ctx->error = X509_V_ERR_CERT_REVOKED;
|
if(idx >= 0)
|
||||||
ok = ctx->verify_cb(0, ctx);
|
{
|
||||||
return ok;
|
ctx->error = X509_V_ERR_CERT_REVOKED;
|
||||||
|
ok = ctx->verify_cb(0, ctx);
|
||||||
|
if (!ok) return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->flags & X509_V_FLAG_IGNORE_CRITICAL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* See if we have any critical CRL extensions: since we
|
||||||
|
* currently don't handle any CRL extensions the CRL must be
|
||||||
|
* rejected.
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
ctx->error =
|
||||||
|
X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
|
||||||
|
ok = ctx->verify_cb(0, ctx);
|
||||||
|
if(!ok) return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int internal_verify(X509_STORE_CTX *ctx)
|
static int internal_verify(X509_STORE_CTX *ctx)
|
||||||
|
@ -305,17 +305,26 @@ struct x509_store_ctx_st /* X509_STORE_CTX */
|
|||||||
|
|
||||||
#define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33
|
#define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33
|
||||||
#define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
|
#define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34
|
||||||
|
#define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35
|
||||||
|
#define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36
|
||||||
|
|
||||||
/* The application is not happy */
|
/* The application is not happy */
|
||||||
#define X509_V_ERR_APPLICATION_VERIFICATION 50
|
#define X509_V_ERR_APPLICATION_VERIFICATION 50
|
||||||
|
|
||||||
/* Certificate verify flags */
|
/* Certificate verify flags */
|
||||||
|
|
||||||
#define X509_V_FLAG_CB_ISSUER_CHECK 0x1 /* Send issuer+subject checks to verify_cb */
|
/* Send issuer+subject checks to verify_cb */
|
||||||
#define X509_V_FLAG_USE_CHECK_TIME 0x2 /* Use check time instead of current time */
|
#define X509_V_FLAG_CB_ISSUER_CHECK 0x1
|
||||||
#define X509_V_FLAG_CRL_CHECK 0x4 /* Lookup CRLs */
|
/* Use check time instead of current time */
|
||||||
#define X509_V_FLAG_CRL_CHECK_ALL 0x8 /* Lookup CRLs for whole chain */
|
#define X509_V_FLAG_USE_CHECK_TIME 0x2
|
||||||
#define X509_V_FLAG_IGNORE_CRITICAL 0x10 /* Ignore unhandled critical extensions */
|
/* Lookup CRLs */
|
||||||
|
#define X509_V_FLAG_CRL_CHECK 0x4
|
||||||
|
/* Lookup CRLs for whole chain */
|
||||||
|
#define X509_V_FLAG_CRL_CHECK_ALL 0x8
|
||||||
|
/* Ignore unhandled critical extensions */
|
||||||
|
#define X509_V_FLAG_IGNORE_CRITICAL 0x10
|
||||||
|
/* Disable workarounds for broken certificates */
|
||||||
|
#define X509_V_FLAG_X509_STRICT 0x20
|
||||||
|
|
||||||
int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
|
int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
|
||||||
X509_NAME *name);
|
X509_NAME *name);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* project 2001.
|
* project 2001.
|
||||||
*/
|
*/
|
||||||
/* ====================================================================
|
/* ====================================================================
|
||||||
* Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
|
* Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -415,6 +415,7 @@ static void x509v3_cache_extensions(X509 *x)
|
|||||||
* 1 is a CA
|
* 1 is a CA
|
||||||
* 2 basicConstraints absent so "maybe" a CA
|
* 2 basicConstraints absent so "maybe" a CA
|
||||||
* 3 basicConstraints absent but self signed V1.
|
* 3 basicConstraints absent but self signed V1.
|
||||||
|
* 4 basicConstraints absent but keyUsage present and keyCertSign asserted.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
|
#define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
|
||||||
@ -436,7 +437,7 @@ static int ca_check(const X509 *x)
|
|||||||
} else {
|
} else {
|
||||||
if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3;
|
if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3;
|
||||||
/* If key usage present it must have certSign so tolerate it */
|
/* If key usage present it must have certSign so tolerate it */
|
||||||
else if (x->ex_flags & EXFLAG_KUSAGE) return 3;
|
else if (x->ex_flags & EXFLAG_KUSAGE) return 4;
|
||||||
else return 2;
|
else return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user