int ossl_x509_likely_issued(X509 *issuer, X509 *subject);
int ossl_x509_signing_allowed(const X509 *issuer, const X509 *subject);
+int ossl_x509_store_ctx_get_by_subject(const X509_STORE_CTX *ctx, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret);
* 0 if not found or X509_LOOKUP_by_subject_ex() returns an error,
* -1 on failure
*/
-static int ossl_x509_store_ctx_get_by_subject(const X509_STORE_CTX *ctx,
- X509_LOOKUP_TYPE type,
- const X509_NAME *name,
- X509_OBJECT *ret)
+int ossl_x509_store_ctx_get_by_subject(const X509_STORE_CTX *ctx, X509_LOOKUP_TYPE type,
+ const X509_NAME *name, X509_OBJECT *ret)
{
X509_STORE *store = ctx->store;
X509_LOOKUP *lu;
/*-
* Try to get issuer cert from |ctx->store| accepted by |ctx->check_issued|.
+ * Prefer the first match with suitable validity period or latest expiration.
*
* Return values are:
* 1 lookup successful.
*/
int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
- STACK_OF(X509) *certs = X509_STORE_CTX_get1_certs(ctx, X509_get_issuer_name(x));
- int ret = 0;
+ const X509_NAME *xn = X509_get_issuer_name(x);
+ X509_OBJECT *obj = X509_OBJECT_new();
+ STACK_OF(X509) *certs;
+ int ret;
- if (certs == NULL)
+ *issuer = NULL;
+ if (obj == NULL)
return -1;
+ ret = ossl_x509_store_ctx_get_by_subject(ctx, X509_LU_X509, xn, obj);
+ if (ret != 1)
+ goto end;
+
+ /* quick happy path: certificate matches and is currently valid */
+ if (ctx->check_issued(ctx, x, obj->data.x509)) {
+ if (ossl_x509_check_cert_time(ctx, obj->data.x509, -1)) {
+ *issuer = obj->data.x509;
+ /* |*issuer| has taken over the cert reference from |obj| */
+ obj->type = X509_LU_NONE;
+ goto end;
+ }
+ }
+
+ ret = -1;
+ if ((certs = X509_STORE_CTX_get1_certs(ctx, xn)) == NULL)
+ goto end;
*issuer = get0_best_issuer_sk(ctx, 0, 0 /* allow duplicates */, certs, x);
+ ret = 0;
if (*issuer != NULL)
ret = X509_up_ref(*issuer) ? 1 : -1;
OSSL_STACK_OF_X509_free(certs);
+ end:
+ X509_OBJECT_free(obj);
return ret;
}