Improve the implementation of X509_STORE_CTX_get1_issuer()

It is possible for the stack of X509_OBJECTs held in an X509_STORE_CTX to
have a custom compare function associated with it. Normally (by default)
this uses X509_NAME_cmp(). The X509_STORE_CTX_get1_issuer() function
assumed that it would always be X509_NAME_cmp().

By implementing OPENSSL_sk_find_all() function we can avoid explicitly
using X509_NAME_cmp() in X509_STORE_CTX_get1_issuer().

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14728)
This commit is contained in:
Tomas Mraz
2021-04-28 11:19:34 +02:00
parent e1491a2f15
commit 5fd7eb5c8a
7 changed files with 55 additions and 29 deletions
+30 -4
View File
@@ -297,7 +297,7 @@ void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc)
}
static int internal_find(OPENSSL_STACK *st, const void *data,
int ret_val_options)
int ret_val_options, int *pnum)
{
const void *r;
int i;
@@ -307,8 +307,13 @@ static int internal_find(OPENSSL_STACK *st, const void *data,
if (st->comp == NULL) {
for (i = 0; i < st->num; i++)
if (st->data[i] == data)
if (st->data[i] == data) {
if (pnum != NULL)
*pnum = 1;
return i;
}
if (pnum != NULL)
*pnum = 0;
return -1;
}
@@ -319,20 +324,41 @@ static int internal_find(OPENSSL_STACK *st, const void *data,
}
if (data == NULL)
return -1;
if (pnum != NULL)
ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH;
r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp,
ret_val_options);
if (pnum != NULL) {
*pnum = 0;
if (r != NULL) {
const void **p = (const void **)r;
while (p < st->data + st->num) {
if (st->comp(&data, p) != 0)
break;
++*pnum;
++p;
}
}
}
return r == NULL ? -1 : (int)((const void **)r - st->data);
}
int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data)
{
return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH);
return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, NULL);
}
int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data)
{
return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH);
return internal_find(st, data, OSSL_BSEARCH_VALUE_ON_NOMATCH, NULL);
}
int OPENSSL_sk_find_all(OPENSSL_STACK *st, const void *data, int *pnum)
{
return internal_find(st, data, OSSL_BSEARCH_FIRST_VALUE_ON_MATCH, pnum);
}
int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data)
+4 -18
View File
@@ -516,19 +516,7 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
return -1;
}
idx = sk_X509_OBJECT_find(h, &stmp);
if (idx >= 0 && pnmatch) {
int tidx;
const X509_OBJECT *tobj, *pstmp;
*pnmatch = 1;
pstmp = &stmp;
for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) {
tobj = sk_X509_OBJECT_value(h, tidx);
if (x509_object_cmp(&tobj, &pstmp))
break;
(*pnmatch)++;
}
}
idx = sk_X509_OBJECT_find_all(h, &stmp, pnmatch);
return idx;
}
@@ -725,7 +713,7 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
const X509_NAME *xn;
X509_OBJECT *obj = X509_OBJECT_new(), *pobj = NULL;
X509_STORE *store = ctx->store;
int i, ok, idx, ret;
int i, ok, idx, ret, nmatch = 0;
if (obj == NULL)
return -1;
@@ -761,16 +749,14 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
/* Find index of first currently valid cert accepted by 'check_issued' */
ret = 0;
X509_STORE_lock(store);
idx = X509_OBJECT_idx_by_subject(store->objs, X509_LU_X509, xn);
idx = x509_object_idx_cnt(store->objs, X509_LU_X509, xn, &nmatch);
if (idx != -1) { /* should be true as we've had at least one match */
/* Look through all matching certs for suitable issuer */
for (i = idx; i < sk_X509_OBJECT_num(store->objs); i++) {
for (i = idx; i < idx + nmatch; i++) {
pobj = sk_X509_OBJECT_value(store->objs, i);
/* See if we've run past the matches */
if (pobj->type != X509_LU_X509)
break;
if (X509_NAME_cmp(X509_get_subject_name(pobj->data.x509), xn) != 0)
break; /* Not more cert matches xn */
if (ctx->check_issued(ctx, x, pobj->data.x509)) {
ret = 1;
/* If times check fine, exit with match, else keep looking. */
+14 -7
View File
@@ -8,8 +8,9 @@ sk_TYPE_num, sk_TYPE_value, sk_TYPE_new, sk_TYPE_new_null,
sk_TYPE_reserve, sk_TYPE_free, sk_TYPE_zero, sk_TYPE_delete,
sk_TYPE_delete_ptr, sk_TYPE_push, sk_TYPE_unshift, sk_TYPE_pop,
sk_TYPE_shift, sk_TYPE_pop_free, sk_TYPE_insert, sk_TYPE_set,
sk_TYPE_find, sk_TYPE_find_ex, sk_TYPE_sort, sk_TYPE_is_sorted,
sk_TYPE_dup, sk_TYPE_deep_copy, sk_TYPE_set_cmp_func, sk_TYPE_new_reserve
sk_TYPE_find, sk_TYPE_find_ex, sk_TYPE_find_all, sk_TYPE_sort,
sk_TYPE_is_sorted, sk_TYPE_dup, sk_TYPE_deep_copy, sk_TYPE_set_cmp_func,
sk_TYPE_new_reserve
- stack container
=head1 SYNOPSIS
@@ -46,6 +47,7 @@ sk_TYPE_dup, sk_TYPE_deep_copy, sk_TYPE_set_cmp_func, sk_TYPE_new_reserve
TYPE *sk_TYPE_set(STACK_OF(TYPE) *sk, int idx, const TYPE *ptr);
int sk_TYPE_find(STACK_OF(TYPE) *sk, TYPE *ptr);
int sk_TYPE_find_ex(STACK_OF(TYPE) *sk, TYPE *ptr);
int sk_TYPE_find_all(STACK_OF(TYPE) *sk, TYPE *ptr, int *pnum);
void sk_TYPE_sort(const STACK_OF(TYPE) *sk);
int sk_TYPE_is_sorted(const STACK_OF(TYPE) *sk);
STACK_OF(TYPE) *sk_TYPE_dup(const STACK_OF(TYPE) *sk);
@@ -165,18 +167,23 @@ B<sk_I<TYPE>_find>() searches I<sk> for the element I<ptr>. In the case
where no comparison function has been specified, the function performs
a linear search for a pointer equal to I<ptr>. The index of the first
matching element is returned or B<-1> if there is no match. In the case
where a comparison function has been specified, I<sk> is sorted then
where a comparison function has been specified, I<sk> is sorted and
B<sk_I<TYPE>_find>() returns the index of a matching element or B<-1> if there
is no match. Note that, in this case, the matching element returned is
not guaranteed to be the first; the comparison function will usually
is no match. Note that, in this case the comparison function will usually
compare the values pointed to rather than the pointers themselves and
the order of elements in I<sk> could change.
the order of elements in I<sk> can change.
B<sk_I<TYPE>_find_ex>() operates like B<sk_I<TYPE>_find>() except when a
comparison function has been specified and no matching element is found.
Instead of returning B<-1>, B<sk_I<TYPE>_find_ex>() returns the index of the
element either before or after the location where I<ptr> would be if it were
present in I<sk>.
present in I<sk>. The function also does not guarantee that the first matching
element in the sorted stack is returned.
B<sk_I<TYPE>_find_all>() operates like B<sk_I<TYPE>_find>() but it also
sets the I<*pnum> to number of matching elements in the stack. In case
no comparison function has been specified the I<*pnum> will be always set
to 1 if matching element was found, 0 otherwise.
B<sk_I<TYPE>_sort>() sorts I<sk> using the supplied comparison function.
+4
View File
@@ -146,6 +146,10 @@ extern "C" {
{ \
return OPENSSL_sk_find_ex((OPENSSL_STACK *)sk, (const void *)ptr); \
} \
static ossl_unused ossl_inline int sk_##t1##_find_all(STACK_OF(t1) *sk, t2 *ptr, int *pnum) \
{ \
return OPENSSL_sk_find_all((OPENSSL_STACK *)sk, (const void *)ptr, pnum); \
} \
static ossl_unused ossl_inline void sk_##t1##_sort(STACK_OF(t1) *sk) \
{ \
OPENSSL_sk_sort((OPENSSL_STACK *)sk); \
+1
View File
@@ -45,6 +45,7 @@ void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc);
void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p);
int OPENSSL_sk_find(OPENSSL_STACK *st, const void *data);
int OPENSSL_sk_find_ex(OPENSSL_STACK *st, const void *data);
int OPENSSL_sk_find_all(OPENSSL_STACK *st, const void *data, int *pnum);
int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data);
int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data);
void *OPENSSL_sk_shift(OPENSSL_STACK *st);
+1
View File
@@ -5347,6 +5347,7 @@ EVP_ASYM_CIPHER_description ? 3_0_0 EXIST::FUNCTION:
EVP_KEM_description ? 3_0_0 EXIST::FUNCTION:
EVP_KEYEXCH_description ? 3_0_0 EXIST::FUNCTION:
EVP_KDF_description ? 3_0_0 EXIST::FUNCTION:
OPENSSL_sk_find_all ? 3_0_0 EXIST::FUNCTION:
X509_CRL_new_ex ? 3_0_0 EXIST::FUNCTION:
OSSL_PARAM_dup ? 3_0_0 EXIST::FUNCTION:
OSSL_PARAM_merge ? 3_0_0 EXIST::FUNCTION:
+1
View File
@@ -45,6 +45,7 @@ SKM_DEFINE_STACK_OF_INTERNAL(${nametype}, ${realtype}, ${plaintype})
#define sk_${nametype}_set(sk, idx, ptr) ((${realtype} *)OPENSSL_sk_set(ossl_check_${nametype}_sk_type(sk), (idx), ossl_check_${nametype}_type(ptr)))
#define sk_${nametype}_find(sk, ptr) OPENSSL_sk_find(ossl_check_${nametype}_sk_type(sk), ossl_check_${nametype}_type(ptr))
#define sk_${nametype}_find_ex(sk, ptr) OPENSSL_sk_find_ex(ossl_check_${nametype}_sk_type(sk), ossl_check_${nametype}_type(ptr))
#define sk_${nametype}_find_all(sk, ptr, pnum) OPENSSL_sk_find_all(ossl_check_${nametype}_sk_type(sk), ossl_check_${nametype}_type(ptr), pnum)
#define sk_${nametype}_sort(sk) OPENSSL_sk_sort(ossl_check_${nametype}_sk_type(sk))
#define sk_${nametype}_is_sorted(sk) OPENSSL_sk_is_sorted(ossl_check_const_${nametype}_sk_type(sk))
#define sk_${nametype}_dup(sk) ((STACK_OF(${nametype}) *)OPENSSL_sk_dup(ossl_check_const_${nametype}_sk_type(sk)))