提交 7e365d51 编写于 作者: D Dr. David von Oheimb 提交者: Dr. David von Oheimb

x509_vfy.c: Sort out return values 0 vs. -1 (failure/internal error)

Also simplify first part of verify_chain()
Reviewed-by: NPaul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14095)
上级 364246a9
......@@ -106,19 +106,23 @@ int X509_self_signed(X509 *cert, int verify_signature)
return X509_verify(cert, pkey);
}
/* Given a certificate try and find an exact match in the store */
static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x)
/*
* Given a certificate, try and find an exact match in the store.
* Returns 1 on success, 0 on not found, -1 on internal error.
*/
static int lookup_cert_match(X509 **result, X509_STORE_CTX *ctx, X509 *x)
{
STACK_OF(X509) *certs;
X509 *xtmp = NULL;
int i;
int i, ret;
*result = NULL;
/* Lookup all certs with matching subject name */
ERR_set_mark();
certs = ctx->lookup_certs(ctx, X509_get_subject_name(x));
ERR_pop_to_mark();
if (certs == NULL)
return NULL;
return -1;
/* Look for exact match */
for (i = 0; i < sk_X509_num(certs); i++) {
xtmp = sk_X509_value(certs, i);
......@@ -126,10 +130,15 @@ static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x)
break;
xtmp = NULL;
}
if (xtmp != NULL && !X509_up_ref(xtmp))
xtmp = NULL;
ret = xtmp != NULL;
if (ret) {
if (!X509_up_ref(xtmp))
ret = -1;
else
*result = xtmp;
}
sk_X509_pop_free(certs, X509_free);
return xtmp;
return ret;
}
/*-
......@@ -194,6 +203,7 @@ static int check_auth_level(X509_STORE_CTX *ctx)
return 1;
}
/* Returns -1 on internal error */
static int verify_chain(X509_STORE_CTX *ctx)
{
int err;
......@@ -213,18 +223,18 @@ static int verify_chain(X509_STORE_CTX *ctx)
/* Verify chain signatures and expiration times */
ok = ctx->verify != NULL ? ctx->verify(ctx) : internal_verify(ctx);
if (!ok)
return 0;
if (ok <= 0)
return ok;
if ((ok = check_name_constraints(ctx)) == 0)
return 0;
if ((ok = check_name_constraints(ctx)) <= 0)
return ok;
#ifndef OPENSSL_NO_RFC3779
/* RFC 3779 path validation, now that CRL check has been done */
if ((ok = X509v3_asid_validate_path(ctx)) == 0)
return 0;
if ((ok = X509v3_addr_validate_path(ctx)) == 0)
return 0;
if ((ok = X509v3_asid_validate_path(ctx)) <= 0)
return ok;
if ((ok = X509v3_addr_validate_path(ctx)) <= 0)
return ok;
#endif
/* If we get this far evaluate policies */
......@@ -332,28 +342,32 @@ static int check_issued(ossl_unused X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
return x509_likely_issued(issuer, x) == X509_V_OK;
}
/* Alternative lookup method: look from a STACK stored in other_ctx */
/*
* Alternative lookup method: look from a STACK stored in other_ctx.
* Returns -1 on internal error.
*/
static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
*issuer = find_issuer(ctx, ctx->other_ctx, x);
if (*issuer != NULL && X509_up_ref(*issuer))
return 1;
*issuer = NULL;
if (*issuer != NULL)
return X509_up_ref(*issuer) ? 1 : -1;
return 0;
}
/* Returns NULL on internal error (such as out of memory) */
static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx,
const X509_NAME *nm)
{
STACK_OF(X509) *sk = NULL;
STACK_OF(X509) *sk = sk_X509_new_null();
X509 *x;
int i;
if (sk == NULL)
return NULL;
for (i = 0; i < sk_X509_num(ctx->other_ctx); i++) {
x = sk_X509_value(ctx->other_ctx, i);
if (X509_NAME_cmp(nm, X509_get_subject_name(x)) == 0) {
if (!X509_add_cert_new(&sk, x, X509_ADD_FLAG_UP_REF)) {
if (!X509_add_cert(sk, x, X509_ADD_FLAG_UP_REF)) {
sk_X509_pop_free(sk, X509_free);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return NULL;
......@@ -366,6 +380,7 @@ static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx,
/*
* Check EE or CA certificate purpose. For trusted certificates explicit local
* auxiliary trust can be used to override EKU-restrictions.
* Sadly, returns 0 also on internal error.
*/
static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth,
int must_be_ca)
......@@ -414,7 +429,10 @@ static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth,
return verify_cb_cert(ctx, x, depth, X509_V_ERR_INVALID_PURPOSE);
}
/* Check extensions of a cert chain for consistency with the supplied purpose */
/*
* Check extensions of a cert chain for consistency with the supplied purpose.
* Sadly, returns 0 also on internal error.
*/
static int check_chain(X509_STORE_CTX *ctx)
{
int i, must_be_ca, plen = 0;
......@@ -596,7 +614,7 @@ static int has_san_id(X509 *x, int gtype)
GENERAL_NAMES *gs = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
if (gs == NULL)
return 0;
return -1;
for (i = 0; i < sk_GENERAL_NAME_num(gs); i++) {
GENERAL_NAME *g = sk_GENERAL_NAME_value(gs, i);
......@@ -610,6 +628,7 @@ static int has_san_id(X509 *x, int gtype)
return ret;
}
/* Returns -1 on internal error */
static int check_name_constraints(X509_STORE_CTX *ctx)
{
int i;
......@@ -672,7 +691,7 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
if (tmpsubject == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
return -1;
}
tmpentry = X509_NAME_delete_entry(tmpsubject, last_loc);
......@@ -701,6 +720,7 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
if (nc) {
int rv = NAME_CONSTRAINTS_check(x, nc);
int ret = 1;
/* If EE certificate check commonName too */
if (rv == X509_V_OK && i == 0
......@@ -708,14 +728,16 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
& X509_CHECK_FLAG_NEVER_CHECK_SUBJECT) == 0
&& ((ctx->param->hostflags
& X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT) != 0
|| !has_san_id(x, GEN_DNS)))
|| (ret = has_san_id(x, GEN_DNS)) == 0))
rv = NAME_CONSTRAINTS_check_CN(x, nc);
if (ret < 0)
return ret;
switch (rv) {
case X509_V_OK:
break;
case X509_V_ERR_OUT_OF_MEM:
return 0;
return -1;
default:
CB_FAIL_IF(1, ctx, x, i, rv);
break;
......@@ -770,9 +792,10 @@ static int check_id(X509_STORE_CTX *ctx)
return 1;
}
/* Returns -1 on internal error */
static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
{
int i;
int i, res;
X509 *x = NULL;
X509 *mx;
SSL_DANE *dane = ctx->dane;
......@@ -784,11 +807,9 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
* match, we're done, otherwise we'll merely record the match depth.
*/
if (DANETLS_HAS_TA(dane) && num_untrusted > 0 && num_untrusted < num) {
switch (trust = check_dane_issuer(ctx, num_untrusted)) {
case X509_TRUST_TRUSTED:
case X509_TRUST_REJECTED:
trust = check_dane_issuer(ctx, num_untrusted);
if (trust != X509_TRUST_UNTRUSTED)
return trust;
}
}
/*
......@@ -825,7 +846,9 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
*/
i = 0;
x = sk_X509_value(ctx->chain, i);
mx = lookup_cert_match(ctx, x);
res = lookup_cert_match(&mx, ctx, x);
if (res < 0)
return res;
if (mx == NULL)
return X509_TRUST_UNTRUSTED;
......@@ -867,6 +890,7 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted)
return X509_TRUST_UNTRUSTED;
}
/* Sadly, returns 0 also on internal error. */
static int check_revocation(X509_STORE_CTX *ctx)
{
int i = 0, last = 0, ok = 0;
......@@ -890,6 +914,7 @@ static int check_revocation(X509_STORE_CTX *ctx)
return 1;
}
/* Sadly, returns 0 also on internal error. */
static int check_cert(X509_STORE_CTX *ctx)
{
X509_CRL *crl = NULL, *dcrl = NULL;
......@@ -1604,21 +1629,15 @@ static int check_policy(X509_STORE_CTX *ctx)
* was verified via a bare public key, and pop it off right after the
* X509_policy_check() call.
*/
if (ctx->bare_ta_signed && !sk_X509_push(ctx->chain, NULL)) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
if (ctx->bare_ta_signed && !sk_X509_push(ctx->chain, NULL))
goto memerr;
ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
ctx->param->policies, ctx->param->flags);
if (ctx->bare_ta_signed)
(void)sk_X509_pop(ctx->chain);
if (ret == X509_PCY_TREE_INTERNAL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
if (ret == X509_PCY_TREE_INTERNAL)
goto memerr;
/* Invalid or inconsistent extensions */
if (ret == X509_PCY_TREE_INVALID) {
int i;
......@@ -1655,6 +1674,11 @@ static int check_policy(X509_STORE_CTX *ctx)
}
return 1;
memerr:
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return -1;
}
/*-
......@@ -1690,7 +1714,10 @@ int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth)
return 1;
}
/* verify the issuer signatures and cert times of ctx->chain */
/*
* Verify the issuer signatures and cert times of ctx->chain.
* Sadly, returns 0 also on internal error.
*/
static int internal_verify(X509_STORE_CTX *ctx)
{
int n = sk_X509_num(ctx->chain) - 1;
......@@ -1964,7 +1991,10 @@ int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
return 1;
}
/* Make a delta CRL as the difference between two full CRLs */
/*
* Make a delta CRL as the difference between two full CRLs.
* Sadly, returns NULL also on internal error.
*/
X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
EVP_PKEY *skey, const EVP_MD *md, unsigned int flags)
{
......@@ -2628,6 +2658,7 @@ static unsigned char *dane_i2d(X509 *cert, uint8_t selector,
#define DANETLS_NONE 256 /* impossible uint8_t */
/* Returns -1 on internal error */
static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
{
SSL_DANE *dane = ctx->dane;
......@@ -2770,6 +2801,7 @@ static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth)
return matched;
}
/* Returns -1 on internal error */
static int check_dane_issuer(X509_STORE_CTX *ctx, int depth)
{
SSL_DANE *dane = ctx->dane;
......@@ -2786,7 +2818,7 @@ static int check_dane_issuer(X509_STORE_CTX *ctx, int depth)
*/
cert = sk_X509_value(ctx->chain, depth);
if (cert != NULL && (matched = dane_match(ctx, cert, depth)) < 0)
return X509_TRUST_REJECTED;
return matched;
if (matched > 0) {
ctx->num_untrusted = depth - 1;
return X509_TRUST_TRUSTED;
......@@ -2850,6 +2882,7 @@ static int check_leaf_suiteb(X509_STORE_CTX *ctx, X509 *cert)
return 1;
}
/* Returns -1 on internal error */
static int dane_verify(X509_STORE_CTX *ctx)
{
X509 *cert = ctx->cert;
......@@ -2874,8 +2907,8 @@ static int dane_verify(X509_STORE_CTX *ctx)
matched = dane_match(ctx, ctx->cert, 0);
done = matched != 0 || (!DANETLS_HAS_TA(dane) && dane->mdpth < 0);
if (done)
X509_get_pubkey_parameters(NULL, ctx->chain);
if (done && !X509_get_pubkey_parameters(NULL, ctx->chain))
return -1;
if (matched > 0) {
/* Callback invoked as needed */
......@@ -2912,7 +2945,10 @@ static int dane_verify(X509_STORE_CTX *ctx)
return verify_chain(ctx);
}
/* Get issuer, without duplicate suppression */
/*
* Get issuer, without duplicate suppression
* Returns -1 on internal error.
*/
static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert)
{
STACK_OF(X509) *saved_chain = ctx->chain;
......@@ -2925,6 +2961,7 @@ static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert)
return ok;
}
/* Returns -1 on internal error */
static int build_chain(X509_STORE_CTX *ctx)
{
SSL_DANE *dane = ctx->dane;
......@@ -2971,11 +3008,8 @@ static int build_chain(X509_STORE_CTX *ctx)
* typically the content of the peer's certificate message) so can make
* multiple passes over it, while free to remove elements as we go.
*/
if ((sk_untrusted = sk_X509_dup(ctx->untrusted)) == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
if ((sk_untrusted = sk_X509_dup(ctx->untrusted)) == NULL)
goto memerr;
/*
* If we got any "DANE-TA(2) Cert(0) Full(0)" trust anchors from DNS, add
......@@ -2988,15 +3022,11 @@ static int build_chain(X509_STORE_CTX *ctx)
* this to change. ]
*/
if (DANETLS_ENABLED(dane) && dane->certs != NULL) {
if (sk_untrusted == NULL && (sk_untrusted = sk_X509_new_null()) == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
if (sk_untrusted == NULL && (sk_untrusted = sk_X509_new_null()) == NULL)
goto memerr;
if (!X509_add_certs(sk_untrusted, dane->certs, X509_ADD_FLAG_DEFAULT)) {
sk_X509_free(sk_untrusted);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
goto memerr;
}
}
......@@ -3056,7 +3086,7 @@ static int build_chain(X509_STORE_CTX *ctx)
ok = num > depth ? 0 : get_issuer(&issuer, ctx, curr);
if (ok < 0) {
trust = X509_TRUST_REJECTED;
trust = -1;
ctx->error = X509_V_ERR_STORE_LOOKUP;
break;
}
......@@ -3078,11 +3108,8 @@ static int build_chain(X509_STORE_CTX *ctx)
*/
if ((search & S_DOALTERNATE) != 0) {
if (!ossl_assert(num > i && i > 0 && !self_signed)) {
ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
X509_free(issuer);
trust = X509_TRUST_REJECTED;
ctx->error = X509_V_ERR_UNSPECIFIED;
break;
goto int_err;
}
search &= ~S_DOALTERNATE;
for (; num > i; --num)
......@@ -3110,10 +3137,7 @@ static int build_chain(X509_STORE_CTX *ctx)
goto int_err;
if (!sk_X509_push(ctx->chain, curr)) {
X509_free(issuer);
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
trust = X509_TRUST_REJECTED;
ctx->error = X509_V_ERR_OUT_OF_MEM;
break;
goto memerr;
}
} else if (num == ctx->num_untrusted) {
/*
......@@ -3153,8 +3177,7 @@ static int build_chain(X509_STORE_CTX *ctx)
goto int_err;
search &= ~S_DOUNTRUSTED;
trust = check_trust(ctx, num);
if (trust == X509_TRUST_TRUSTED
|| trust == X509_TRUST_REJECTED)
if (trust != X509_TRUST_UNTRUSTED)
break;
if (!self_signed)
continue;
......@@ -3223,6 +3246,9 @@ static int build_chain(X509_STORE_CTX *ctx)
}
sk_X509_free(sk_untrusted);
if (trust < 0) /* internal error */
return trust;
/*
* Last chance to make a trusted chain, either bare DANE-TA public-key
* signers, or else direct leaf PKIX trust.
......@@ -3264,7 +3290,12 @@ static int build_chain(X509_STORE_CTX *ctx)
sk_X509_free(sk_untrusted);
ERR_raise(ERR_LIB_X509, ERR_R_INTERNAL_ERROR);
ctx->error = X509_V_ERR_UNSPECIFIED;
return 0;
return -1;
memerr:
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
ctx->error = X509_V_ERR_OUT_OF_MEM;
return -1;
}
static const int minbits_table[] = { 80, 112, 128, 192, 256 };
......
......@@ -33,10 +33,11 @@ SSL/TLS code.
A negative return value from X509_verify_cert() can occur if it is invoked
incorrectly, such as with no certificate set in I<ctx>, or when it is called
twice in succession without reinitialising I<ctx> for the second call.
A negative return value can also happen due to internal resource problems or if
a retry operation is requested during internal lookups (which never happens
with standard lookup methods).
Applications must check for <= 0 return value on error.
A negative return value can also happen due to internal resource problems
or because an internal inconsistency has been detected
or if a retry operation is requested during internal lookups
(which never happens with standard lookup methods).
Applications must interpret any return value <= 0 as an error.
The X509_STORE_CTX_verify() behaves like X509_verify_cert() except that its
target certificate is the first element of the list of untrusted certificates
......@@ -48,6 +49,11 @@ Both functions return 1 if a complete chain can be built and validated,
otherwise they return 0, and in exceptional circumstances (such as malloc
failure and internal errors) they can also return a negative code.
If a complete chain can be built and validated both functions return 1.
If the certificate must be rejected on the basis of the data available
or any required certificate status data is not available they return 0.
If no definite answer possible they usually return a negative code.
On error or failure additional error information can be obtained by
examining I<ctx> using, for example, L<X509_STORE_CTX_get_error(3)>. Even if
verification indicated success, the stored error code may be different from
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册