get_issuer can never return -1
The -1 cases were all removed in
https://boringssl-review.googlesource.com/c/boringssl/+/8303, so we can
simplify things. This removes almost all cases where X509_verify_cert
could have returned -1.
As part of this, align the get_issuer and find_issuer calling
conventions. Also rename it to get_trusted_issuer to make it clearer
that this is only searches for trusted certs.
Change-Id: I586d037106bb74887738a342d222948db8e49d53
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/65088
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index 1c10891..539d6fa 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -503,12 +503,8 @@
return NULL;
}
-// Try to get issuer certificate from store. Due to limitations of the API
-// this can only retrieve a single certificate matching a given subject name.
-// However it will fill the cache with all matching certificates, so we can
-// examine the cache for all matches. Return values are: 1 lookup
-// successful. 0 certificate not found. -1 some other error.
-int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) {
+int X509_STORE_CTX_get1_issuer(X509 **out_issuer, X509_STORE_CTX *ctx,
+ X509 *x) {
X509_NAME *xn;
X509_OBJECT obj, *pobj;
int idx, ret;
@@ -519,7 +515,7 @@
}
// If certificate matches all OK
if (x509_check_issued_with_callback(ctx, x, obj.data.x509)) {
- *issuer = obj.data.x509;
+ *out_issuer = obj.data.x509;
return 1;
}
X509_OBJECT_free_contents(&obj);
@@ -542,7 +538,7 @@
break;
}
if (x509_check_issued_with_callback(ctx, x, pobj->data.x509)) {
- *issuer = pobj->data.x509;
+ *out_issuer = pobj->data.x509;
X509_OBJECT_up_ref_count(pobj);
ret = 1;
break;
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index e7345a2..7e9aca4 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -110,7 +110,7 @@
static int check_cert(X509_STORE_CTX *ctx);
static int check_policy(X509_STORE_CTX *ctx);
-static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
+static X509 *get_trusted_issuer(X509_STORE_CTX *ctx, X509 *x);
static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, X509_CRL *crl,
X509 *x);
static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x);
@@ -162,7 +162,7 @@
}
int X509_verify_cert(X509_STORE_CTX *ctx) {
- X509 *xtmp, *xtmp2, *chain_ss = NULL;
+ X509 *chain_ss = NULL;
int bad_chain = 0;
X509_VERIFY_PARAM *param = ctx->param;
int i, ok = 0;
@@ -234,32 +234,27 @@
}
// If asked see if we can find issuer in trusted store first
if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) {
- ok = get_issuer(&xtmp, ctx, x);
- if (ok < 0) {
- ctx->error = X509_V_ERR_STORE_LOOKUP;
- goto end;
- }
- // If successful for now free up cert so it will be picked up
- // again later.
- if (ok > 0) {
- X509_free(xtmp);
+ X509 *issuer = get_trusted_issuer(ctx, x);
+ if (issuer != NULL) {
+ // Free the certificate. It will be picked up again later.
+ X509_free(issuer);
break;
}
}
// If we were passed a cert chain, use it first
if (sktmp != NULL) {
- xtmp = find_issuer(ctx, sktmp, x);
- if (xtmp != NULL) {
- if (!sk_X509_push(ctx->chain, xtmp)) {
+ X509 *issuer = find_issuer(ctx, sktmp, x);
+ if (issuer != NULL) {
+ if (!sk_X509_push(ctx->chain, issuer)) {
ctx->error = X509_V_ERR_OUT_OF_MEM;
ok = 0;
goto end;
}
- X509_up_ref(xtmp);
- (void)sk_X509_delete_ptr(sktmp, xtmp);
+ X509_up_ref(issuer);
+ (void)sk_X509_delete_ptr(sktmp, issuer);
ctx->last_untrusted++;
- x = xtmp;
+ x = issuer;
num++;
// reparse the full chain for the next one
continue;
@@ -291,14 +286,12 @@
// We have a single self signed certificate: see if we can
// find it in the store. We must have an exact match to avoid
// possible impersonation.
- ok = get_issuer(&xtmp, ctx, x);
- if ((ok <= 0) || X509_cmp(x, xtmp)) {
+ X509 *issuer = get_trusted_issuer(ctx, x);
+ if (issuer == NULL || X509_cmp(x, issuer) != 0) {
+ X509_free(issuer);
ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
ctx->current_cert = x;
ctx->error_depth = i - 1;
- if (ok == 1) {
- X509_free(xtmp);
- }
bad_chain = 1;
ok = ctx->verify_cb(0, ctx);
if (!ok) {
@@ -308,7 +301,7 @@
// We have a match: replace certificate with store
// version so we get any trust settings.
X509_free(x);
- x = xtmp;
+ x = issuer;
(void)sk_X509_set(ctx->chain, i - 1, x);
ctx->last_untrusted = 0;
}
@@ -336,18 +329,13 @@
if (is_self_signed) {
break;
}
- ok = get_issuer(&xtmp, ctx, x);
-
- if (ok < 0) {
- ctx->error = X509_V_ERR_STORE_LOOKUP;
- goto end;
- }
- if (ok == 0) {
+ X509 *issuer = get_trusted_issuer(ctx, x);
+ if (issuer == NULL) {
break;
}
- x = xtmp;
+ x = issuer;
if (!sk_X509_push(ctx->chain, x)) {
- X509_free(xtmp);
+ X509_free(issuer);
ctx->error = X509_V_ERR_OUT_OF_MEM;
ok = 0;
goto end;
@@ -372,21 +360,17 @@
!(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) &&
!(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) {
while (j-- > 1) {
- xtmp2 = sk_X509_value(ctx->chain, j - 1);
- ok = get_issuer(&xtmp, ctx, xtmp2);
- if (ok < 0) {
- goto end;
- }
+ X509 *issuer =
+ get_trusted_issuer(ctx, sk_X509_value(ctx->chain, j - 1));
// Check if we found an alternate chain
- if (ok > 0) {
+ if (issuer != NULL) {
// Free up the found cert we'll add it again later
- X509_free(xtmp);
+ X509_free(issuer);
// Dump all the certs above this point - we've found an
// alternate chain
while (num > j) {
- xtmp = sk_X509_pop(ctx->chain);
- X509_free(xtmp);
+ X509_free(sk_X509_pop(ctx->chain));
num--;
}
ctx->last_untrusted = (int)sk_X509_num(ctx->chain);
@@ -511,18 +495,21 @@
return ctx->verify_cb(0, ctx);
}
-static int get_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) {
+static X509 *get_trusted_issuer(X509_STORE_CTX *ctx, X509 *x) {
+ X509 *issuer;
if (ctx->trusted_stack != NULL) {
// Ignore the store and use the configured stack instead.
- *issuer = find_issuer(ctx, ctx->trusted_stack, x);
- if (*issuer) {
- X509_up_ref(*issuer);
- return 1;
+ issuer = find_issuer(ctx, ctx->trusted_stack, x);
+ if (issuer != NULL) {
+ X509_up_ref(issuer);
}
- return 0;
+ return issuer;
}
- return X509_STORE_CTX_get1_issuer(issuer, ctx, x);
+ if (!X509_STORE_CTX_get1_issuer(&issuer, ctx, x)) {
+ return NULL;
+ }
+ return issuer;
}
// Check a certificate chains extensions for consistency with the supplied
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index b0dc725..893bf42 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -3071,6 +3071,19 @@
OPENSSL_EXPORT int X509_check_ip_asc(const X509 *x509, const char *ipasc,
unsigned int flags);
+// X509_STORE_CTX_get1_issuer looks up a candidate trusted issuer for |x509| out
+// of |ctx|'s |X509_STORE|, based on the criteria in |X509_check_issued|. If one
+// was found, it returns one and sets |*out_issuer| to the issuer. The caller
+// must release |*out_issuer| with |X509_free| when done. If none was found, it
+// returns zero and leaves |*out_issuer| unchanged.
+//
+// This function only searches for trusted issuers. It does not consider
+// untrusted intermediates passed in to |X509_STORE_CTX_init|.
+//
+// TODO(crbug.com/boringssl/407): |x509| should be const.
+OPENSSL_EXPORT int X509_STORE_CTX_get1_issuer(X509 **out_issuer,
+ X509_STORE_CTX *ctx, X509 *x509);
+
// X.509 information.
//
@@ -3787,9 +3800,6 @@
// on error.
OPENSSL_EXPORT X509_STORE_CTX *X509_STORE_CTX_new(void);
-OPENSSL_EXPORT int X509_STORE_CTX_get1_issuer(X509 **issuer,
- X509_STORE_CTX *ctx, X509 *x);
-
// X509_STORE_CTX_free releases memory associated with |ctx|.
OPENSSL_EXPORT void X509_STORE_CTX_free(X509_STORE_CTX *ctx);