Check chain extensions also for trusted certificates
This includes basic constraints, key usages, issuer EKUs and auxiliary trust OIDs (given a trust suitably related to the intended purpose). Added tests and updated documentation. Reviewed-by: Dr. Stephen Henson <steve@openssl.org>
This commit is contained in:
parent
1b4cf96f9b
commit
0daccd4dc1
13
apps/opt.c
13
apps/opt.c
@ -496,14 +496,25 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
|
||||
X509_VERIFY_PARAM_add0_policy(vpm, otmp);
|
||||
break;
|
||||
case OPT_V_PURPOSE:
|
||||
/* purpose name -> purpose index */
|
||||
i = X509_PURPOSE_get_by_sname(opt_arg());
|
||||
if (i < 0) {
|
||||
BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg());
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* purpose index -> purpose object */
|
||||
xptmp = X509_PURPOSE_get0(i);
|
||||
|
||||
/* purpose object -> purpose value */
|
||||
i = X509_PURPOSE_get_id(xptmp);
|
||||
X509_VERIFY_PARAM_set_purpose(vpm, i);
|
||||
|
||||
if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) {
|
||||
BIO_printf(bio_err,
|
||||
"%s: Internal error setting purpose %s\n",
|
||||
prog, opt_arg());
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case OPT_V_VERIFY_NAME:
|
||||
vtmp = X509_VERIFY_PARAM_lookup(opt_arg());
|
||||
|
@ -276,7 +276,7 @@ static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
|
||||
|
||||
static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
|
||||
{
|
||||
if (x->aux)
|
||||
if (x->aux && (x->aux->trust || x->aux->reject))
|
||||
return obj_trust(trust->arg1, x, flags);
|
||||
return X509_TRUST_UNTRUSTED;
|
||||
}
|
||||
@ -293,23 +293,26 @@ static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
|
||||
|
||||
static int obj_trust(int id, X509 *x, int flags)
|
||||
{
|
||||
ASN1_OBJECT *obj;
|
||||
X509_CERT_AUX *ax = x->aux;
|
||||
int i;
|
||||
X509_CERT_AUX *ax;
|
||||
ax = x->aux;
|
||||
|
||||
if (!ax)
|
||||
return X509_TRUST_UNTRUSTED;
|
||||
if (ax->reject) {
|
||||
for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
|
||||
obj = sk_ASN1_OBJECT_value(ax->reject, i);
|
||||
if (OBJ_obj2nid(obj) == id)
|
||||
ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->reject, i);
|
||||
int nid = OBJ_obj2nid(obj);
|
||||
|
||||
if (nid == id || nid == NID_anyExtendedKeyUsage)
|
||||
return X509_TRUST_REJECTED;
|
||||
}
|
||||
}
|
||||
if (ax->trust) {
|
||||
for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
|
||||
obj = sk_ASN1_OBJECT_value(ax->trust, i);
|
||||
if (OBJ_obj2nid(obj) == id)
|
||||
ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->trust, i);
|
||||
int nid = OBJ_obj2nid(obj);
|
||||
|
||||
if (nid == id || nid == NID_anyExtendedKeyUsage)
|
||||
return X509_TRUST_TRUSTED;
|
||||
}
|
||||
/*
|
||||
|
@ -362,6 +362,48 @@ static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, X509_NAME *nm)
|
||||
return sk;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check EE or CA certificate purpose. For trusted certificates explicit local
|
||||
* auxiliary trust can be used to override EKU-restrictions.
|
||||
*/
|
||||
static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth,
|
||||
int must_be_ca)
|
||||
{
|
||||
int pu_ok = X509_check_purpose(x, purpose, must_be_ca > 0);
|
||||
int tr_ok = X509_TRUST_UNTRUSTED;
|
||||
|
||||
/*
|
||||
* For trusted certificates we want to see whether any auxiliary trust
|
||||
* settings override the purpose constraints we failed to meet above.
|
||||
*
|
||||
* This is complicated by the fact that the trust ordinals in
|
||||
* ctx->param->trust are entirely independent of the purpose ordinals in
|
||||
* ctx->param->purpose!
|
||||
*
|
||||
* What connects them is their mutual initialization via calls from
|
||||
* X509_STORE_CTX_set_default() into X509_VERIFY_PARAM_lookup() which sets
|
||||
* related values of both param->trust and param->purpose. It is however
|
||||
* typically possible to infer associated trust values from a purpose value
|
||||
* via the X509_PURPOSE API.
|
||||
*
|
||||
* Therefore, we can only check for trust overrides when the purpose we're
|
||||
* checking is the same as ctx->param->purpose and ctx->param->trust is
|
||||
* also set, or can be inferred from the purpose.
|
||||
*/
|
||||
if (depth >= ctx->num_untrusted && purpose == ctx->param->purpose)
|
||||
tr_ok = X509_check_trust(x, ctx->param->trust, X509_TRUST_NO_SS_COMPAT);
|
||||
|
||||
if (tr_ok != X509_TRUST_REJECTED &&
|
||||
(pu_ok == 1 ||
|
||||
(pu_ok != 0 && (ctx->param->flags & X509_V_FLAG_X509_STRICT) == 0)))
|
||||
return 1;
|
||||
|
||||
ctx->error = X509_V_ERR_INVALID_PURPOSE;
|
||||
ctx->error_depth = depth;
|
||||
ctx->current_cert = x;
|
||||
return ctx->verify_cb(0, ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a certificate chains extensions for consistency with the supplied
|
||||
* purpose
|
||||
@ -369,11 +411,12 @@ static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, X509_NAME *nm)
|
||||
|
||||
static int check_chain_extensions(X509_STORE_CTX *ctx)
|
||||
{
|
||||
int i, ok = 0, must_be_ca, plen = 0;
|
||||
int i, must_be_ca, plen = 0;
|
||||
X509 *x;
|
||||
int proxy_path_length = 0;
|
||||
int purpose;
|
||||
int allow_proxy_certs;
|
||||
int num = sk_X509_num(ctx->chain);
|
||||
|
||||
/*-
|
||||
* must_be_ca can have 1 of 3 values:
|
||||
@ -402,8 +445,7 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
|
||||
purpose = ctx->param->purpose;
|
||||
}
|
||||
|
||||
/* Check all untrusted certificates */
|
||||
for (i = 0; i == 0 || i < ctx->num_untrusted; i++) {
|
||||
for (i = 0; i < num; i++) {
|
||||
int ret;
|
||||
x = sk_X509_value(ctx->chain, i);
|
||||
if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
|
||||
@ -411,17 +453,15 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
|
||||
ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
|
||||
ctx->error_depth = i;
|
||||
ctx->current_cert = x;
|
||||
ok = ctx->verify_cb(0, ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
if (!ctx->verify_cb(0, ctx))
|
||||
return 0;
|
||||
}
|
||||
if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) {
|
||||
ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
|
||||
ctx->error_depth = i;
|
||||
ctx->current_cert = x;
|
||||
ok = ctx->verify_cb(0, ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
if (!ctx->verify_cb(0, ctx))
|
||||
return 0;
|
||||
}
|
||||
ret = X509_check_ca(x);
|
||||
switch (must_be_ca) {
|
||||
@ -453,22 +493,12 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
|
||||
if (ret == 0) {
|
||||
ctx->error_depth = i;
|
||||
ctx->current_cert = x;
|
||||
ok = ctx->verify_cb(0, ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
if (! ctx->verify_cb(0, ctx))
|
||||
return 0;
|
||||
}
|
||||
if (ctx->param->purpose > 0) {
|
||||
ret = X509_check_purpose(x, purpose, must_be_ca > 0);
|
||||
if ((ret == 0)
|
||||
|| ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
|
||||
&& (ret != 1))) {
|
||||
ctx->error = X509_V_ERR_INVALID_PURPOSE;
|
||||
ctx->error_depth = i;
|
||||
ctx->current_cert = x;
|
||||
ok = ctx->verify_cb(0, ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
}
|
||||
if (purpose > 0) {
|
||||
if (!check_purpose(ctx, x, purpose, i, must_be_ca))
|
||||
return 0;
|
||||
}
|
||||
/* Check pathlen if not self issued */
|
||||
if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
|
||||
@ -477,9 +507,8 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
|
||||
ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
|
||||
ctx->error_depth = i;
|
||||
ctx->current_cert = x;
|
||||
ok = ctx->verify_cb(0, ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
if (!ctx->verify_cb(0, ctx))
|
||||
return 0;
|
||||
}
|
||||
/* Increment path length if not self issued */
|
||||
if (!(x->ex_flags & EXFLAG_SI))
|
||||
@ -494,18 +523,15 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
|
||||
ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
|
||||
ctx->error_depth = i;
|
||||
ctx->current_cert = x;
|
||||
ok = ctx->verify_cb(0, ctx);
|
||||
if (!ok)
|
||||
goto end;
|
||||
if (!ctx->verify_cb(0, ctx))
|
||||
return 0;
|
||||
}
|
||||
proxy_path_length++;
|
||||
must_be_ca = 0;
|
||||
} else
|
||||
must_be_ca = 1;
|
||||
}
|
||||
ok = 1;
|
||||
end:
|
||||
return ok;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_name_constraints(X509_STORE_CTX *ctx)
|
||||
@ -2016,11 +2042,20 @@ void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
|
||||
|
||||
int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
|
||||
{
|
||||
/*
|
||||
* XXX: Why isn't this function always used to set the associated trust?
|
||||
* Should there even be a VPM->trust field at all? Or should the trust
|
||||
* always be inferred from the purpose by X509_STORE_CTX_init().
|
||||
*/
|
||||
return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
|
||||
}
|
||||
|
||||
int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
|
||||
{
|
||||
/*
|
||||
* XXX: See above, this function would only be needed when the default
|
||||
* trust for the purpose needs an override in a corner case.
|
||||
*/
|
||||
return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
|
||||
}
|
||||
|
||||
@ -2054,6 +2089,11 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
|
||||
ptmp = X509_PURPOSE_get0(idx);
|
||||
if (ptmp->trust == X509_TRUST_DEFAULT) {
|
||||
idx = X509_PURPOSE_get_by_id(def_purpose);
|
||||
/*
|
||||
* XXX: In the two callers above def_purpose is always 0, which is
|
||||
* not a known value, so idx will always be -1. How is the
|
||||
* X509_TRUST_DEFAULT case actually supposed to be handled?
|
||||
*/
|
||||
if (idx == -1) {
|
||||
X509err(X509_F_X509_STORE_CTX_PURPOSE_INHERIT,
|
||||
X509_R_UNKNOWN_PURPOSE_ID);
|
||||
@ -2211,6 +2251,18 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: For now, continue to inherit trust from VPM, but infer from the
|
||||
* purpose if this still yields the default value.
|
||||
*/
|
||||
if (ctx->param->trust == X509_TRUST_DEFAULT) {
|
||||
int idx = X509_PURPOSE_get_by_id(ctx->param->purpose);
|
||||
X509_PURPOSE *xp = X509_PURPOSE_get0(idx);
|
||||
|
||||
if (xp != NULL)
|
||||
ctx->param->trust = X509_PURPOSE_get_trust(xp);
|
||||
}
|
||||
|
||||
if (CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
|
||||
&ctx->ex_data))
|
||||
return 1;
|
||||
|
@ -133,7 +133,7 @@ static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
|
||||
return;
|
||||
param->name = NULL;
|
||||
param->purpose = 0;
|
||||
param->trust = 0;
|
||||
param->trust = X509_TRUST_DEFAULT;
|
||||
/*
|
||||
* param->inh_flags = X509_VP_FLAG_DEFAULT;
|
||||
*/
|
||||
@ -243,7 +243,7 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
|
||||
to_overwrite = 0;
|
||||
|
||||
x509_verify_param_copy(purpose, 0);
|
||||
x509_verify_param_copy(trust, 0);
|
||||
x509_verify_param_copy(trust, X509_TRUST_DEFAULT);
|
||||
x509_verify_param_copy(depth, -1);
|
||||
|
||||
/* If overwrite or check time not set, copy across */
|
||||
@ -511,7 +511,7 @@ static const X509_VERIFY_PARAM default_table[] = {
|
||||
"default", /* X509 default parameters */
|
||||
0, /* Check time */
|
||||
0, /* internal flags */
|
||||
0, /* flags */
|
||||
X509_V_FLAG_TRUSTED_FIRST, /* flags */
|
||||
0, /* purpose */
|
||||
0, /* trust */
|
||||
100, /* depth */
|
||||
|
@ -198,14 +198,16 @@ When constructing the certificate chain, use the trusted certificates specified
|
||||
via B<-CAfile>, B<-CApath> or B<-trusted> before any certificates specified via
|
||||
B<-untrusted>.
|
||||
This can be useful in environments with Bridge or Cross-Certified CAs.
|
||||
As of OpenSSL 1.1.0 this option is on by default and cannot be disabled.
|
||||
|
||||
=item B<-no_alt_chains>
|
||||
|
||||
When building a certificate chain, if the first certificate chain found is not
|
||||
trusted, then OpenSSL will continue to check to see if an alternative chain can
|
||||
be found that is trusted. With this option that behaviour is suppressed so that
|
||||
only the first chain found is ever used. Using this option will force the
|
||||
behaviour to match that of OpenSSL versions prior to 1.1.0.
|
||||
By default, unless B<-trusted_first> is specified, when building a certificate
|
||||
chain, if the first certificate chain found is not trusted, then OpenSSL will
|
||||
attempt to replace untrusted issuer certificates with certificates from the
|
||||
trust store to see if an alternative chain can be found that is trusted.
|
||||
As of OpenSSL 1.1.0, with B<-trusted_first> always on, this option has no
|
||||
effect.
|
||||
|
||||
=item B<-untrusted file>
|
||||
|
||||
@ -264,13 +266,17 @@ the subject certificate.
|
||||
|
||||
Use default verification policies like trust model and required certificate
|
||||
policies identified by B<name>.
|
||||
The trust model determines which auxiliary trust or reject OIDs are applicable
|
||||
to verifying the given certificate chain.
|
||||
See the B<-addtrust> and B<-addreject> options of the L<x509(1)> command-line
|
||||
utility.
|
||||
Supported policy names include: B<default>, B<pkcs7>, B<smime_sign>,
|
||||
B<ssl_client>, B<ssl_server>.
|
||||
This checks not only the purpose of the leaf certificate, but also the
|
||||
trust settings of the trusted CAs.
|
||||
When in doubt, use this option rather than B<-purpose>.
|
||||
The B<-verify_name> option more closely matches how certificates are checked in
|
||||
e.g. SSL and S/MIME.
|
||||
These mimics the combinations of purpose and trust settings used in SSL, CMS
|
||||
and S/MIME.
|
||||
As of OpenSSL 1.1.0, the trust model is inferred from the purpose when not
|
||||
specified, so the B<-verify_name> options are functionally equivalent to the
|
||||
corresponding B<-purpose> settings.
|
||||
|
||||
=item B<-x509_strict>
|
||||
|
||||
|
@ -289,9 +289,12 @@ clears all the prohibited or rejected uses of the certificate.
|
||||
|
||||
=item B<-addtrust arg>
|
||||
|
||||
adds a trusted certificate use. Any object name can be used here
|
||||
but currently only B<clientAuth> (SSL client use), B<serverAuth>
|
||||
(SSL server use) and B<emailProtection> (S/MIME email) are used.
|
||||
adds a trusted certificate use.
|
||||
Any object name can be used here but currently only B<clientAuth> (SSL client
|
||||
use), B<serverAuth> (SSL server use), B<emailProtection> (S/MIME email) and
|
||||
B<anyExtendedKeyUsage> are used.
|
||||
As of OpenSSL 1.1.0, the last of these blocks all purposes when rejected or
|
||||
enables all purposes when trusted.
|
||||
Other OpenSSL applications may define additional uses.
|
||||
|
||||
=item B<-addreject arg>
|
||||
|
@ -197,11 +197,20 @@ verification. If this flag is set then additional status codes will be sent
|
||||
to the verification callback and it B<must> be prepared to handle such cases
|
||||
without assuming they are hard errors.
|
||||
|
||||
If B<X509_V_FLAG_TRUSTED_FIRST> is set, when constructing the certificate chain,
|
||||
L<X509_verify_cert(3)> will search the trust store for issuer certificates before
|
||||
searching the provided untrusted certificates.
|
||||
As of OpenSSL 1.1.0 this option is on by default and cannot be disabled.
|
||||
|
||||
The B<X509_V_FLAG_NO_ALT_CHAINS> flag suppresses checking for alternative
|
||||
chains. By default, when building a certificate chain, if the first certificate
|
||||
chain found is not trusted, then OpenSSL will continue to check to see if an
|
||||
alternative chain can be found that is trusted. With this flag set the behaviour
|
||||
will match that of OpenSSL versions prior to 1.1.0.
|
||||
chains.
|
||||
By default, unless B<X509_V_FLAG_TRUSTED_FIRST> is set, when building a
|
||||
certificate chain, if the first certificate chain found is not trusted, then
|
||||
OpenSSL will attempt to replace untrusted certificates supplied by the peer
|
||||
with certificates from the trust store to see if an alternative chain can be
|
||||
found that is trusted.
|
||||
As of OpenSSL 1.1.0, with B<X509_V_FLAG_TRUSTED_FIRST> always set, this option
|
||||
has no effect.
|
||||
|
||||
The B<X509_V_FLAG_NO_CHECK_TIME> flag suppresses checking the validity period
|
||||
of certificates and CRLs against the current time. If X509_VERIFY_PARAM_set_time()
|
||||
|
@ -183,7 +183,7 @@ DEFINE_STACK_OF(X509_TRUST)
|
||||
|
||||
/* standard trust ids */
|
||||
|
||||
# define X509_TRUST_DEFAULT -1/* Only valid in purpose settings */
|
||||
# define X509_TRUST_DEFAULT 0 /* Only valid in purpose settings */
|
||||
|
||||
# define X509_TRUST_COMPAT 1
|
||||
# define X509_TRUST_SSL_CLIENT 2
|
||||
|
18
test/certs/root+anyEKU.pem
Normal file
18
test/certs/root+anyEKU.pem
Normal file
@ -0,0 +1,18 @@
|
||||
-----BEGIN TRUSTED CERTIFICATE-----
|
||||
MIIC8TCCAdmgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
|
||||
IENBMCAXDTE2MDExNTA4MTk0OVoYDzIxMTYwMTE2MDgxOTQ5WjASMRAwDgYDVQQD
|
||||
DAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4eYA9Qa8
|
||||
oEY4eQ8/HnEZE20C3yubdmv8rLAh7daRCEI7pWM17FJboKJKxdYAlAOXWj25ZyjS
|
||||
feMhXKTtxjyNjoTRnVTDPdl0opZ2Z3H5xhpQd7P9eO5b4OOMiSPCmiLsPtQ3ngfN
|
||||
wCtVERc6NEIcaQ06GLDtFZRexv2eh8Yc55QaksBfBcFzQ+UD3gmRySTO2I6Lfi7g
|
||||
MUjRhipqVSZ66As2Tpex4KTJ2lxpSwOACFaDox+yKrjBTP7FsU3UwAGq7b7OJb3u
|
||||
aa32B81uK6GJVPVo65gJ7clgZsszYkoDsGjWDqtfwTVVfv1G7rrr3Laio+2Ff3ff
|
||||
tWgiQ35mJCOvxQIDAQABo1AwTjAdBgNVHQ4EFgQUjvUlrx6ba4Q9fICayVOcTXL3
|
||||
o1IwHwYDVR0jBBgwFoAUjvUlrx6ba4Q9fICayVOcTXL3o1IwDAYDVR0TBAUwAwEB
|
||||
/zANBgkqhkiG9w0BAQsFAAOCAQEAyRRJx27WYOogPXZpPfAMt8ptapr/ugLWGLlw
|
||||
bzKySoyLpoV2/YNAvTAGB90iFq6x/ujjrK41/ES0p3v38/Qfuxo24gcZgc/oYLV2
|
||||
UqR+uGCx68p2OWLYctBsARtYWOEgPhHFb9aVxcOQKyZHtivDX0wLGX+nqZoHX9IY
|
||||
mc0sbpRBRMzxRsChbzD5re9kZ5NrgkjA6DJ7jYh2GitOM6oIU3Dd9+pk3bCEkFUg
|
||||
Ry9qN/k+AyeqH1Qcb5LU+MTmlw8bmyzmMOBZgdegtO4HshcBMO054KSB3WSfBPDO
|
||||
bEhZ0vm/lw63TGi88yIMtlkmcU2g0RKpeQI96G6QeqHyKF3p8DAIMAYGBFUdJQA=
|
||||
-----END TRUSTED CERTIFICATE-----
|
18
test/certs/root-anyEKU.pem
Normal file
18
test/certs/root-anyEKU.pem
Normal file
@ -0,0 +1,18 @@
|
||||
-----BEGIN TRUSTED CERTIFICATE-----
|
||||
MIIC8TCCAdmgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
|
||||
IENBMCAXDTE2MDExNTA4MTk0OVoYDzIxMTYwMTE2MDgxOTQ5WjASMRAwDgYDVQQD
|
||||
DAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4eYA9Qa8
|
||||
oEY4eQ8/HnEZE20C3yubdmv8rLAh7daRCEI7pWM17FJboKJKxdYAlAOXWj25ZyjS
|
||||
feMhXKTtxjyNjoTRnVTDPdl0opZ2Z3H5xhpQd7P9eO5b4OOMiSPCmiLsPtQ3ngfN
|
||||
wCtVERc6NEIcaQ06GLDtFZRexv2eh8Yc55QaksBfBcFzQ+UD3gmRySTO2I6Lfi7g
|
||||
MUjRhipqVSZ66As2Tpex4KTJ2lxpSwOACFaDox+yKrjBTP7FsU3UwAGq7b7OJb3u
|
||||
aa32B81uK6GJVPVo65gJ7clgZsszYkoDsGjWDqtfwTVVfv1G7rrr3Laio+2Ff3ff
|
||||
tWgiQ35mJCOvxQIDAQABo1AwTjAdBgNVHQ4EFgQUjvUlrx6ba4Q9fICayVOcTXL3
|
||||
o1IwHwYDVR0jBBgwFoAUjvUlrx6ba4Q9fICayVOcTXL3o1IwDAYDVR0TBAUwAwEB
|
||||
/zANBgkqhkiG9w0BAQsFAAOCAQEAyRRJx27WYOogPXZpPfAMt8ptapr/ugLWGLlw
|
||||
bzKySoyLpoV2/YNAvTAGB90iFq6x/ujjrK41/ES0p3v38/Qfuxo24gcZgc/oYLV2
|
||||
UqR+uGCx68p2OWLYctBsARtYWOEgPhHFb9aVxcOQKyZHtivDX0wLGX+nqZoHX9IY
|
||||
mc0sbpRBRMzxRsChbzD5re9kZ5NrgkjA6DJ7jYh2GitOM6oIU3Dd9+pk3bCEkFUg
|
||||
Ry9qN/k+AyeqH1Qcb5LU+MTmlw8bmyzmMOBZgdegtO4HshcBMO054KSB3WSfBPDO
|
||||
bEhZ0vm/lw63TGi88yIMtlkmcU2g0RKpeQI96G6QeqHyKF3p8DAIoAYGBFUdJQA=
|
||||
-----END TRUSTED CERTIFICATE-----
|
19
test/certs/root2+clientAuth.pem
Normal file
19
test/certs/root2+clientAuth.pem
Normal file
@ -0,0 +1,19 @@
|
||||
-----BEGIN TRUSTED CERTIFICATE-----
|
||||
MIIC8TCCAdmgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
|
||||
IENBMCAXDTE2MDExNTA4MTk0OVoYDzIxMTYwMTE2MDgxOTQ5WjASMRAwDgYDVQQD
|
||||
DAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyB6dJAD5
|
||||
wbStQf4HE0EhldtDShNVQ/jhDu6s2Ka30FdP4ml1+c2Py7ODUSjSCegXaBIOXCA+
|
||||
R0zaBAJ3ZeqXx3UrE9PiXaHRGZcoPtX4mK9IOHhIdxwPUa6ceSOJn4cHY+p0cFLp
|
||||
/5bnUErp4IqbL1bMd4v8fFxJ0ZDGJahfLiurnYUyalaNCHK+hK2+RaeRgPlsXfiU
|
||||
/vwhhjFhdhixbPm8l+S+2xNySV1JAAzrUvEDdNZ0iBvuVcS2mlhSKTht5Zeg+0C6
|
||||
7kYYqxM9CVZCwcV/aSUImwjeFsNMJsl/nFyEacu6vXz0rjvLwPzTAeVYZy592Gwv
|
||||
akWOtiDdap7WJQIDAQABo1AwTjAdBgNVHQ4EFgQUnM5mQjCrHAgmX3MZbd8Pp65Y
|
||||
Uh4wHwYDVR0jBBgwFoAUnM5mQjCrHAgmX3MZbd8Pp65YUh4wDAYDVR0TBAUwAwEB
|
||||
/zANBgkqhkiG9w0BAQsFAAOCAQEADkH6+rUX2QD5TMBn8x4PR9mTQsxhD2k8K2bv
|
||||
NpbsWX0ta2pDPhiBpIbrTrTmw656MMRkwMLYIAX7BFhyjO9gO0nVXfU1SSTDsso+
|
||||
qu/K1t2US/rLeJQn8gYiTw6AqmvxHOndLaZQrYef4rUzsYnahNzxcoS1FMVxoJFM
|
||||
o+1Wo0BFBlASv5Az0iFfjd1Uy3+AHB41+2vczNIWSki3mg4hzus2PSS4AA9IYeh+
|
||||
zU/HJMddnVedLKNstTAfR85ftACtsP6JhBqCBqC4mCVsN2ZlgucETbsOMyWYB4+y
|
||||
9b6JIYDA1wxNVBXwN+D4MyALxjmjwcTsL6pXgoVc0JEJWVqQ1zAMMAoGCCsGAQUF
|
||||
BwMC
|
||||
-----END TRUSTED CERTIFICATE-----
|
19
test/certs/root2+serverAuth.pem
Normal file
19
test/certs/root2+serverAuth.pem
Normal file
@ -0,0 +1,19 @@
|
||||
-----BEGIN TRUSTED CERTIFICATE-----
|
||||
MIIC8TCCAdmgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
|
||||
IENBMCAXDTE2MDExNTA4MTk0OVoYDzIxMTYwMTE2MDgxOTQ5WjASMRAwDgYDVQQD
|
||||
DAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyB6dJAD5
|
||||
wbStQf4HE0EhldtDShNVQ/jhDu6s2Ka30FdP4ml1+c2Py7ODUSjSCegXaBIOXCA+
|
||||
R0zaBAJ3ZeqXx3UrE9PiXaHRGZcoPtX4mK9IOHhIdxwPUa6ceSOJn4cHY+p0cFLp
|
||||
/5bnUErp4IqbL1bMd4v8fFxJ0ZDGJahfLiurnYUyalaNCHK+hK2+RaeRgPlsXfiU
|
||||
/vwhhjFhdhixbPm8l+S+2xNySV1JAAzrUvEDdNZ0iBvuVcS2mlhSKTht5Zeg+0C6
|
||||
7kYYqxM9CVZCwcV/aSUImwjeFsNMJsl/nFyEacu6vXz0rjvLwPzTAeVYZy592Gwv
|
||||
akWOtiDdap7WJQIDAQABo1AwTjAdBgNVHQ4EFgQUnM5mQjCrHAgmX3MZbd8Pp65Y
|
||||
Uh4wHwYDVR0jBBgwFoAUnM5mQjCrHAgmX3MZbd8Pp65YUh4wDAYDVR0TBAUwAwEB
|
||||
/zANBgkqhkiG9w0BAQsFAAOCAQEADkH6+rUX2QD5TMBn8x4PR9mTQsxhD2k8K2bv
|
||||
NpbsWX0ta2pDPhiBpIbrTrTmw656MMRkwMLYIAX7BFhyjO9gO0nVXfU1SSTDsso+
|
||||
qu/K1t2US/rLeJQn8gYiTw6AqmvxHOndLaZQrYef4rUzsYnahNzxcoS1FMVxoJFM
|
||||
o+1Wo0BFBlASv5Az0iFfjd1Uy3+AHB41+2vczNIWSki3mg4hzus2PSS4AA9IYeh+
|
||||
zU/HJMddnVedLKNstTAfR85ftACtsP6JhBqCBqC4mCVsN2ZlgucETbsOMyWYB4+y
|
||||
9b6JIYDA1wxNVBXwN+D4MyALxjmjwcTsL6pXgoVc0JEJWVqQ1zAMMAoGCCsGAQUF
|
||||
BwMB
|
||||
-----END TRUSTED CERTIFICATE-----
|
19
test/certs/root2-serverAuth.pem
Normal file
19
test/certs/root2-serverAuth.pem
Normal file
@ -0,0 +1,19 @@
|
||||
-----BEGIN TRUSTED CERTIFICATE-----
|
||||
MIIC8TCCAdmgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
|
||||
IENBMCAXDTE2MDExNTA4MTk0OVoYDzIxMTYwMTE2MDgxOTQ5WjASMRAwDgYDVQQD
|
||||
DAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyB6dJAD5
|
||||
wbStQf4HE0EhldtDShNVQ/jhDu6s2Ka30FdP4ml1+c2Py7ODUSjSCegXaBIOXCA+
|
||||
R0zaBAJ3ZeqXx3UrE9PiXaHRGZcoPtX4mK9IOHhIdxwPUa6ceSOJn4cHY+p0cFLp
|
||||
/5bnUErp4IqbL1bMd4v8fFxJ0ZDGJahfLiurnYUyalaNCHK+hK2+RaeRgPlsXfiU
|
||||
/vwhhjFhdhixbPm8l+S+2xNySV1JAAzrUvEDdNZ0iBvuVcS2mlhSKTht5Zeg+0C6
|
||||
7kYYqxM9CVZCwcV/aSUImwjeFsNMJsl/nFyEacu6vXz0rjvLwPzTAeVYZy592Gwv
|
||||
akWOtiDdap7WJQIDAQABo1AwTjAdBgNVHQ4EFgQUnM5mQjCrHAgmX3MZbd8Pp65Y
|
||||
Uh4wHwYDVR0jBBgwFoAUnM5mQjCrHAgmX3MZbd8Pp65YUh4wDAYDVR0TBAUwAwEB
|
||||
/zANBgkqhkiG9w0BAQsFAAOCAQEADkH6+rUX2QD5TMBn8x4PR9mTQsxhD2k8K2bv
|
||||
NpbsWX0ta2pDPhiBpIbrTrTmw656MMRkwMLYIAX7BFhyjO9gO0nVXfU1SSTDsso+
|
||||
qu/K1t2US/rLeJQn8gYiTw6AqmvxHOndLaZQrYef4rUzsYnahNzxcoS1FMVxoJFM
|
||||
o+1Wo0BFBlASv5Az0iFfjd1Uy3+AHB41+2vczNIWSki3mg4hzus2PSS4AA9IYeh+
|
||||
zU/HJMddnVedLKNstTAfR85ftACtsP6JhBqCBqC4mCVsN2ZlgucETbsOMyWYB4+y
|
||||
9b6JIYDA1wxNVBXwN+D4MyALxjmjwcTsL6pXgoVc0JEJWVqQ1zAMoAoGCCsGAQUF
|
||||
BwMB
|
||||
-----END TRUSTED CERTIFICATE-----
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Primary root: root-cert
|
||||
# root certs variants: CA:false, key2, DN2
|
||||
# trust variants: +serverAuth -serverAuth +clientAuth
|
||||
# trust variants: +serverAuth -serverAuth +clientAuth +anyEKU -anyEKU
|
||||
#
|
||||
./mkcert.sh genroot "Root CA" root-key root-cert
|
||||
./mkcert.sh genss "Root CA" root-key root-nonca
|
||||
@ -15,6 +15,16 @@ openssl x509 -in root-cert.pem -trustout \
|
||||
-addreject serverAuth -out root-serverAuth.pem
|
||||
openssl x509 -in root-cert.pem -trustout \
|
||||
-addtrust clientAuth -out root+clientAuth.pem
|
||||
openssl x509 -in root-cert.pem -trustout \
|
||||
-addreject anyExtendedKeyUsage -out root-anyEKU.pem
|
||||
openssl x509 -in root-cert.pem -trustout \
|
||||
-addtrust anyExtendedKeyUsage -out root+anyEKU.pem
|
||||
openssl x509 -in root-cert2.pem -trustout \
|
||||
-addtrust serverAuth -out root2+serverAuth.pem
|
||||
openssl x509 -in root-cert2.pem -trustout \
|
||||
-addreject serverAuth -out root2-serverAuth.pem
|
||||
openssl x509 -in root-cert2.pem -trustout \
|
||||
-addtrust clientAuth -out root2+clientAuth.pem
|
||||
|
||||
# Primary intermediate ca: ca-cert
|
||||
# ca variants: CA:false, key2, DN2, issuer2, expired
|
||||
|
@ -9,80 +9,110 @@ use OpenSSL::Test qw/:DEFAULT top_file/;
|
||||
setup("test_verify");
|
||||
|
||||
sub verify {
|
||||
my ($cert, $vname, $trusted, $untrusted, @opts) = @_;
|
||||
my @args = qw(openssl verify -verify_name);
|
||||
my ($cert, $purpose, $trusted, $untrusted, @opts) = @_;
|
||||
my @args = qw(openssl verify -purpose);
|
||||
my @path = qw(test certs);
|
||||
push(@args, "$vname", @opts);
|
||||
push(@args, "$purpose", @opts);
|
||||
for (@$trusted) { push(@args, "-trusted", top_file(@path, "$_.pem")) }
|
||||
for (@$untrusted) { push(@args, "-untrusted", top_file(@path, "$_.pem")) }
|
||||
push(@args, top_file(@path, "$cert.pem"));
|
||||
run(app([@args]));
|
||||
}
|
||||
|
||||
plan tests => 29;
|
||||
plan tests => 38;
|
||||
|
||||
# Canonical success
|
||||
ok(verify("ee-cert", "ssl_server", ["root-cert"], ["ca-cert"]),
|
||||
ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]),
|
||||
"verify valid chain");
|
||||
|
||||
# Root CA variants
|
||||
ok(verify("ee-cert", "ssl_server", [qw(root-nonca)], [qw(ca-cert)]),
|
||||
"Trusted certs not subject to CA:true checks");
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(root-cert2)], [qw(ca-cert)]),
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-nonca)], [qw(ca-cert)]),
|
||||
"Trusted CA certs now subject to CA:true checks");
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-cert2)], [qw(ca-cert)]),
|
||||
"fail wrong root key");
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(root-name2)], [qw(ca-cert)]),
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-name2)], [qw(ca-cert)]),
|
||||
"fail wrong root DN");
|
||||
ok(verify("ee-cert", "ssl_server", [qw(root+serverAuth)], [qw(ca-cert)]),
|
||||
ok(verify("ee-cert", "sslserver", [qw(root+serverAuth)], [qw(ca-cert)]),
|
||||
"accept right EKU");
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(root-serverAuth)], [qw(ca-cert)]),
|
||||
ok(verify("ee-cert", "sslserver", [qw(root+anyEKU)], [qw(ca-cert)]),
|
||||
"accept anyEKU");
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-serverAuth)], [qw(ca-cert)]),
|
||||
"fail rejected EKU");
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(root+clientAuth)], [qw(ca-cert)]),
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-anyEKU)], [qw(ca-cert)]),
|
||||
"fail rejected anyEKU");
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root+clientAuth)], [qw(ca-cert)]),
|
||||
"fail wrong EKU");
|
||||
|
||||
# Check that trusted-first is on by setting up paths to different roots
|
||||
# depending on whether the intermediate is the trusted or untrusted one.
|
||||
#
|
||||
ok(verify("ee-cert", "sslserver", [qw(root-serverAuth root-cert2 ca-root2)],
|
||||
[qw(ca-cert)]),
|
||||
"verify trusted-first path");
|
||||
ok(verify("ee-cert", "sslserver", [qw(root-cert root2+serverAuth ca-root2)],
|
||||
[qw(ca-cert)]),
|
||||
"verify trusted-first path right EKU");
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-cert root2-serverAuth ca-root2)],
|
||||
[qw(ca-cert)]),
|
||||
"fail trusted-first path rejected EKU");
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-cert root2+clientAuth ca-root2)],
|
||||
[qw(ca-cert)]),
|
||||
"fail trusted-first path wrong EKU");
|
||||
|
||||
# CA variants
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(root-cert)], [qw(ca-nonca)]),
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-cert)], [qw(ca-nonca)]),
|
||||
"fail non-CA");
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(root-cert)], [qw(ca-cert2)]),
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-cert)], [qw(ca-cert2)]),
|
||||
"fail wrong CA key");
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(root-cert)], [qw(ca-name2)]),
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-cert)], [qw(ca-name2)]),
|
||||
"fail wrong CA DN");
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(root-cert)], [qw(ca-root2)]),
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-cert)], [qw(ca-root2)]),
|
||||
"fail wrong CA issuer");
|
||||
ok(!verify("ee-cert", "ssl_server", [], [qw(ca-cert)], "-partial_chain"),
|
||||
ok(!verify("ee-cert", "sslserver", [], [qw(ca-cert)], "-partial_chain"),
|
||||
"fail untrusted partial");
|
||||
ok(!verify("ee-cert", "ssl_server", [], [qw(ca+serverAuth)], "-partial_chain"),
|
||||
ok(!verify("ee-cert", "sslserver", [], [qw(ca+serverAuth)], "-partial_chain"),
|
||||
"fail untrusted EKU partial");
|
||||
ok(verify("ee-cert", "ssl_server", [qw(ca+serverAuth)], [], "-partial_chain"),
|
||||
ok(verify("ee-cert", "sslserver", [qw(ca+serverAuth)], [], "-partial_chain"),
|
||||
"accept trusted EKU partial");
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(ca-serverAuth)], [], "-partial_chain"),
|
||||
ok(!verify("ee-cert", "sslserver", [qw(ca-serverAuth)], [], "-partial_chain"),
|
||||
"fail rejected EKU partial");
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(ca+clientAuth)], [], "-partial_chain"),
|
||||
ok(!verify("ee-cert", "sslserver", [qw(ca+clientAuth)], [], "-partial_chain"),
|
||||
"fail wrong EKU partial");
|
||||
|
||||
# We now test auxiliary trust even for intermediate trusted certs without
|
||||
# -partial_chain. Note that "-trusted_first" is now always on and cannot
|
||||
# be disabled.
|
||||
ok(verify("ee-cert", "sslserver", [qw(root-cert ca+serverAuth)], [qw(ca-cert)]),
|
||||
"accept trusted EKU");
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-cert ca-serverAuth)], [qw(ca-cert)]),
|
||||
"fail rejected EKU");
|
||||
ok(!verify("ee-cert", "sslserver", [qw(root-cert ca+clientAuth)], [qw(ca-cert)]),
|
||||
"fail wrong EKU");
|
||||
|
||||
# EE variants
|
||||
ok(verify("ee-client", "ssl_client", [qw(root-cert)], [qw(ca-cert)]),
|
||||
ok(verify("ee-client", "sslclient", [qw(root-cert)], [qw(ca-cert)]),
|
||||
"accept client cert");
|
||||
ok(!verify("ee-client", "ssl_server", [qw(root-cert)], [qw(ca-cert)]),
|
||||
ok(!verify("ee-client", "sslserver", [qw(root-cert)], [qw(ca-cert)]),
|
||||
"fail wrong leaf purpose");
|
||||
ok(!verify("ee-cert", "ssl_client", [qw(root-cert)], [qw(ca-cert)]),
|
||||
ok(!verify("ee-cert", "sslclient", [qw(root-cert)], [qw(ca-cert)]),
|
||||
"fail wrong leaf purpose");
|
||||
ok(!verify("ee-cert2", "ssl_server", [qw(root-cert)], [qw(ca-cert)]),
|
||||
ok(!verify("ee-cert2", "sslserver", [qw(root-cert)], [qw(ca-cert)]),
|
||||
"fail wrong CA key");
|
||||
ok(!verify("ee-name2", "ssl_server", [qw(root-cert)], [qw(ca-cert)]),
|
||||
ok(!verify("ee-name2", "sslserver", [qw(root-cert)], [qw(ca-cert)]),
|
||||
"fail wrong CA name");
|
||||
ok(!verify("ee-expired", "ssl_server", [qw(root-cert)], [qw(ca-cert)]),
|
||||
ok(!verify("ee-expired", "sslserver", [qw(root-cert)], [qw(ca-cert)]),
|
||||
"fail expired leaf");
|
||||
ok(verify("ee-cert", "ssl_server", [qw(ee-cert)], [], "-partial_chain"),
|
||||
ok(verify("ee-cert", "sslserver", [qw(ee-cert)], [], "-partial_chain"),
|
||||
"accept last-resort direct leaf match");
|
||||
ok(verify("ee-client", "ssl_client", [qw(ee-client)], [], "-partial_chain"),
|
||||
ok(verify("ee-client", "sslclient", [qw(ee-client)], [], "-partial_chain"),
|
||||
"accept last-resort direct leaf match");
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(ee-client)], [], "-partial_chain"),
|
||||
ok(!verify("ee-cert", "sslserver", [qw(ee-client)], [], "-partial_chain"),
|
||||
"fail last-resort direct leaf non-match");
|
||||
ok(verify("ee-cert", "ssl_server", [qw(ee+serverAuth)], [], "-partial_chain"),
|
||||
ok(verify("ee-cert", "sslserver", [qw(ee+serverAuth)], [], "-partial_chain"),
|
||||
"accept direct match with trusted EKU");
|
||||
ok(!verify("ee-cert", "ssl_server", [qw(ee-serverAuth)], [], "-partial_chain"),
|
||||
ok(!verify("ee-cert", "sslserver", [qw(ee-serverAuth)], [], "-partial_chain"),
|
||||
"reject direct match with rejected EKU");
|
||||
ok(verify("ee-client", "ssl_client", [qw(ee+clientAuth)], [], "-partial_chain"),
|
||||
ok(verify("ee-client", "sslclient", [qw(ee+clientAuth)], [], "-partial_chain"),
|
||||
"accept direct match with trusted EKU");
|
||||
ok(!verify("ee-client", "ssl_client", [qw(ee-clientAuth)], [], "-partial_chain"),
|
||||
ok(!verify("ee-client", "sslclient", [qw(ee-clientAuth)], [], "-partial_chain"),
|
||||
"reject direct match with rejected EKU");
|
||||
|
Loading…
x
Reference in New Issue
Block a user