Move peer chain security checks into x509_vfy.c

A new X509_VERIFY_PARAM_set_auth_level() function sets the
authentication security level.  For verification of SSL peers, this
is automatically set from the SSL security level.  Otherwise, for
now, the authentication security level remains at (effectively) 0
by default.

The new "-auth_level" verify(1) option is available in all the
command-line tools that support the standard verify(1) options.

New verify(1) tests added to check enforcement of chain signature
and public key security levels.  Also added new tests of enforcement
of the verify_depth limit.

Updated documentation.

Reviewed-by: Dr. Stephen Henson <steve@openssl.org>
This commit is contained in:
Viktor Dukhovni 2016-03-18 22:09:41 -04:00
parent 70dd3c6593
commit fbb82a60dc
31 changed files with 543 additions and 73 deletions

View file

@ -180,6 +180,7 @@ void wait_for_async(SSL *s);
OPT_V_POLICY_PRINT, OPT_V_CHECK_SS_SIG, OPT_V_TRUSTED_FIRST, \
OPT_V_SUITEB_128_ONLY, OPT_V_SUITEB_128, OPT_V_SUITEB_192, \
OPT_V_PARTIAL_CHAIN, OPT_V_NO_ALT_CHAINS, OPT_V_NO_CHECK_TIME, \
OPT_V_VERIFY_AUTH_LEVEL, \
OPT_V__LAST
# define OPT_V_OPTIONS \
@ -187,8 +188,10 @@ void wait_for_async(SSL *s);
{ "purpose", OPT_V_PURPOSE, 's', \
"certificate chain purpose"}, \
{ "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name"}, \
{ "verify_depth", OPT_V_VERIFY_DEPTH, 'p', \
"chain depth limit"}, \
{ "verify_depth", OPT_V_VERIFY_DEPTH, 'n', \
"chain depth limit" }, \
{ "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n', \
"chain authentication security level" }, \
{ "attime", OPT_V_ATTIME, 'M', "verification epoch time" }, \
{ "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's', \
"expected peer hostname" }, \
@ -235,6 +238,7 @@ void wait_for_async(SSL *s);
case OPT_V_PURPOSE: \
case OPT_V_VERIFY_NAME: \
case OPT_V_VERIFY_DEPTH: \
case OPT_V_VERIFY_AUTH_LEVEL: \
case OPT_V_ATTIME: \
case OPT_V_VERIFY_HOSTNAME: \
case OPT_V_VERIFY_EMAIL: \

View file

@ -526,6 +526,11 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
if (i >= 0)
X509_VERIFY_PARAM_set_depth(vpm, i);
break;
case OPT_V_VERIFY_AUTH_LEVEL:
i = atoi(opt_arg());
if (i >= 0)
X509_VERIFY_PARAM_set_auth_level(vpm, i);
break;
case OPT_V_ATTIME:
if (!opt_imax(opt_arg(), &t))
return 0;

View file

@ -70,6 +70,7 @@ struct X509_VERIFY_PARAM_st {
int purpose; /* purpose to check untrusted certificates */
int trust; /* trust setting to check */
int depth; /* Verify depth */
int auth_level; /* Security level for chain verification */
STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */
/* Peer identity details */
STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */

View file

@ -203,6 +203,12 @@ const char *X509_verify_cert_error_string(long n)
return ("IP address mismatch");
case X509_V_ERR_DANE_NO_MATCH:
return ("No matching DANE TLSA records");
case X509_V_ERR_EE_KEY_TOO_SMALL:
return ("EE certificate key too weak");
case X509_V_ERR_CA_KEY_TOO_SMALL:
return ("CA certificate key too weak");
case X509_V_ERR_CA_MD_TOO_WEAK:
return ("CA signature digest algorithm too weak");
default:
/* Printing an error number into a static buffer is not thread-safe */

View file

@ -126,6 +126,8 @@ static int check_cert(X509_STORE_CTX *ctx);
static int check_policy(X509_STORE_CTX *ctx);
static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
static int check_dane_issuer(X509_STORE_CTX *ctx, int depth);
static int check_key_level(X509_STORE_CTX *ctx, X509 *cert);
static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert);
static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
unsigned int *preasons, X509_CRL *crl, X509 *x);
@ -221,6 +223,35 @@ static int verify_cb_crl(X509_STORE_CTX *ctx, int err)
return ctx->verify_cb(0, ctx);
}
static int check_auth_level(X509_STORE_CTX *ctx)
{
int i;
int num = sk_X509_num(ctx->chain);
if (ctx->param->auth_level <= 0)
return 1;
for (i = 0; i < num; ++i) {
X509 *cert = sk_X509_value(ctx->chain, i);
/*
* We've already checked the security of the leaf key, so here we only
* check the security of issuer keys.
*/
if (i > 0 && !check_key_level(ctx, cert) &&
verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_KEY_TOO_SMALL) == 0)
return 0;
/*
* We also check the signature algorithm security of all certificates
* except those of the trust anchor at index num-1.
*/
if (i < num - 1 && !check_sig_level(ctx, cert) &&
verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_MD_TOO_WEAK) == 0)
return 0;
}
return 1;
}
static int verify_chain(X509_STORE_CTX *ctx)
{
int err;
@ -232,6 +263,7 @@ static int verify_chain(X509_STORE_CTX *ctx)
*/
if ((ok = build_chain(ctx)) == 0 ||
(ok = check_chain_extensions(ctx)) == 0 ||
(ok = check_auth_level(ctx)) == 0 ||
(ok = check_name_constraints(ctx)) == 0 ||
(ok = check_id(ctx)) == 0 || 1)
X509_get_pubkey_parameters(NULL, ctx->chain);
@ -294,6 +326,11 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
X509_up_ref(ctx->cert);
ctx->num_untrusted = 1;
/* If the peer's public key is too weak, we can stop early. */
if (!check_key_level(ctx, ctx->cert) &&
!verify_cb_cert(ctx, ctx->cert, 0, X509_V_ERR_EE_KEY_TOO_SMALL))
return 0;
/*
* If dane->trecs is an empty stack, we'll fail, since the user enabled
* DANE. If none of the TLSA records were usable, and it makes sense to
@ -308,20 +345,19 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
/*
* Given a STACK_OF(X509) find the issuer of cert (if any)
*/
static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
{
int i;
X509 *issuer, *rv = NULL;;
for (i = 0; i < sk_X509_num(sk); i++) {
issuer = sk_X509_value(sk, i);
if (ctx->check_issued(ctx, x, issuer)) {
rv = issuer;
if (x509_check_cert_time(ctx, rv, -1))
break;
}
X509 *issuer = sk_X509_value(sk, i);
if (!ctx->check_issued(ctx, x, issuer))
continue;
if (x509_check_cert_time(ctx, issuer, -1))
return issuer;
}
return rv;
return NULL;
}
/* Given a possible certificate and issuer check them */
@ -2656,6 +2692,19 @@ static int dane_verify(X509_STORE_CTX *ctx)
return verify_chain(ctx);
}
/* Get issuer, without duplicate suppression */
static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert)
{
STACK_OF(X509) *saved_chain = ctx->chain;
int ok;
ctx->chain = NULL;
ok = ctx->get_issuer(issuer, ctx, cert);
ctx->chain = saved_chain;
return ok;
}
static int build_chain(X509_STORE_CTX *ctx)
{
struct dane_st *dane = (struct dane_st *)ctx->dane;
@ -2735,12 +2784,19 @@ static int build_chain(X509_STORE_CTX *ctx)
/*
* Look in the trust store if enabled for first lookup, or we've run
* out of untrusted issuers and search here is not disabled. When
* we exceed the depth limit, we simulate absence of a match.
* out of untrusted issuers and search here is not disabled. When we
* reach the depth limit, we stop extending the chain, if by that point
* we've not found a trust-anchor, any trusted chain would be too long.
*
* The error reported to the application verify callback is at the
* maximal valid depth with the current certificate equal to the last
* not ultimately-trusted issuer. For example, with verify_depth = 0,
* the callback will report errors at depth=1 when the immediate issuer
* of the leaf certificate is not a trust anchor. No attempt will be
* made to locate an issuer for that certificate, since such a chain
* would be a-priori too long.
*/
if ((search & S_DOTRUSTED) != 0) {
STACK_OF(X509) *hide = ctx->chain;
i = num = sk_X509_num(ctx->chain);
if ((search & S_DOALTERNATE) != 0) {
/*
@ -2762,10 +2818,7 @@ static int build_chain(X509_STORE_CTX *ctx)
}
x = sk_X509_value(ctx->chain, i-1);
/* Suppress duplicate suppression */
ctx->chain = NULL;
ok = (depth < num) ? 0 : ctx->get_issuer(&xtmp, ctx, x);
ctx->chain = hide;
ok = (depth < num) ? 0 : get_issuer(&xtmp, ctx, x);
if (ok < 0) {
trust = X509_TRUST_REJECTED;
@ -2892,12 +2945,12 @@ static int build_chain(X509_STORE_CTX *ctx)
num = sk_X509_num(ctx->chain);
OPENSSL_assert(num == ctx->num_untrusted);
x = sk_X509_value(ctx->chain, num-1);
xtmp = (depth < num) ? NULL : find_issuer(ctx, sktmp, x);
/*
* Once we run out of untrusted issuers, we stop looking for more
* and start looking only in the trust store if enabled.
*/
xtmp = (ss || depth < num) ? NULL : find_issuer(ctx, sktmp, x);
if (xtmp == NULL) {
search &= ~S_DOUNTRUSTED;
if (may_trusted)
@ -2905,22 +2958,20 @@ static int build_chain(X509_STORE_CTX *ctx)
continue;
}
if (!sk_X509_push(ctx->chain, x = xtmp)) {
/* Drop this issuer from future consideration */
(void) sk_X509_delete_ptr(sktmp, xtmp);
if (!sk_X509_push(ctx->chain, xtmp)) {
X509err(X509_F_BUILD_CHAIN, ERR_R_MALLOC_FAILURE);
trust = X509_TRUST_REJECTED;
search = 0;
continue;
}
X509_up_ref(x);
X509_up_ref(x = xtmp);
++ctx->num_untrusted;
ss = cert_self_signed(xtmp);
/*
* Not strictly necessary, but saves cycles looking at the same
* certificates over and over.
*/
(void) sk_X509_delete_ptr(sktmp, x);
/*
* Check for DANE-TA trust of the topmost untrusted certificate.
*/
@ -2974,3 +3025,60 @@ static int build_chain(X509_STORE_CTX *ctx)
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY);
}
}
static const int minbits_table[] = { 80, 112, 128, 192, 256 };
static const int NUM_AUTH_LEVELS = OSSL_NELEM(minbits_table);
/*
* Check whether the public key of ``cert`` meets the security level of
* ``ctx``.
*
* Returns 1 on success, 0 otherwise.
*/
static int check_key_level(X509_STORE_CTX *ctx, X509 *cert)
{
EVP_PKEY *pkey = X509_get0_pubkey(cert);
int level = ctx->param->auth_level;
/* Unsupported or malformed keys are not secure */
if (pkey == NULL)
return 0;
if (level <= 0)
return 1;
if (level > NUM_AUTH_LEVELS)
level = NUM_AUTH_LEVELS;
return EVP_PKEY_security_bits(pkey) >= minbits_table[level - 1];
}
/*
* Check whether the signature digest algorithm of ``cert`` meets the security
* level of ``ctx``. Should not be checked for trust anchors (whether
* self-signed or otherwise).
*
* Returns 1 on success, 0 otherwise.
*/
static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert)
{
int nid = X509_get_signature_nid(cert);
int mdnid = NID_undef;
int secbits = -1;
int level = ctx->param->auth_level;
if (level <= 0)
return 1;
if (level > NUM_AUTH_LEVELS)
level = NUM_AUTH_LEVELS;
/* Lookup signature algorithm digest */
if (nid && OBJ_find_sigid_algs(nid, &mdnid, NULL)) {
const EVP_MD *md;
/* Assume 4 bits of collision resistance for each hash octet */
if (mdnid != NID_undef && (md = EVP_get_digestbynid(mdnid)) != NULL)
secbits = EVP_MD_size(md) * 4;
}
return secbits >= minbits_table[level - 1];
}

View file

@ -140,6 +140,7 @@ static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
param->inh_flags = 0;
param->flags = 0;
param->depth = -1;
param->auth_level = -1; /* -1 means unset, 0 is explicit */
sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
param->policies = NULL;
sk_OPENSSL_STRING_pop_free(param->hosts, str_free);
@ -245,6 +246,7 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
x509_verify_param_copy(purpose, 0);
x509_verify_param_copy(trust, X509_TRUST_DEFAULT);
x509_verify_param_copy(depth, -1);
x509_verify_param_copy(auth_level, -1);
/* If overwrite or check time not set, copy across */
@ -368,6 +370,11 @@ void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
param->depth = depth;
}
void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level)
{
param->auth_level = auth_level;
}
void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
{
param->check_time = t;
@ -493,6 +500,11 @@ int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
return param->depth;
}
int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param)
{
return param->auth_level;
}
const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
{
return param->name;
@ -515,6 +527,7 @@ static const X509_VERIFY_PARAM default_table[] = {
0, /* purpose */
0, /* trust */
100, /* depth */
-1, /* auth_level */
NULL, /* policies */
vpm_empty_id},
{
@ -525,6 +538,7 @@ static const X509_VERIFY_PARAM default_table[] = {
X509_PURPOSE_SMIME_SIGN, /* purpose */
X509_TRUST_EMAIL, /* trust */
-1, /* depth */
-1, /* auth_level */
NULL, /* policies */
vpm_empty_id},
{
@ -535,6 +549,7 @@ static const X509_VERIFY_PARAM default_table[] = {
X509_PURPOSE_SMIME_SIGN, /* purpose */
X509_TRUST_EMAIL, /* trust */
-1, /* depth */
-1, /* auth_level */
NULL, /* policies */
vpm_empty_id},
{
@ -545,6 +560,7 @@ static const X509_VERIFY_PARAM default_table[] = {
X509_PURPOSE_SSL_CLIENT, /* purpose */
X509_TRUST_SSL_CLIENT, /* trust */
-1, /* depth */
-1, /* auth_level */
NULL, /* policies */
vpm_empty_id},
{
@ -555,6 +571,7 @@ static const X509_VERIFY_PARAM default_table[] = {
X509_PURPOSE_SSL_SERVER, /* purpose */
X509_TRUST_SSL_SERVER, /* trust */
-1, /* depth */
-1, /* auth_level */
NULL, /* policies */
vpm_empty_id}
};

View file

@ -58,6 +58,7 @@ B<openssl> B<cms>
[B<-trusted_first>]
[B<-no_alt_chains>]
[B<-use_deltas>]
[B<-auth_level num>]
[B<-verify_depth num>]
[B<-verify_email email>]
[B<-verify_hostname hostname>]
@ -475,8 +476,8 @@ B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
B<-inhibit_map>, B<-no_alt_chains>, B<-partial_chain>, B<-policy>,
B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
B<-verify_name>, B<-x509_strict>
B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
B<-verify_ip>, B<-verify_name>, B<-x509_strict>
Set various certificate chain validation options. See the
L<verify(1)> manual page for details.

View file

@ -53,6 +53,7 @@ B<openssl> B<ocsp>
[B<-trusted_first>]
[B<-no_alt_chains>]
[B<-use_deltas>]
[B<-auth_level num>]
[B<-verify_depth num>]
[B<-verify_email email>]
[B<-verify_hostname hostname>]
@ -197,11 +198,11 @@ B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
B<-inhibit_map>, B<-no_alt_chains>, B<-partial_chain>, B<-policy>,
B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
B<-verify_name>, B<-x509_strict>
B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
B<-verify_ip>, B<-verify_name>, B<-x509_strict>
Set different certificate verification options.
See L<B<verify>|verify(1)> manual page for details.
See L<verify(1)> manual page for details.
=item B<-verify_other file>

View file

@ -45,6 +45,7 @@ B<openssl> B<s_client>
[B<-trusted_first>]
[B<-no_alt_chains>]
[B<-use_deltas>]
[B<-auth_level num>]
[B<-verify_depth num>]
[B<-verify_email email>]
[B<-verify_hostname hostname>]
@ -229,8 +230,8 @@ B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
B<-inhibit_map>, B<-no_alt_chains>, B<-partial_chain>, B<-policy>,
B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
B<-verify_name>, B<-x509_strict>
B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
B<-verify_ip>, B<-verify_name>, B<-x509_strict>
Set various certificate chain validation options. See the
L<verify(1)> manual page for details.

View file

@ -55,6 +55,7 @@ B<openssl> B<s_server>
[B<-trusted_first>]
[B<-no_alt_chains>]
[B<-use_deltas>]
[B<-auth_level num>]
[B<-verify_depth num>]
[B<-verify_return_error>]
[B<-verify_email email>]
@ -234,8 +235,8 @@ B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
B<-inhibit_map>, B<-no_alt_chains>, B<-partial_chain>, B<-policy>,
B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
B<-verify_name>, B<-x509_strict>
B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
B<-verify_ip>, B<-verify_name>, B<-x509_strict>
Set different peer certificate verification options.
See the L<verify(1)> manual page for details.

View file

@ -40,6 +40,7 @@ B<openssl> B<smime>
[B<-trusted_first>]
[B<-no_alt_chains>]
[B<-use_deltas>]
[B<-auth_level num>]
[B<-verify_depth num>]
[B<-verify_email email>]
[B<-verify_hostname hostname>]
@ -307,8 +308,8 @@ B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
B<-inhibit_map>, B<-no_alt_chains>, B<-partial_chain>, B<-policy>,
B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
B<-verify_name>, B<-x509_strict>
B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
B<-verify_ip>, B<-verify_name>, B<-x509_strict>
Set various options of certificate chain verification. See
L<verify(1)> manual page for details.

View file

@ -73,6 +73,7 @@ I<verify options:>
[-suiteB_192]
[-trusted_first]
[-use_deltas]
[-auth_level num]
[-verify_depth num]
[-verify_email email]
[-verify_hostname hostname]
@ -371,17 +372,15 @@ all intermediate CA certificates unless the response includes them.
=item I<verify options>
The options [-attime timestamp], [-check_ss_sig], [-crl_check],
[-crl_check_all], [-explicit_policy], [-extended_crl],
[-ignore_critical], [-inhibit_any], [-inhibit_map],
[-issuer_checks], [-no_alt_chains], [-no_check_time],
[-partial_chain], [-policy arg], [-policy_check],
[-policy_print], [-purpose purpose], [-suiteB_128],
[-suiteB_128_only], [-suiteB_192], [-trusted_first],
[-use_deltas], [-verify_depth num], [-verify_email email],
[-verify_hostname hostname], [-verify_ip ip], [-verify_name name],
and [-x509_strict] can be used to control timestamp verification.
See L<verify(1)>.
The options B<-attime timestamp>, B<-check_ss_sig>, B<-crl_check>,
B<-crl_check_all>, B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>,
B<-inhibit_any>, B<-inhibit_map>, B<-issuer_checks>, B<-no_alt_chains>,
B<-no_check_time>, B<-partial_chain>, B<-policy>, B<-policy_check>,
B<-policy_print>, B<-purpose>, B<-suiteB_128>, B<-suiteB_128_only>,
B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>, B<-auth_level>,
B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
B<-verify_name>, and B<-x509_strict> can be used to control timestamp
verification. See L<verify(1)>.
=back

View file

@ -38,6 +38,7 @@ B<openssl> B<verify>
[B<-trusted file>]
[B<-use_deltas>]
[B<-verbose>]
[B<-auth_level level>]
[B<-verify_depth num>]
[B<-verify_email email>]
[B<-verify_hostname hostname>]
@ -227,9 +228,30 @@ Enable support for delta CRLs.
Print extra information about the operations being performed.
=item B<-auth_level level>
Set the certificate chain authentication security level to B<level>.
The authentication security level determines the acceptable signature and
public key strength when verifying certificate chains.
For a certificate chain to validate, the public keys of all the certificates
must meet the specified security B<level>.
The signature algorithm security level is enforced for all the certificates in
the chain except for the chain's I<trust anchor>, which is either directly
trusted or validated by means other than its signature.
See L<SSL_CTX_set_security_level(3)> for the definitions of the available
levels.
The default security level is -1, or "not set".
At security level 0 or lower all algorithms are acceptable.
Security level 1 requires at least 80-bit-equivalent security and is broadly
interoperable, though it will, for example, reject MD5 signatures or RSA keys
shorter than 1024 bits.
=item B<-verify_depth num>
Limit the maximum depth of the certificate chain to B<num> certificates.
Limit the certificate chain to B<num> intermediate CA certificates.
A maximal depth chain can have up to B<num+2> certificates, since neither the
end-entity certificate nor the trust-anchor certificate count against the
B<-verify_depth> limit.
=item B<-verify_email email>

View file

@ -2,15 +2,16 @@
=head1 NAME
X509_VERIFY_PARAM_set_flags, X509_VERIFY_PARAM_clear_flags, X509_VERIFY_PARAM_get_flags, X509_VERIFY_PARAM_set_purpose, X509_VERIFY_PARAM_set_trust, X509_VERIFY_PARAM_set_depth, X509_VERIFY_PARAM_get_depth, X509_VERIFY_PARAM_set_time, X509_VERIFY_PARAM_add0_policy, X509_VERIFY_PARAM_set1_policies, X509_VERIFY_PARAM_set1_host, X509_VERIFY_PARAM_add1_host, X509_VERIFY_PARAM_set_hostflags, X509_VERIFY_PARAM_get0_peername, X509_VERIFY_PARAM_set1_email, X509_VERIFY_PARAM_set1_ip, X509_VERIFY_PARAM_set1_ip_asc - X509 verification parameters
X509_VERIFY_PARAM_set_flags, X509_VERIFY_PARAM_clear_flags, X509_VERIFY_PARAM_get_flags, X509_VERIFY_PARAM_set_purpose, X509_VERIFY_PARAM_set_trust, X509_VERIFY_PARAM_set_depth, X509_VERIFY_PARAM_get_depth, X509_VERIFY_PARAM_set_auth_level, X509_VERIFY_PARAM_get_auth_level, X509_VERIFY_PARAM_set_time, X509_VERIFY_PARAM_add0_policy, X509_VERIFY_PARAM_set1_policies, X509_VERIFY_PARAM_set1_host, X509_VERIFY_PARAM_add1_host, X509_VERIFY_PARAM_set_hostflags, X509_VERIFY_PARAM_get0_peername, X509_VERIFY_PARAM_set1_email, X509_VERIFY_PARAM_set1_ip, X509_VERIFY_PARAM_set1_ip_asc - X509 verification parameters
=head1 SYNOPSIS
#include <openssl/x509_vfy.h>
int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags);
int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param,
unsigned long flags);
int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
unsigned long flags);
unsigned long flags);
unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose);
@ -19,13 +20,17 @@ X509_VERIFY_PARAM_set_flags, X509_VERIFY_PARAM_clear_flags, X509_VERIFY_PARAM_ge
void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t);
int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
ASN1_OBJECT *policy);
ASN1_OBJECT *policy);
int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
STACK_OF(ASN1_OBJECT) *policies);
void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth);
int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param);
void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param,
int auth_level);
int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
const char *name, size_t namelen);
int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
@ -71,8 +76,32 @@ policy set is cleared. The B<policies> parameter can be B<NULL> to clear
an existing policy set.
X509_VERIFY_PARAM_set_depth() sets the maximum verification depth to B<depth>.
That is the maximum number of untrusted CA certificates that can appear in a
That is the maximum number of intermediate CA certificates that can appear in a
chain.
A maximal depth chain contains 2 more certificates than the limit, since
neither the end-entity ceritificate nor the trust-anchor count against this
limit.
Thus a B<depth> limit of 0 only allows the end-entity certificate to be signed
directly by the trust-anchor, while with a B<depth> limit of 1 there can be one
intermediate CA certificate between the trust-anchor and the end-entity
certificate.
X509_VERIFY_PARAM_set_auth_level() sets the authentication security level to
B<auth_level>.
The authentication security level determines the acceptable signature and public
key strength when verifying certificate chains.
For a certificate chain to validate, the public keys of all the certificates
must meet the specified security level.
The signature algorithm security level is not enforced for the chain's I<trust
anchor> certificate, which is either directly trusted or validated by means other
than its signature.
See L<SSL_CTX_set_security_level(3)> for the definitions of the available
levels.
The default security level is -1, or "not set".
At security level 0 or lower all algorithms are acceptable.
Security level 1 requires at least 80-bit-equivalent security and is broadly
interoperable, though it will, for example, reject MD5 signatures or RSA keys
shorter than 1024 bits.
X509_VERIFY_PARAM_set1_host() sets the expected DNS hostname to
B<name> clearing any previously specified host name or names. If
@ -139,6 +168,9 @@ values.
X509_VERIFY_PARAM_get_depth() returns the current verification depth.
X509_VERIFY_PARAM_get_auth_level() returns the current authentication security
level.
=head1 VERIFICATION FLAGS
The verification flags consists of zero or more of the following flags

View file

@ -355,7 +355,10 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
# define X509_V_ERR_IP_ADDRESS_MISMATCH 64
/* DANE TLSA errors */
# define X509_V_ERR_DANE_NO_MATCH 65
/* security level errors */
# define X509_V_ERR_EE_KEY_TOO_SMALL 66
# define X509_V_ERR_CA_KEY_TOO_SMALL 67
# define X509_V_ERR_CA_MD_TOO_WEAK 68
/* Certificate verify flags */
@ -552,6 +555,7 @@ unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose);
int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust);
void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth);
void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level);
void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t);
int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
ASN1_OBJECT *policy);
@ -574,6 +578,7 @@ int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param,
const char *ipasc);
int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param);
const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param);
int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param);

View file

@ -494,6 +494,12 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
return (0);
}
param = X509_STORE_CTX_get0_param(&ctx);
/*
* XXX: Separate @AUTHSECLEVEL and @TLSSECLEVEL would be useful at some
* point, for now a single @SECLEVEL sets the same policy for TLS crypto
* and PKI authentication.
*/
X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(s));
/* Set suite B flags if needed */
X509_STORE_CTX_set_flags(&ctx, tls1_suiteb(s));
@ -520,17 +526,8 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
if (s->ctx->app_verify_callback != NULL)
i = s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg);
else {
else
i = X509_verify_cert(&ctx);
# if 0
/* Dummy error calls so mkerr generates them */
SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, SSL_R_EE_KEY_TOO_SMALL);
SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, SSL_R_CA_KEY_TOO_SMALL);
SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK);
# endif
if (i > 0)
i = ssl_security_cert_chain(s, ctx.chain, NULL, 1);
}
s->verify_result = ctx.error;
sk_X509_pop_free(s->verified_chain, X509_free);
@ -894,12 +891,18 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
* ignore the error return from this call. We're not actually verifying
* the cert - we're just building as much of the chain as we can
*/
X509_verify_cert(&xs_ctx);
(void) X509_verify_cert(&xs_ctx);
/* Don't leave errors in the queue */
ERR_clear_error();
i = ssl_security_cert_chain(s, xs_ctx.chain, NULL, 0);
if (i != 1) {
X509_STORE_CTX_cleanup(&xs_ctx);
#if 0
/* Dummy error calls so mkerr generates them */
SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_EE_KEY_TOO_SMALL);
SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_KEY_TOO_SMALL);
SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK);
#endif
SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, i);
return 0;
}

View file

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICRDCCASygAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
IENBMCAXDTE2MDMyMDA2MjcyN1oYDzIxMTYwMzIxMDYyNzI3WjANMQswCQYDVQQD
DAJDQTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQC3wNLc1A9gAjz1H94ozPrLOhE2
R8c6RQjkUIALCOuw8xbZV+AEDSqP11Bw8MVzvmpksR9s1idJhLOugwMNTHfTXJjV
DWoQh9ofR51J5sOph4yDhQBXRmiuvqMDj+a81UkCAwEAAaNQME4wHQYDVR0OBBYE
FKrzei/LKJop6yShiJupKskW0ZQcMB8GA1UdIwQYMBaAFI71Ja8em2uEPXyAmslT
nE1y96NSMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFr4hjVtLuZz
gxLILAOREEtanckfnapUrhTLukog9Q8uzqMUE+YDEhkcP4YAVjcab6HaXrbcxXsn
zn+v+GPszD9G3doGbUjuwEEAHz+k/9sjsn8QAGw/XslYhd5dktaRRCqaTNiWT+Ks
xKntAsgXcgWNIpvGikzTB/W7IrjIV8/S1JjLABtoY88tFUX81Ohr3bFFsRc9EHVS
MtGnEwfoBOSlCUjaTWBNHHi1HstK9sG2SNT/nhN1HATk/aiCiQRKr/bm6ezPC2If
6mRidaNiQN8+vzvtn86BqtRJOEi8jj5CBax6IqwfE+lDZIwT7H9C9Cu8Yp4mTM0x
wwzRDnFVisM=
-----END CERTIFICATE-----

View file

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICSjCCAdSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
IENBMCAXDTE2MDMyMDA2MjcyN1oYDzIxMTYwMzIxMDYyNzI3WjANMQswCQYDVQQD
DAJDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJadpD0ASxxfxsvd
j9IxsogVzMSGLFziaYuE9KejU9+R479RifvwfBANO62sNWJ19X//9G5UjwWmkiOz
n1k50DkYsBBA3mJzik6wjt/c58lBIlSEgAgpvDU8ht8w3t20JP9+YqXAeugqFj/W
l9rFQtsvaWSRywjXVlp5fxuEQelNnXcJEKhsKTNExsBUZebo4/J1BWpklWzA9P0l
YW5INvDAAwcF1nzlEf0Y6Eot03IMNyg2MTE4hehxjdgCSci8GYnFirE/ojXqqpAc
ZGh7r2dqWgZUD1Dh+bT2vjrUzj8eTH3GdzI+oljt29102JIUaqj3yzRYkah8FLF9
CLNNsUcCAwEAAaNQME4wHQYDVR0OBBYEFLQRM/HX4l73U54gIhBPhga/H8leMB8G
A1UdIwQYMBaAFFjzE/eu8wvKwzb2aODw52C+0gLVMAwGA1UdEwQFMAMBAf8wDQYJ
KoZIhvcNAQELBQADYQCZM1sSpIyjyuGirBYvezFryUq5EyZiME3HIHJ7AbmquPtE
LcoE8lwxEYXl7OTbLZHxIKkt6+WX2TL/0yshJLq/42nh5DZwyug7fIITmkzmzidF
rbnl7fIop7OJX/kELbY=
-----END CERTIFICATE-----

View file

@ -0,0 +1,18 @@
-----BEGIN TRUSTED CERTIFICATE-----
MIIC7DCCAdSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADASMRAwDgYDVQQDDAdSb290
IENBMCAXDTE2MDMyMDA2MjcyN1oYDzIxMTYwMzIxMDYyNzI3WjANMQswCQYDVQQD
DAJDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJadpD0ASxxfxsvd
j9IxsogVzMSGLFziaYuE9KejU9+R479RifvwfBANO62sNWJ19X//9G5UjwWmkiOz
n1k50DkYsBBA3mJzik6wjt/c58lBIlSEgAgpvDU8ht8w3t20JP9+YqXAeugqFj/W
l9rFQtsvaWSRywjXVlp5fxuEQelNnXcJEKhsKTNExsBUZebo4/J1BWpklWzA9P0l
YW5INvDAAwcF1nzlEf0Y6Eot03IMNyg2MTE4hehxjdgCSci8GYnFirE/ojXqqpAc
ZGh7r2dqWgZUD1Dh+bT2vjrUzj8eTH3GdzI+oljt29102JIUaqj3yzRYkah8FLF9
CLNNsUcCAwEAAaNQME4wHQYDVR0OBBYEFLQRM/HX4l73U54gIhBPhga/H8leMB8G
A1UdIwQYMBaAFI71Ja8em2uEPXyAmslTnE1y96NSMAwGA1UdEwQFMAMBAf8wDQYJ
KoZIhvcNAQEEBQADggEBACTmLO0KOkXFNjj6hXozC9GzQYMXdCfNmgMuetk8xdVm
TqkF/qIGK2FBWn91IH0/9ydZbL83EKjPjqjwqzXqExJ0Un+fy7XbYMKtjGJ21egJ
x97jzKey5phEwRD/4fJ+PCml9eE/SNzBV0xKSDq4qQYvSJ3GF6KCATVlr0bDzQJZ
yTY3FeNoy+K7Mb0rHtsGru60C/Ft1dl9uiJ+yKXMiCxPcDjYb+95mA9QJ1kXfR8J
JVfeKhEEK+QIVpz/37aQ4jx/zbGblFsruALK22aLnpgrfUzrsYQ8W8T/DV2dV1ra
4wHz/QtlE4isInOaK2+pvXwyGar+1/s3+VxXEiPlZ7IwCDAGBgRVHSUA
-----END TRUSTED CERTIFICATE-----

View file

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC7DCCAdSgAwIBAgIBAjANBgkqhkiG9w0BAQQFADASMRAwDgYDVQQDDAdSb290
IENBMCAXDTE2MDMyMDA2MjcyN1oYDzIxMTYwMzIxMDYyNzI3WjANMQswCQYDVQQD
DAJDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJadpD0ASxxfxsvd
j9IxsogVzMSGLFziaYuE9KejU9+R479RifvwfBANO62sNWJ19X//9G5UjwWmkiOz
n1k50DkYsBBA3mJzik6wjt/c58lBIlSEgAgpvDU8ht8w3t20JP9+YqXAeugqFj/W
l9rFQtsvaWSRywjXVlp5fxuEQelNnXcJEKhsKTNExsBUZebo4/J1BWpklWzA9P0l
YW5INvDAAwcF1nzlEf0Y6Eot03IMNyg2MTE4hehxjdgCSci8GYnFirE/ojXqqpAc
ZGh7r2dqWgZUD1Dh+bT2vjrUzj8eTH3GdzI+oljt29102JIUaqj3yzRYkah8FLF9
CLNNsUcCAwEAAaNQME4wHQYDVR0OBBYEFLQRM/HX4l73U54gIhBPhga/H8leMB8G
A1UdIwQYMBaAFI71Ja8em2uEPXyAmslTnE1y96NSMAwGA1UdEwQFMAMBAf8wDQYJ
KoZIhvcNAQEEBQADggEBACTmLO0KOkXFNjj6hXozC9GzQYMXdCfNmgMuetk8xdVm
TqkF/qIGK2FBWn91IH0/9ydZbL83EKjPjqjwqzXqExJ0Un+fy7XbYMKtjGJ21egJ
x97jzKey5phEwRD/4fJ+PCml9eE/SNzBV0xKSDq4qQYvSJ3GF6KCATVlr0bDzQJZ
yTY3FeNoy+K7Mb0rHtsGru60C/Ft1dl9uiJ+yKXMiCxPcDjYb+95mA9QJ1kXfR8J
JVfeKhEEK+QIVpz/37aQ4jx/zbGblFsruALK22aLnpgrfUzrsYQ8W8T/DV2dV1ra
4wHz/QtlE4isInOaK2+pvXwyGar+1/s3+VxXEiPlZ7I=
-----END CERTIFICATE-----

13
test/certs/ca-key-768.pem Normal file
View file

@ -0,0 +1,13 @@
-----BEGIN PRIVATE KEY-----
MIIB5QIBADANBgkqhkiG9w0BAQEFAASCAc8wggHLAgEAAmEAt8DS3NQPYAI89R/e
KMz6yzoRNkfHOkUI5FCACwjrsPMW2VfgBA0qj9dQcPDFc75qZLEfbNYnSYSzroMD
DUx301yY1Q1qEIfaH0edSebDqYeMg4UAV0Zorr6jA4/mvNVJAgMBAAECYQCJAsu3
QJ9eNQ0CsQpTXdO6aMegs5CHkCX7J1Lx52rl+7uTv4QXQUH1EtS2AbEYhmdGzMFN
ZlBrg1vDsW/yn02NZzvT6xT/kvzFhQVw1i8B0YyB8wPao3f2ZxPkAfeoAAECMQDa
6VkNYlHgPOlTtwU1WYUirFczpipQsuk/lIf7B3+rVRUHoAE4nbeIRJgkKZaJEAEC
MQDW4pYsyN79HEqFpOFlfsrERw3y4hLRXGeHxbfJFdAe7SUfNj28ZI2EPFE0DJhX
RUkCMA39M2+jhM/rlI2A+Jg8LEHW+YuXZsTZagZiG35zMDlmqn1eQDW5/mx61a4Z
6kDAAQIwIlbZWtTK1bX0rsC3iEmny4/zSbIZAb37iXXuNcM3nAmXmhJH8Vg8STp+
W4v7uE6JAjEAwiB9wCVwG4UhvKNQ4Wd2mfJiKZQNF4rL4ID0g+Wk6kX67c7u2hfH
sSaluw9nM91s
-----END PRIVATE KEY-----

View file

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICeDCCAWCgAwIBAgIBAjANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDDAJDQTAg
Fw0xNjAzMjAwNjI3MjdaGA8yMTE2MDMyMTA2MjcyN1owGTEXMBUGA1UEAwwOc2Vy
dmVyLmV4YW1wbGUwfDANBgkqhkiG9w0BAQEFAANrADBoAmEAwCvrPAynx+7VtpFz
4cWZW3/n3/nMwK4fxkWSB0kbVUhQaYiaQGWEfB4JpRz5rPt8NW5m2aVGT7mMjScu
8YyFa3IDdpBeQL1n8VQUH3FLySgQHC1bkkzwyzQM8JirCdl/AgMBAAGjfTB7MB0G
A1UdDgQWBBSRBasp1P/UDCesreviw4Lwz8tFBDAfBgNVHSMEGDAWgBS0ETPx1+Je
91OeICIQT4YGvx/JXjAJBgNVHRMEAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMBkG
A1UdEQQSMBCCDnNlcnZlci5leGFtcGxlMA0GCSqGSIb3DQEBCwUAA4IBAQB5xled
do7U++n86KmJDGnXd4XMpr1QbTFVSO7fhSiObeGm961re/TI7AhuLlsZYP601YhZ
pRe9B7tiEuzu3iCD4kKB0yxgUCSsF0u1KbHSUNe2H5bBJC21c2eLZh6U54y014nL
gFSDOsA8M1301+Hlh5AS+4iTR0Ra02RaZb3L5HCR2wtkJubh3rSj8eBzb6fx+Lhw
JoeRg34lhycGC4bBVwkRT8bo73Nrs71JUP2A6/PjdsIfF2rtVMEuIq8AMQ5wInZ+
2mIxJ4MwCClwLCq3VxI1bzdf1TYsPNxYTUS1POb2VgNofG0mBTHNUYUO20aF0ct8
PCQqIqxUIegfS3f5
-----END CERTIFICATE-----

View file

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICfjCCAgigAwIBAgIBAjANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDDAJDQTAg
Fw0xNjAzMjAwNjI3MjdaGA8yMTE2MDMyMTA2MjcyN1owGTEXMBUGA1UEAwwOc2Vy
dmVyLmV4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo/4lY
YYWu3tssD9Vz++K3qBt6dWAr1H08c3a1rt6TL38kkG3JHPSKOM2fooAWVsu0LLuT
5Rcf/w3GQ/4xNPgo2HXpo7uIgu+jcuJTYgVFTeAxl++qnRDSWA2eBp4yuxsIVl1l
Dz9mjsI2oBH/wFk1/Ukc3RxCMwZ4rgQ4I+XndWfTlK1aqUAfrFkQ9QzBZK1KxMY1
U7OWaoIbFYvRmavknm+UqtKW5Vf7jJFkijwkFsbSGb6CYBM7YrDtPh2zyvlr3zG5
ep5LR2inKcc/SuIiJ7TvkGPX79ByST5brbkb1Ctvhmjd1XMSuEPJ3EEPoqNGT4tn
iIQPYf55NB9KiR+3AgMBAAGjfTB7MB0GA1UdDgQWBBTnm+IqrYpsOst2UeWOB5gi
l+FzojAfBgNVHSMEGDAWgBSq83ovyyiaKeskoYibqSrJFtGUHDAJBgNVHRMEAjAA
MBMGA1UdJQQMMAoGCCsGAQUFBwMBMBkGA1UdEQQSMBCCDnNlcnZlci5leGFtcGxl
MA0GCSqGSIb3DQEBCwUAA2EASAwDwXsYGnhQDyWixI9eKZwXAA9E4rEIdmKNvVjU
jWkMh1oC0FZl4TTHU+sAaXmv2QItZOcG2QEHoTIZDPYiy+7eZC7pPQY25dkxeSZ9
TIlMnfePzYTc3BnfxZj82Mny
-----END CERTIFICATE-----

View file

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDIDCCAgigAwIBAgIBAjANBgkqhkiG9w0BAQQFADANMQswCQYDVQQDDAJDQTAg
Fw0xNjAzMjAwNjI3MjdaGA8yMTE2MDMyMTA2MjcyN1owGTEXMBUGA1UEAwwOc2Vy
dmVyLmV4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo/4lY
YYWu3tssD9Vz++K3qBt6dWAr1H08c3a1rt6TL38kkG3JHPSKOM2fooAWVsu0LLuT
5Rcf/w3GQ/4xNPgo2HXpo7uIgu+jcuJTYgVFTeAxl++qnRDSWA2eBp4yuxsIVl1l
Dz9mjsI2oBH/wFk1/Ukc3RxCMwZ4rgQ4I+XndWfTlK1aqUAfrFkQ9QzBZK1KxMY1
U7OWaoIbFYvRmavknm+UqtKW5Vf7jJFkijwkFsbSGb6CYBM7YrDtPh2zyvlr3zG5
ep5LR2inKcc/SuIiJ7TvkGPX79ByST5brbkb1Ctvhmjd1XMSuEPJ3EEPoqNGT4tn
iIQPYf55NB9KiR+3AgMBAAGjfTB7MB0GA1UdDgQWBBTnm+IqrYpsOst2UeWOB5gi
l+FzojAfBgNVHSMEGDAWgBS0ETPx1+Je91OeICIQT4YGvx/JXjAJBgNVHRMEAjAA
MBMGA1UdJQQMMAoGCCsGAQUFBwMBMBkGA1UdEQQSMBCCDnNlcnZlci5leGFtcGxl
MA0GCSqGSIb3DQEBBAUAA4IBAQBqCPfIEZOVUiq2exiRFoxVOvq668Y55lJZ9+4j
E5Ncq9mdbuD7GIxJSKByf899yBJUG32ZIbmwnSHfBkPolc/LjQhUDxJtSBE8vFaA
8AZ1rsOcaWapPQ94gYIgncBS15t7RjTX1l04fY0NPqVsWmTji+ummA5e7iCj6l6t
CqRGhMeSZWa1mc+Plurmz7oWEqkUK5cfTrlDnXeQNOI8EK8lc636elqqdnw0amO4
yKJlaXRlm/I1nQdUQ0G5Bk2Tp/QGoJCtJ25XsoIbnCs0tIbpQllTdLsRQmOussAP
NvdwbKtAAolgMAxH9pl1Mc6OIo2e8405EWs1jvGEMgE0IFAY
-----END CERTIFICATE-----

13
test/certs/ee-key-768.pem Normal file
View file

@ -0,0 +1,13 @@
-----BEGIN PRIVATE KEY-----
MIIB5QIBADANBgkqhkiG9w0BAQEFAASCAc8wggHLAgEAAmEAwCvrPAynx+7VtpFz
4cWZW3/n3/nMwK4fxkWSB0kbVUhQaYiaQGWEfB4JpRz5rPt8NW5m2aVGT7mMjScu
8YyFa3IDdpBeQL1n8VQUH3FLySgQHC1bkkzwyzQM8JirCdl/AgMBAAECYQCzO0MW
qqcBrhvdPyPZerZhxJW7K/xv6PbxsYlVCjZYAC4ff6x+SzCZolpUiQXE9Hdyhlyk
alcqn2vT5TagWk64YUmIMP7BCT2Ps/IW0nQl07k27c2BNq3IzdRnBz5SbQECMQDg
9UxISqFOG6sLdZIKA88Q+M2HE/MdzwiJby/bSUXhn5aluZqjR60nGPqAb2S/r98C
MQDasGzUTXqEYOPsAL4irzKMMiMdqbj6dNHsmo1GIYKx8PuN193i/cNd5XDv78Gm
imECMQC10IvewbKtVl9f2540ye9JYE18pvsPVI0pxtt++DGqsTkoqGH7JasktmN/
+ogLBTECMBf9/xKTpXtcfeTod/OqMOt8nKmmcyrXIijJE/K7vnDzNUXshuVeXc6x
W2CXdzFkQQIweyLLA6etAJGsmCRwIgnfp1ubmVdfPou68byHSnzAf4/GxBriSd5b
EQcYwjE7SDI7
-----END PRIVATE KEY-----

View file

@ -10,6 +10,10 @@
#
DAYS=36525
if [ -z "$OPENSSL_SIGALG" ]; then
OPENSSL_SIGALG=sha256
fi
stderr_onerror() {
(
err=$("$@" >&3 2>&1) || {
@ -53,7 +57,7 @@ req() {
local errs
stderr_onerror \
openssl req -new -sha256 -key "${key}.pem" \
openssl req -new -"${OPENSSL_SIGALG}" -key "${key}.pem" \
-config <(printf "[req]\n%s\n%s\n[dn]\nCN=%s\n" \
"prompt = no" "distinguished_name = dn" "${cn}")
}
@ -63,7 +67,7 @@ req_nocn() {
key "$key"
stderr_onerror \
openssl req -new -sha256 -subj / -key "${key}.pem" \
openssl req -new -"${OPENSSL_SIGALG}" -subj / -key "${key}.pem" \
-config <(printf "[req]\n%s\n[dn]\nCN_default =\n" \
"distinguished_name = dn")
}
@ -73,7 +77,7 @@ cert() {
local exts=$1; shift
stderr_onerror \
openssl x509 -req -sha256 -out "${cert}.pem" \
openssl x509 -req -"${OPENSSL_SIGALG}" -out "${cert}.pem" \
-extfile <(printf "%s\n" "$exts") "$@"
}

View file

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBpzCCATGgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
IENBMCAXDTE2MDMyMDA2MjcyN1oYDzIxMTYwMzIxMDYyNzI3WjASMRAwDgYDVQQD
DAdSb290IENBMHwwDQYJKoZIhvcNAQEBBQADawAwaAJhALntqSk2YVnhNalAikA2
tuSOvHUKVSJlqjKmzlUPI+gQFyBWxtyQdwepI87tl8EW1in2IiOeN49W+OtVOlBi
Mxwqi/BcBltTbbSrlRpoSKOH6V7zIXvfsqjwWsDi37V1xQIDAQABo1AwTjAdBgNV
HQ4EFgQUWPMT967zC8rDNvZo4PDnYL7SAtUwHwYDVR0jBBgwFoAUWPMT967zC8rD
NvZo4PDnYL7SAtUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAANhAFDU7FyF
Ma6EG0OBS4IYws2US9t3IQwlI5noQwm9R3Nk/3AIUrdPG8ydRyV1N4GuRhRpprh0
sEbX3ZO9/E54DbPYfS5kqfZZtohUNy+Wmx8XY9OSv4SWUrrMSIRFXS63MA==
-----END CERTIFICATE-----

View file

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC8TCCAdmgAwIBAgIBATANBgkqhkiG9w0BAQQFADASMRAwDgYDVQQDDAdSb290
IENBMCAXDTE2MDMyMDA2MjcyN1oYDzIxMTYwMzIxMDYyNzI3WjASMRAwDgYDVQQD
DAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4eYA9Qa8
oEY4eQ8/HnEZE20C3yubdmv8rLAh7daRCEI7pWM17FJboKJKxdYAlAOXWj25ZyjS
feMhXKTtxjyNjoTRnVTDPdl0opZ2Z3H5xhpQd7P9eO5b4OOMiSPCmiLsPtQ3ngfN
wCtVERc6NEIcaQ06GLDtFZRexv2eh8Yc55QaksBfBcFzQ+UD3gmRySTO2I6Lfi7g
MUjRhipqVSZ66As2Tpex4KTJ2lxpSwOACFaDox+yKrjBTP7FsU3UwAGq7b7OJb3u
aa32B81uK6GJVPVo65gJ7clgZsszYkoDsGjWDqtfwTVVfv1G7rrr3Laio+2Ff3ff
tWgiQ35mJCOvxQIDAQABo1AwTjAdBgNVHQ4EFgQUjvUlrx6ba4Q9fICayVOcTXL3
o1IwHwYDVR0jBBgwFoAUjvUlrx6ba4Q9fICayVOcTXL3o1IwDAYDVR0TBAUwAwEB
/zANBgkqhkiG9w0BAQQFAAOCAQEAwSTZo97psLqiNmgvCC/Z51F3S9bFKPjGK4dc
Kqh8pMJsb8DnfGlPnsYXq/0oPcBThTRGZDqTeZa0ms8G+g4GS21TPF7lmvVJUJhz
GRLJxX7TYB8xriSJ15DwZgGmEGPfzmoIq27nwrO4TRAi0TCLdw01XZwiq2V7anl+
jrIpJPDuaT3oBqnGTMZ5IoaQq2TX8PS/ZW6icJiRmXLMp/HUycKpDUshiuARR5Mi
UOzX8IHwn76Zj6z1R8xW9j1WcEycFYevTMaRuS6hnYagiSaAytIQU8hgMR4AWodM
NFYv5t9rguJnimGUGMMBIYXnPNE2kaoq9qCVgjuC14gWU0kq6Q==
-----END CERTIFICATE-----

View file

@ -0,0 +1,13 @@
-----BEGIN PRIVATE KEY-----
MIIB5AIBADANBgkqhkiG9w0BAQEFAASCAc4wggHKAgEAAmEAue2pKTZhWeE1qUCK
QDa25I68dQpVImWqMqbOVQ8j6BAXIFbG3JB3B6kjzu2XwRbWKfYiI543j1b461U6
UGIzHCqL8FwGW1NttKuVGmhIo4fpXvMhe9+yqPBawOLftXXFAgMBAAECYH1FP4Bg
/16Lepg6v+tb8gY0lY1WFN5EGVRfRw3QUaT9kldboEjjnQ8wSswVEPYr56IHZ8mH
Or8LtJVrB3fjriq5vNOt7lRscuV7IcVtOyVWu5+MoJmO67Q2vRJXLWTdAQIxANtp
AiqObXo8vyT+EDcOEW104PfKNVh/4fhyrDwAk/yTcxkv4dcnuTykeLPvkXq4cQIx
ANjvQa+9LubMy3N1uXIbWWsiEBi4BdNK+xuppJ2puckaiQU42Mfmw/Nj4LMEJLfc
lQIwCYcv3uU8f9hvfI3D6oAj5Zrzwg737hXvnDhunlRwGMHWd7uKlStWcfm6fCXl
LW0hAjEAneK0egVEp3IR+PyLdcL194UZFgSJKNj/nYiAaMdokjcf1o8jJ4qKvw/I
MEIpvy9pAjAzaFHKRugCN01V2dgXYYGL8+zkcwG4ehDXH1XEs4v8r3WtHBPPKED6
AemfAQJLvh8=
-----END PRIVATE KEY-----

View file

@ -32,6 +32,14 @@ openssl x509 -in root-nonca.pem -trustout \
openssl x509 -in root-nonca.pem -trustout \
-addtrust anyExtendedKeyUsage -out nroot+anyEKU.pem
# Root CA security level variants:
# MD5 self-signature
OPENSSL_SIGALG=md5 \
./mkcert.sh genroot "Root CA" root-key root-cert-md5
# 768-bit key
OPENSSL_KEYBITS=768 \
./mkcert.sh genroot "Root CA" root-key-768 root-cert-768
# primary client-EKU root: croot-cert
# trust variants: +serverAuth -serverAuth +clientAuth +anyEKU -anyEKU
#
@ -97,6 +105,18 @@ openssl x509 -in ca-nonca.pem -trustout \
openssl x509 -in ca-nonca.pem -trustout \
-addtrust serverAuth -out nca+anyEKU.pem
# Intermediate CA security variants:
# MD5 issuer signature,
OPENSSL_SIGALG=md5 \
./mkcert.sh genca "CA" ca-key ca-cert-md5 root-key root-cert
openssl x509 -in ca-cert-md5.pem -trustout \
-addtrust anyExtendedKeyUsage -out ca-cert-md5-any.pem
# Issuer has 768-bit key
./mkcert.sh genca "CA" ca-key ca-cert-768i root-key-768 root-cert-768
# CA has 768-bit key
OPENSSL_KEYBITS=768 \
./mkcert.sh genca "CA" ca-key-768 ca-cert-768 root-key root-cert
# client intermediate ca: cca-cert
# trust variants: +serverAuth, -serverAuth, +clientAuth, -clientAuth
#
@ -152,3 +172,13 @@ openssl x509 -in ee-client.pem -trustout \
-addtrust clientAuth -out ee+clientAuth.pem
openssl x509 -in ee-client.pem -trustout \
-addreject clientAuth -out ee-clientAuth.pem
# Leaf cert security level variants
# MD5 issuer signature
OPENSSL_SIGALG=md5 \
./mkcert.sh genee server.example ee-key ee-cert-md5 ca-key ca-cert
# 768-bit issuer key
./mkcert.sh genee server.example ee-key ee-cert-768i ca-key-768 ca-cert-768
# 768-bit leaf key
OPENSSL_KEYBITS=768 \
./mkcert.sh genee server.example ee-key-768 ee-cert-768 ca-key ca-cert

View file

@ -10,7 +10,7 @@ setup("test_verify");
sub verify {
my ($cert, $purpose, $trusted, $untrusted, @opts) = @_;
my @args = qw(openssl verify -purpose);
my @args = qw(openssl verify -auth_level 1 -purpose);
my @path = qw(test certs);
push(@args, "$purpose", @opts);
for (@$trusted) { push(@args, "-trusted", srctop_file(@path, "$_.pem")) }
@ -19,7 +19,7 @@ sub verify {
run(app([@args]));
}
plan tests => 83;
plan tests => 101;
# Canonical success
ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]),
@ -214,3 +214,47 @@ ok(verify("ee-client", "sslclient", [qw(ee+clientAuth)], [], "-partial_chain"),
"accept direct match with client trust");
ok(!verify("ee-client", "sslclient", [qw(ee-clientAuth)], [], "-partial_chain"),
"reject direct match with client mistrust");
# Security level tests
ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"], "-auth_level", "2"),
"accept RSA 2048 chain at auth level 2");
ok(!verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"], "-auth_level", "3"),
"reject RSA 2048 root at auth level 3");
ok(verify("ee-cert", "sslserver", ["root-cert-768"], ["ca-cert-768i"], "-auth_level", "0"),
"accept RSA 768 root at auth level 0");
ok(!verify("ee-cert", "sslserver", ["root-cert-768"], ["ca-cert-768i"]),
"reject RSA 768 root at auth level 1");
ok(verify("ee-cert-768i", "sslserver", ["root-cert"], ["ca-cert-768"], "-auth_level", "0"),
"accept RSA 768 intermediate at auth level 0");
ok(!verify("ee-cert-768i", "sslserver", ["root-cert"], ["ca-cert-768"]),
"reject RSA 768 intermediate at auth level 1");
ok(verify("ee-cert-768", "sslserver", ["root-cert"], ["ca-cert"], "-auth_level", "0"),
"accept RSA 768 leaf at auth level 0");
ok(!verify("ee-cert-768", "sslserver", ["root-cert"], ["ca-cert"]),
"reject RSA 768 leaf at auth level 1");
#
ok(verify("ee-cert", "sslserver", ["root-cert-md5"], ["ca-cert"], "-auth_level", "2"),
"accept md5 self-signed TA at auth level 2");
ok(verify("ee-cert", "sslserver", ["ca-cert-md5-any"], [], "-auth_level", "2"),
"accept md5 intermediate TA at auth level 2");
ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert-md5"], "-auth_level", "0"),
"accept md5 intermediate at auth level 0");
ok(!verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert-md5"]),
"reject md5 intermediate at auth level 1");
ok(verify("ee-cert-md5", "sslserver", ["root-cert"], ["ca-cert"], "-auth_level", "0"),
"accept md5 leaf at auth level 0");
ok(!verify("ee-cert-md5", "sslserver", ["root-cert"], ["ca-cert"]),
"reject md5 leaf at auth level 1");
# Depth tests, note the depth limit bounds the number of CA certificates
# between the trust-anchor and the leaf, so, for example, with a root->ca->leaf
# chain, depth = 1 is sufficient, but depth == 0 is not.
#
ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"], "-verify_depth", "2"),
"accept chain with verify_depth 2");
ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"], "-verify_depth", "1"),
"accept chain with verify_depth 1");
ok(!verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"], "-verify_depth", "0"),
"accept chain with verify_depth 0");
ok(verify("ee-cert", "sslserver", ["ca-cert-md5-any"], [], "-verify_depth", "0"),
"accept md5 intermediate TA with verify_depth 0");