summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/apps.h8
-rw-r--r--apps/opt.c5
-rw-r--r--crypto/x509/x509_lcl.h1
-rw-r--r--crypto/x509/x509_txt.c6
-rw-r--r--crypto/x509/x509_vfy.c160
-rw-r--r--crypto/x509/x509_vpm.c17
-rw-r--r--doc/apps/cms.pod5
-rw-r--r--doc/apps/ocsp.pod7
-rw-r--r--doc/apps/s_client.pod5
-rw-r--r--doc/apps/s_server.pod5
-rw-r--r--doc/apps/smime.pod5
-rw-r--r--doc/apps/ts.pod21
-rw-r--r--doc/apps/verify.pod24
-rw-r--r--doc/crypto/X509_VERIFY_PARAM_set_flags.pod42
-rw-r--r--include/openssl/x509_vfy.h7
-rw-r--r--ssl/ssl_cert.c25
-rw-r--r--test/certs/ca-cert-768.pem15
-rw-r--r--test/certs/ca-cert-768i.pem15
-rw-r--r--test/certs/ca-cert-md5-any.pem18
-rw-r--r--test/certs/ca-cert-md5.pem18
-rw-r--r--test/certs/ca-key-768.pem13
-rw-r--r--test/certs/ee-cert-768.pem16
-rw-r--r--test/certs/ee-cert-768i.pem16
-rw-r--r--test/certs/ee-cert-md5.pem19
-rw-r--r--test/certs/ee-key-768.pem13
-rwxr-xr-xtest/certs/mkcert.sh10
-rw-r--r--test/certs/root-cert-768.pem11
-rw-r--r--test/certs/root-cert-md5.pem18
-rw-r--r--test/certs/root-key-768.pem13
-rwxr-xr-xtest/certs/setup.sh30
-rw-r--r--test/recipes/25-test_verify.t48
31 files changed, 543 insertions, 73 deletions
diff --git a/apps/apps.h b/apps/apps.h
index 434ca54b7d..a310dd2b78 100644
--- a/apps/apps.h
+++ b/apps/apps.h
@@ -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: \
diff --git a/apps/opt.c b/apps/opt.c
index af994bb743..462894a938 100644
--- a/apps/opt.c
+++ b/apps/opt.c
@@ -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;
diff --git a/crypto/x509/x509_lcl.h b/crypto/x509/x509_lcl.h
index 0726201e8f..603c17737f 100644
--- a/crypto/x509/x509_lcl.h
+++ b/crypto/x509/x509_lcl.h
@@ -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 */
diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c
index f7f27e97ef..8a9a7f0444 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -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 */
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 92f1c5c447..10fbeeff6d 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -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,23 +2958,21 @@ 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.
*/
switch (trust = check_dane_issuer(ctx, ctx->num_untrusted - 1)) {
@@ -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];
+}
diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c
index 41b0fde4a5..4a0bed021c 100644
--- a/crypto/x509/x509_vpm.c
+++ b/crypto/x509/x509_vpm.c
@@ -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}
};
diff --git a/doc/apps/cms.pod b/doc/apps/cms.pod
index 36e6b3ca3a..42c351489c 100644
--- a/doc/apps/cms.pod
+++ b/doc/apps/cms.pod
@@ -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.
diff --git a/doc/apps/ocsp.pod b/doc/apps/ocsp.pod
index be195bcb30..c796fd5966 100644
--- a/doc/apps/ocsp.pod
+++ b/doc/apps/ocsp.pod
@@ -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>
diff --git a/doc/apps/s_client.pod b/doc/apps/s_client.pod
index 1873293ea8..881fbcfefe 100644
--- a/doc/apps/s_client.pod
+++ b/doc/apps/s_client.pod
@@ -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.
diff --git a/doc/apps/s_server.pod b/doc/apps/s_server.pod
index 25e544468a..08554f4530 100644
--- a/doc/apps/s_server.pod
+++ b/doc/apps/s_server.pod
@@ -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.
diff --git a/doc/apps/smime.pod b/doc/apps/smime.pod
index 418d8faa2d..e6323ad0b0 100644
--- a/doc/apps/smime.pod
+++ b/doc/apps/smime.pod
@@ -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.
diff --git a/doc/apps/ts.pod b/doc/apps/ts.pod
index 93ea9e059a..e64e5fcf34 100644
--- a/doc/apps/ts.pod
+++ b/doc/apps/ts.pod
@@ -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
diff --git a/doc/apps/verify.pod b/doc/apps/verify.pod
index ecde35fe8a..96d6be4a4d 100644
--- a/doc/apps/verify.pod
+++ b/doc/apps/verify.pod
@@ -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>
diff --git a/doc/crypto/X509_VERIFY_PARAM_set_flags.pod b/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
index 6fb33edd91..04f521506f 100644
--- a/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
+++ b/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
@@ -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);