From 2f605e8d24ac054a862e0fc4ea7e53196c99bb7e Mon Sep 17 00:00:00 2001
From: "Dr. Stephen Henson" <steve@openssl.org>
Date: Mon, 4 Oct 2004 16:30:12 +0000
Subject: [PATCH] Fix race condition when CRL checking is enabled.

---
 CHANGES                  |  7 +++++
 crypto/asn1/x_crl.c      | 39 +++++-------------------
 crypto/stack/safestack.h | 66 ++++++++++++++++++++++++++++++++++++++++
 crypto/stack/stack.c     |  7 +++++
 crypto/stack/stack.h     |  1 +
 crypto/x509/x509.h       |  1 +
 crypto/x509/x509_vfy.c   |  9 ++++++
 util/mkstack.pl          |  1 +
 8 files changed, 100 insertions(+), 31 deletions(-)

diff --git a/CHANGES b/CHANGES
index 52d9b4a1b3..caee856df0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -725,6 +725,13 @@
 
  Changes between 0.9.7d and 0.9.7e  [XX xxx XXXX]
 
+  *) Avoid a race condition when CRLs are checked in a multi threaded 
+     environment. This would happen due to the reordering of the revoked
+     entries during signature checking and serial number lookup. Now the
+     encoding is cached and the serial number sort performed under a lock.
+     Add new STACK function sk_is_sorted().
+     [Steve Henson]
+
   *) Add Delta CRL to the extension code.
      [Steve Henson]
 
diff --git a/crypto/asn1/x_crl.c b/crypto/asn1/x_crl.c
index 11fce96825..e4d19183ca 100644
--- a/crypto/asn1/x_crl.c
+++ b/crypto/asn1/x_crl.c
@@ -63,8 +63,6 @@
 
 static int X509_REVOKED_cmp(const X509_REVOKED * const *a,
 				const X509_REVOKED * const *b);
-static int X509_REVOKED_seq_cmp(const X509_REVOKED * const *a,
-				const X509_REVOKED * const *b);
 
 ASN1_SEQUENCE(X509_REVOKED) = {
 	ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER),
@@ -72,43 +70,28 @@ ASN1_SEQUENCE(X509_REVOKED) = {
 	ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION)
 } ASN1_SEQUENCE_END(X509_REVOKED)
 
-/* The X509_CRL_INFO structure needs a bit of customisation. This is actually
- * mirroring the old behaviour: its purpose is to allow the use of
- * sk_X509_REVOKED_find to lookup revoked certificates. Unfortunately
- * this will zap the original order and the signature so we keep a copy
- * of the original positions and reorder appropriately before encoding.
- *
- * Might want to see if there's a better way of doing this later...
+/* The X509_CRL_INFO structure needs a bit of customisation.
+ * Since we cache the original encoding the signature wont be affected by
+ * reordering of the revoked field.
  */
 static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it)
 {
 	X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
-	int i;
-	int (*old_cmp)(const X509_REVOKED * const *,
-			const X509_REVOKED * const *);
 
 	if(!a || !a->revoked) return 1;
 	switch(operation) {
-
-		/* Save original order */
+		/* Just set cmp function here. We don't sort because that
+		 * would affect the output of X509_CRL_print().
+		 */
 		case ASN1_OP_D2I_POST:
-		for (i=0; i<sk_X509_REVOKED_num(a->revoked); i++)
-			sk_X509_REVOKED_value(a->revoked,i)->sequence=i;
 		sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_cmp);
 		break;
-
-		/* Restore original order */
-		case ASN1_OP_I2D_PRE:
-		old_cmp=sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_seq_cmp);
-		sk_X509_REVOKED_sort(a->revoked);
-		sk_X509_REVOKED_set_cmp_func(a->revoked,old_cmp);
-		break;
 	}
 	return 1;
 }
 
 
-ASN1_SEQUENCE_cb(X509_CRL_INFO, crl_inf_cb) = {
+ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = {
 	ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
 	ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR),
 	ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
@@ -116,7 +99,7 @@ ASN1_SEQUENCE_cb(X509_CRL_INFO, crl_inf_cb) = {
 	ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
 	ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
 	ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0)
-} ASN1_SEQUENCE_END_cb(X509_CRL_INFO, X509_CRL_INFO)
+} ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO)
 
 ASN1_SEQUENCE_ref(X509_CRL, 0, CRYPTO_LOCK_X509_CRL) = {
 	ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
@@ -137,12 +120,6 @@ static int X509_REVOKED_cmp(const X509_REVOKED * const *a,
 		(ASN1_STRING *)(*b)->serialNumber));
 	}
 
-static int X509_REVOKED_seq_cmp(const X509_REVOKED * const *a,
-				const X509_REVOKED * const *b)
-	{
-	return((*a)->sequence-(*b)->sequence);
-	}
-
 int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
 {
 	X509_CRL_INFO *inf;
diff --git a/crypto/stack/safestack.h b/crypto/stack/safestack.h
index 0b38337d03..6d6739eae1 100644
--- a/crypto/stack/safestack.h
+++ b/crypto/stack/safestack.h
@@ -113,6 +113,8 @@ STACK_OF(type) \
 	((type * (*)(STACK_OF(type) *))sk_pop)(st)
 #define SKM_sk_sort(type, st) \
 	((void (*)(STACK_OF(type) *))sk_sort)(st)
+#define SKM_sk_is_sorted(type, st) \
+	((int (*)(const STACK_OF(type) *))sk_is_sorted)(st)
 
 #define	SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
 ((STACK_OF(type) * (*) (STACK_OF(type) **,const unsigned char **, long , \
@@ -188,6 +190,8 @@ STACK_OF(type) \
 	((type *)sk_pop(st))
 #define SKM_sk_sort(type, st) \
 	sk_sort(st)
+#define SKM_sk_is_sorted(type, st) \
+	sk_is_sorted(st)
 
 #define	SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
 	d2i_ASN1_SET(st,pp,length, (char *(*)())d2i_func, (void (*)(void *))free_func, ex_tag,ex_class)
@@ -225,6 +229,7 @@ STACK_OF(type) \
 #define sk_ACCESS_DESCRIPTION_shift(st) SKM_sk_shift(ACCESS_DESCRIPTION, (st))
 #define sk_ACCESS_DESCRIPTION_pop(st) SKM_sk_pop(ACCESS_DESCRIPTION, (st))
 #define sk_ACCESS_DESCRIPTION_sort(st) SKM_sk_sort(ACCESS_DESCRIPTION, (st))
+#define sk_ACCESS_DESCRIPTION_is_sorted(st) SKM_sk_is_sorted(ACCESS_DESCRIPTION, (st))
 
 #define sk_ASN1_GENERALSTRING_new(st) SKM_sk_new(ASN1_GENERALSTRING, (st))
 #define sk_ASN1_GENERALSTRING_new_null() SKM_sk_new_null(ASN1_GENERALSTRING)
@@ -246,6 +251,7 @@ STACK_OF(type) \
 #define sk_ASN1_GENERALSTRING_shift(st) SKM_sk_shift(ASN1_GENERALSTRING, (st))
 #define sk_ASN1_GENERALSTRING_pop(st) SKM_sk_pop(ASN1_GENERALSTRING, (st))
 #define sk_ASN1_GENERALSTRING_sort(st) SKM_sk_sort(ASN1_GENERALSTRING, (st))
+#define sk_ASN1_GENERALSTRING_is_sorted(st) SKM_sk_is_sorted(ASN1_GENERALSTRING, (st))
 
 #define sk_ASN1_INTEGER_new(st) SKM_sk_new(ASN1_INTEGER, (st))
 #define sk_ASN1_INTEGER_new_null() SKM_sk_new_null(ASN1_INTEGER)
@@ -267,6 +273,7 @@ STACK_OF(type) \
 #define sk_ASN1_INTEGER_shift(st) SKM_sk_shift(ASN1_INTEGER, (st))
 #define sk_ASN1_INTEGER_pop(st) SKM_sk_pop(ASN1_INTEGER, (st))
 #define sk_ASN1_INTEGER_sort(st) SKM_sk_sort(ASN1_INTEGER, (st))
+#define sk_ASN1_INTEGER_is_sorted(st) SKM_sk_is_sorted(ASN1_INTEGER, (st))
 
 #define sk_ASN1_OBJECT_new(st) SKM_sk_new(ASN1_OBJECT, (st))
 #define sk_ASN1_OBJECT_new_null() SKM_sk_new_null(ASN1_OBJECT)
@@ -288,6 +295,7 @@ STACK_OF(type) \
 #define sk_ASN1_OBJECT_shift(st) SKM_sk_shift(ASN1_OBJECT, (st))
 #define sk_ASN1_OBJECT_pop(st) SKM_sk_pop(ASN1_OBJECT, (st))
 #define sk_ASN1_OBJECT_sort(st) SKM_sk_sort(ASN1_OBJECT, (st))
+#define sk_ASN1_OBJECT_is_sorted(st) SKM_sk_is_sorted(ASN1_OBJECT, (st))
 
 #define sk_ASN1_STRING_TABLE_new(st) SKM_sk_new(ASN1_STRING_TABLE, (st))
 #define sk_ASN1_STRING_TABLE_new_null() SKM_sk_new_null(ASN1_STRING_TABLE)
@@ -309,6 +317,7 @@ STACK_OF(type) \
 #define sk_ASN1_STRING_TABLE_shift(st) SKM_sk_shift(ASN1_STRING_TABLE, (st))
 #define sk_ASN1_STRING_TABLE_pop(st) SKM_sk_pop(ASN1_STRING_TABLE, (st))
 #define sk_ASN1_STRING_TABLE_sort(st) SKM_sk_sort(ASN1_STRING_TABLE, (st))
+#define sk_ASN1_STRING_TABLE_is_sorted(st) SKM_sk_is_sorted(ASN1_STRING_TABLE, (st))
 
 #define sk_ASN1_TYPE_new(st) SKM_sk_new(ASN1_TYPE, (st))
 #define sk_ASN1_TYPE_new_null() SKM_sk_new_null(ASN1_TYPE)
@@ -330,6 +339,7 @@ STACK_OF(type) \
 #define sk_ASN1_TYPE_shift(st) SKM_sk_shift(ASN1_TYPE, (st))
 #define sk_ASN1_TYPE_pop(st) SKM_sk_pop(ASN1_TYPE, (st))
 #define sk_ASN1_TYPE_sort(st) SKM_sk_sort(ASN1_TYPE, (st))
+#define sk_ASN1_TYPE_is_sorted(st) SKM_sk_is_sorted(ASN1_TYPE, (st))
 
 #define sk_ASN1_VALUE_new(st) SKM_sk_new(ASN1_VALUE, (st))
 #define sk_ASN1_VALUE_new_null() SKM_sk_new_null(ASN1_VALUE)
@@ -351,6 +361,7 @@ STACK_OF(type) \
 #define sk_ASN1_VALUE_shift(st) SKM_sk_shift(ASN1_VALUE, (st))
 #define sk_ASN1_VALUE_pop(st) SKM_sk_pop(ASN1_VALUE, (st))
 #define sk_ASN1_VALUE_sort(st) SKM_sk_sort(ASN1_VALUE, (st))
+#define sk_ASN1_VALUE_is_sorted(st) SKM_sk_is_sorted(ASN1_VALUE, (st))
 
 #define sk_BIO_new(st) SKM_sk_new(BIO, (st))
 #define sk_BIO_new_null() SKM_sk_new_null(BIO)
@@ -372,6 +383,7 @@ STACK_OF(type) \
 #define sk_BIO_shift(st) SKM_sk_shift(BIO, (st))
 #define sk_BIO_pop(st) SKM_sk_pop(BIO, (st))
 #define sk_BIO_sort(st) SKM_sk_sort(BIO, (st))
+#define sk_BIO_is_sorted(st) SKM_sk_is_sorted(BIO, (st))
 
 #define sk_CONF_IMODULE_new(st) SKM_sk_new(CONF_IMODULE, (st))
 #define sk_CONF_IMODULE_new_null() SKM_sk_new_null(CONF_IMODULE)
@@ -393,6 +405,7 @@ STACK_OF(type) \
 #define sk_CONF_IMODULE_shift(st) SKM_sk_shift(CONF_IMODULE, (st))
 #define sk_CONF_IMODULE_pop(st) SKM_sk_pop(CONF_IMODULE, (st))
 #define sk_CONF_IMODULE_sort(st) SKM_sk_sort(CONF_IMODULE, (st))
+#define sk_CONF_IMODULE_is_sorted(st) SKM_sk_is_sorted(CONF_IMODULE, (st))
 
 #define sk_CONF_MODULE_new(st) SKM_sk_new(CONF_MODULE, (st))
 #define sk_CONF_MODULE_new_null() SKM_sk_new_null(CONF_MODULE)
@@ -414,6 +427,7 @@ STACK_OF(type) \
 #define sk_CONF_MODULE_shift(st) SKM_sk_shift(CONF_MODULE, (st))
 #define sk_CONF_MODULE_pop(st) SKM_sk_pop(CONF_MODULE, (st))
 #define sk_CONF_MODULE_sort(st) SKM_sk_sort(CONF_MODULE, (st))
+#define sk_CONF_MODULE_is_sorted(st) SKM_sk_is_sorted(CONF_MODULE, (st))
 
 #define sk_CONF_VALUE_new(st) SKM_sk_new(CONF_VALUE, (st))
 #define sk_CONF_VALUE_new_null() SKM_sk_new_null(CONF_VALUE)
@@ -435,6 +449,7 @@ STACK_OF(type) \
 #define sk_CONF_VALUE_shift(st) SKM_sk_shift(CONF_VALUE, (st))
 #define sk_CONF_VALUE_pop(st) SKM_sk_pop(CONF_VALUE, (st))
 #define sk_CONF_VALUE_sort(st) SKM_sk_sort(CONF_VALUE, (st))
+#define sk_CONF_VALUE_is_sorted(st) SKM_sk_is_sorted(CONF_VALUE, (st))
 
 #define sk_CRYPTO_EX_DATA_FUNCS_new(st) SKM_sk_new(CRYPTO_EX_DATA_FUNCS, (st))
 #define sk_CRYPTO_EX_DATA_FUNCS_new_null() SKM_sk_new_null(CRYPTO_EX_DATA_FUNCS)
@@ -456,6 +471,7 @@ STACK_OF(type) \
 #define sk_CRYPTO_EX_DATA_FUNCS_shift(st) SKM_sk_shift(CRYPTO_EX_DATA_FUNCS, (st))
 #define sk_CRYPTO_EX_DATA_FUNCS_pop(st) SKM_sk_pop(CRYPTO_EX_DATA_FUNCS, (st))
 #define sk_CRYPTO_EX_DATA_FUNCS_sort(st) SKM_sk_sort(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_is_sorted(st) SKM_sk_is_sorted(CRYPTO_EX_DATA_FUNCS, (st))
 
 #define sk_CRYPTO_dynlock_new(st) SKM_sk_new(CRYPTO_dynlock, (st))
 #define sk_CRYPTO_dynlock_new_null() SKM_sk_new_null(CRYPTO_dynlock)
@@ -477,6 +493,7 @@ STACK_OF(type) \
 #define sk_CRYPTO_dynlock_shift(st) SKM_sk_shift(CRYPTO_dynlock, (st))
 #define sk_CRYPTO_dynlock_pop(st) SKM_sk_pop(CRYPTO_dynlock, (st))
 #define sk_CRYPTO_dynlock_sort(st) SKM_sk_sort(CRYPTO_dynlock, (st))
+#define sk_CRYPTO_dynlock_is_sorted(st) SKM_sk_is_sorted(CRYPTO_dynlock, (st))
 
 #define sk_DIST_POINT_new(st) SKM_sk_new(DIST_POINT, (st))
 #define sk_DIST_POINT_new_null() SKM_sk_new_null(DIST_POINT)
@@ -498,6 +515,7 @@ STACK_OF(type) \
 #define sk_DIST_POINT_shift(st) SKM_sk_shift(DIST_POINT, (st))
 #define sk_DIST_POINT_pop(st) SKM_sk_pop(DIST_POINT, (st))
 #define sk_DIST_POINT_sort(st) SKM_sk_sort(DIST_POINT, (st))
+#define sk_DIST_POINT_is_sorted(st) SKM_sk_is_sorted(DIST_POINT, (st))
 
 #define sk_ENGINE_new(st) SKM_sk_new(ENGINE, (st))
 #define sk_ENGINE_new_null() SKM_sk_new_null(ENGINE)
@@ -519,6 +537,7 @@ STACK_OF(type) \
 #define sk_ENGINE_shift(st) SKM_sk_shift(ENGINE, (st))
 #define sk_ENGINE_pop(st) SKM_sk_pop(ENGINE, (st))
 #define sk_ENGINE_sort(st) SKM_sk_sort(ENGINE, (st))
+#define sk_ENGINE_is_sorted(st) SKM_sk_is_sorted(ENGINE, (st))
 
 #define sk_ENGINE_CLEANUP_ITEM_new(st) SKM_sk_new(ENGINE_CLEANUP_ITEM, (st))
 #define sk_ENGINE_CLEANUP_ITEM_new_null() SKM_sk_new_null(ENGINE_CLEANUP_ITEM)
@@ -540,6 +559,7 @@ STACK_OF(type) \
 #define sk_ENGINE_CLEANUP_ITEM_shift(st) SKM_sk_shift(ENGINE_CLEANUP_ITEM, (st))
 #define sk_ENGINE_CLEANUP_ITEM_pop(st) SKM_sk_pop(ENGINE_CLEANUP_ITEM, (st))
 #define sk_ENGINE_CLEANUP_ITEM_sort(st) SKM_sk_sort(ENGINE_CLEANUP_ITEM, (st))
+#define sk_ENGINE_CLEANUP_ITEM_is_sorted(st) SKM_sk_is_sorted(ENGINE_CLEANUP_ITEM, (st))
 
 #define sk_GENERAL_NAME_new(st) SKM_sk_new(GENERAL_NAME, (st))
 #define sk_GENERAL_NAME_new_null() SKM_sk_new_null(GENERAL_NAME)
@@ -561,6 +581,7 @@ STACK_OF(type) \
 #define sk_GENERAL_NAME_shift(st) SKM_sk_shift(GENERAL_NAME, (st))
 #define sk_GENERAL_NAME_pop(st) SKM_sk_pop(GENERAL_NAME, (st))
 #define sk_GENERAL_NAME_sort(st) SKM_sk_sort(GENERAL_NAME, (st))
+#define sk_GENERAL_NAME_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAME, (st))
 
 #define sk_GENERAL_SUBTREE_new(st) SKM_sk_new(GENERAL_SUBTREE, (st))
 #define sk_GENERAL_SUBTREE_new_null() SKM_sk_new_null(GENERAL_SUBTREE)
@@ -582,6 +603,7 @@ STACK_OF(type) \
 #define sk_GENERAL_SUBTREE_shift(st) SKM_sk_shift(GENERAL_SUBTREE, (st))
 #define sk_GENERAL_SUBTREE_pop(st) SKM_sk_pop(GENERAL_SUBTREE, (st))
 #define sk_GENERAL_SUBTREE_sort(st) SKM_sk_sort(GENERAL_SUBTREE, (st))
+#define sk_GENERAL_SUBTREE_is_sorted(st) SKM_sk_is_sorted(GENERAL_SUBTREE, (st))
 
 #define sk_KRB5_APREQBODY_new(st) SKM_sk_new(KRB5_APREQBODY, (st))
 #define sk_KRB5_APREQBODY_new_null() SKM_sk_new_null(KRB5_APREQBODY)
@@ -603,6 +625,7 @@ STACK_OF(type) \
 #define sk_KRB5_APREQBODY_shift(st) SKM_sk_shift(KRB5_APREQBODY, (st))
 #define sk_KRB5_APREQBODY_pop(st) SKM_sk_pop(KRB5_APREQBODY, (st))
 #define sk_KRB5_APREQBODY_sort(st) SKM_sk_sort(KRB5_APREQBODY, (st))
+#define sk_KRB5_APREQBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_APREQBODY, (st))
 
 #define sk_KRB5_AUTHDATA_new(st) SKM_sk_new(KRB5_AUTHDATA, (st))
 #define sk_KRB5_AUTHDATA_new_null() SKM_sk_new_null(KRB5_AUTHDATA)
@@ -624,6 +647,7 @@ STACK_OF(type) \
 #define sk_KRB5_AUTHDATA_shift(st) SKM_sk_shift(KRB5_AUTHDATA, (st))
 #define sk_KRB5_AUTHDATA_pop(st) SKM_sk_pop(KRB5_AUTHDATA, (st))
 #define sk_KRB5_AUTHDATA_sort(st) SKM_sk_sort(KRB5_AUTHDATA, (st))
+#define sk_KRB5_AUTHDATA_is_sorted(st) SKM_sk_is_sorted(KRB5_AUTHDATA, (st))
 
 #define sk_KRB5_AUTHENTBODY_new(st) SKM_sk_new(KRB5_AUTHENTBODY, (st))
 #define sk_KRB5_AUTHENTBODY_new_null() SKM_sk_new_null(KRB5_AUTHENTBODY)
@@ -645,6 +669,7 @@ STACK_OF(type) \
 #define sk_KRB5_AUTHENTBODY_shift(st) SKM_sk_shift(KRB5_AUTHENTBODY, (st))
 #define sk_KRB5_AUTHENTBODY_pop(st) SKM_sk_pop(KRB5_AUTHENTBODY, (st))
 #define sk_KRB5_AUTHENTBODY_sort(st) SKM_sk_sort(KRB5_AUTHENTBODY, (st))
+#define sk_KRB5_AUTHENTBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_AUTHENTBODY, (st))
 
 #define sk_KRB5_CHECKSUM_new(st) SKM_sk_new(KRB5_CHECKSUM, (st))
 #define sk_KRB5_CHECKSUM_new_null() SKM_sk_new_null(KRB5_CHECKSUM)
@@ -666,6 +691,7 @@ STACK_OF(type) \
 #define sk_KRB5_CHECKSUM_shift(st) SKM_sk_shift(KRB5_CHECKSUM, (st))
 #define sk_KRB5_CHECKSUM_pop(st) SKM_sk_pop(KRB5_CHECKSUM, (st))
 #define sk_KRB5_CHECKSUM_sort(st) SKM_sk_sort(KRB5_CHECKSUM, (st))
+#define sk_KRB5_CHECKSUM_is_sorted(st) SKM_sk_is_sorted(KRB5_CHECKSUM, (st))
 
 #define sk_KRB5_ENCDATA_new(st) SKM_sk_new(KRB5_ENCDATA, (st))
 #define sk_KRB5_ENCDATA_new_null() SKM_sk_new_null(KRB5_ENCDATA)
@@ -687,6 +713,7 @@ STACK_OF(type) \
 #define sk_KRB5_ENCDATA_shift(st) SKM_sk_shift(KRB5_ENCDATA, (st))
 #define sk_KRB5_ENCDATA_pop(st) SKM_sk_pop(KRB5_ENCDATA, (st))
 #define sk_KRB5_ENCDATA_sort(st) SKM_sk_sort(KRB5_ENCDATA, (st))
+#define sk_KRB5_ENCDATA_is_sorted(st) SKM_sk_is_sorted(KRB5_ENCDATA, (st))
 
 #define sk_KRB5_ENCKEY_new(st) SKM_sk_new(KRB5_ENCKEY, (st))
 #define sk_KRB5_ENCKEY_new_null() SKM_sk_new_null(KRB5_ENCKEY)
@@ -708,6 +735,7 @@ STACK_OF(type) \
 #define sk_KRB5_ENCKEY_shift(st) SKM_sk_shift(KRB5_ENCKEY, (st))
 #define sk_KRB5_ENCKEY_pop(st) SKM_sk_pop(KRB5_ENCKEY, (st))
 #define sk_KRB5_ENCKEY_sort(st) SKM_sk_sort(KRB5_ENCKEY, (st))
+#define sk_KRB5_ENCKEY_is_sorted(st) SKM_sk_is_sorted(KRB5_ENCKEY, (st))
 
 #define sk_KRB5_PRINCNAME_new(st) SKM_sk_new(KRB5_PRINCNAME, (st))
 #define sk_KRB5_PRINCNAME_new_null() SKM_sk_new_null(KRB5_PRINCNAME)
@@ -729,6 +757,7 @@ STACK_OF(type) \
 #define sk_KRB5_PRINCNAME_shift(st) SKM_sk_shift(KRB5_PRINCNAME, (st))
 #define sk_KRB5_PRINCNAME_pop(st) SKM_sk_pop(KRB5_PRINCNAME, (st))
 #define sk_KRB5_PRINCNAME_sort(st) SKM_sk_sort(KRB5_PRINCNAME, (st))
+#define sk_KRB5_PRINCNAME_is_sorted(st) SKM_sk_is_sorted(KRB5_PRINCNAME, (st))
 
 #define sk_KRB5_TKTBODY_new(st) SKM_sk_new(KRB5_TKTBODY, (st))
 #define sk_KRB5_TKTBODY_new_null() SKM_sk_new_null(KRB5_TKTBODY)
@@ -750,6 +779,7 @@ STACK_OF(type) \
 #define sk_KRB5_TKTBODY_shift(st) SKM_sk_shift(KRB5_TKTBODY, (st))
 #define sk_KRB5_TKTBODY_pop(st) SKM_sk_pop(KRB5_TKTBODY, (st))
 #define sk_KRB5_TKTBODY_sort(st) SKM_sk_sort(KRB5_TKTBODY, (st))
+#define sk_KRB5_TKTBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_TKTBODY, (st))
 
 #define sk_MIME_HEADER_new(st) SKM_sk_new(MIME_HEADER, (st))
 #define sk_MIME_HEADER_new_null() SKM_sk_new_null(MIME_HEADER)
@@ -771,6 +801,7 @@ STACK_OF(type) \
 #define sk_MIME_HEADER_shift(st) SKM_sk_shift(MIME_HEADER, (st))
 #define sk_MIME_HEADER_pop(st) SKM_sk_pop(MIME_HEADER, (st))
 #define sk_MIME_HEADER_sort(st) SKM_sk_sort(MIME_HEADER, (st))
+#define sk_MIME_HEADER_is_sorted(st) SKM_sk_is_sorted(MIME_HEADER, (st))
 
 #define sk_MIME_PARAM_new(st) SKM_sk_new(MIME_PARAM, (st))
 #define sk_MIME_PARAM_new_null() SKM_sk_new_null(MIME_PARAM)
@@ -792,6 +823,7 @@ STACK_OF(type) \
 #define sk_MIME_PARAM_shift(st) SKM_sk_shift(MIME_PARAM, (st))
 #define sk_MIME_PARAM_pop(st) SKM_sk_pop(MIME_PARAM, (st))
 #define sk_MIME_PARAM_sort(st) SKM_sk_sort(MIME_PARAM, (st))
+#define sk_MIME_PARAM_is_sorted(st) SKM_sk_is_sorted(MIME_PARAM, (st))
 
 #define sk_NAME_FUNCS_new(st) SKM_sk_new(NAME_FUNCS, (st))
 #define sk_NAME_FUNCS_new_null() SKM_sk_new_null(NAME_FUNCS)
@@ -813,6 +845,7 @@ STACK_OF(type) \
 #define sk_NAME_FUNCS_shift(st) SKM_sk_shift(NAME_FUNCS, (st))
 #define sk_NAME_FUNCS_pop(st) SKM_sk_pop(NAME_FUNCS, (st))
 #define sk_NAME_FUNCS_sort(st) SKM_sk_sort(NAME_FUNCS, (st))
+#define sk_NAME_FUNCS_is_sorted(st) SKM_sk_is_sorted(NAME_FUNCS, (st))
 
 #define sk_OCSP_CERTID_new(st) SKM_sk_new(OCSP_CERTID, (st))
 #define sk_OCSP_CERTID_new_null() SKM_sk_new_null(OCSP_CERTID)
@@ -834,6 +867,7 @@ STACK_OF(type) \
 #define sk_OCSP_CERTID_shift(st) SKM_sk_shift(OCSP_CERTID, (st))
 #define sk_OCSP_CERTID_pop(st) SKM_sk_pop(OCSP_CERTID, (st))
 #define sk_OCSP_CERTID_sort(st) SKM_sk_sort(OCSP_CERTID, (st))
+#define sk_OCSP_CERTID_is_sorted(st) SKM_sk_is_sorted(OCSP_CERTID, (st))
 
 #define sk_OCSP_ONEREQ_new(st) SKM_sk_new(OCSP_ONEREQ, (st))
 #define sk_OCSP_ONEREQ_new_null() SKM_sk_new_null(OCSP_ONEREQ)
@@ -855,6 +889,7 @@ STACK_OF(type) \
 #define sk_OCSP_ONEREQ_shift(st) SKM_sk_shift(OCSP_ONEREQ, (st))
 #define sk_OCSP_ONEREQ_pop(st) SKM_sk_pop(OCSP_ONEREQ, (st))
 #define sk_OCSP_ONEREQ_sort(st) SKM_sk_sort(OCSP_ONEREQ, (st))
+#define sk_OCSP_ONEREQ_is_sorted(st) SKM_sk_is_sorted(OCSP_ONEREQ, (st))
 
 #define sk_OCSP_SINGLERESP_new(st) SKM_sk_new(OCSP_SINGLERESP, (st))
 #define sk_OCSP_SINGLERESP_new_null() SKM_sk_new_null(OCSP_SINGLERESP)
@@ -876,6 +911,7 @@ STACK_OF(type) \
 #define sk_OCSP_SINGLERESP_shift(st) SKM_sk_shift(OCSP_SINGLERESP, (st))
 #define sk_OCSP_SINGLERESP_pop(st) SKM_sk_pop(OCSP_SINGLERESP, (st))
 #define sk_OCSP_SINGLERESP_sort(st) SKM_sk_sort(OCSP_SINGLERESP, (st))
+#define sk_OCSP_SINGLERESP_is_sorted(st) SKM_sk_is_sorted(OCSP_SINGLERESP, (st))
 
 #define sk_PKCS12_SAFEBAG_new(st) SKM_sk_new(PKCS12_SAFEBAG, (st))
 #define sk_PKCS12_SAFEBAG_new_null() SKM_sk_new_null(PKCS12_SAFEBAG)
@@ -897,6 +933,7 @@ STACK_OF(type) \
 #define sk_PKCS12_SAFEBAG_shift(st) SKM_sk_shift(PKCS12_SAFEBAG, (st))
 #define sk_PKCS12_SAFEBAG_pop(st) SKM_sk_pop(PKCS12_SAFEBAG, (st))
 #define sk_PKCS12_SAFEBAG_sort(st) SKM_sk_sort(PKCS12_SAFEBAG, (st))
+#define sk_PKCS12_SAFEBAG_is_sorted(st) SKM_sk_is_sorted(PKCS12_SAFEBAG, (st))
 
 #define sk_PKCS7_new(st) SKM_sk_new(PKCS7, (st))
 #define sk_PKCS7_new_null() SKM_sk_new_null(PKCS7)
@@ -918,6 +955,7 @@ STACK_OF(type) \
 #define sk_PKCS7_shift(st) SKM_sk_shift(PKCS7, (st))
 #define sk_PKCS7_pop(st) SKM_sk_pop(PKCS7, (st))
 #define sk_PKCS7_sort(st) SKM_sk_sort(PKCS7, (st))
+#define sk_PKCS7_is_sorted(st) SKM_sk_is_sorted(PKCS7, (st))
 
 #define sk_PKCS7_RECIP_INFO_new(st) SKM_sk_new(PKCS7_RECIP_INFO, (st))
 #define sk_PKCS7_RECIP_INFO_new_null() SKM_sk_new_null(PKCS7_RECIP_INFO)
@@ -939,6 +977,7 @@ STACK_OF(type) \
 #define sk_PKCS7_RECIP_INFO_shift(st) SKM_sk_shift(PKCS7_RECIP_INFO, (st))
 #define sk_PKCS7_RECIP_INFO_pop(st) SKM_sk_pop(PKCS7_RECIP_INFO, (st))
 #define sk_PKCS7_RECIP_INFO_sort(st) SKM_sk_sort(PKCS7_RECIP_INFO, (st))
+#define sk_PKCS7_RECIP_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_RECIP_INFO, (st))
 
 #define sk_PKCS7_SIGNER_INFO_new(st) SKM_sk_new(PKCS7_SIGNER_INFO, (st))
 #define sk_PKCS7_SIGNER_INFO_new_null() SKM_sk_new_null(PKCS7_SIGNER_INFO)
@@ -960,6 +999,7 @@ STACK_OF(type) \
 #define sk_PKCS7_SIGNER_INFO_shift(st) SKM_sk_shift(PKCS7_SIGNER_INFO, (st))
 #define sk_PKCS7_SIGNER_INFO_pop(st) SKM_sk_pop(PKCS7_SIGNER_INFO, (st))
 #define sk_PKCS7_SIGNER_INFO_sort(st) SKM_sk_sort(PKCS7_SIGNER_INFO, (st))
+#define sk_PKCS7_SIGNER_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_SIGNER_INFO, (st))
 
 #define sk_POLICYINFO_new(st) SKM_sk_new(POLICYINFO, (st))
 #define sk_POLICYINFO_new_null() SKM_sk_new_null(POLICYINFO)
@@ -981,6 +1021,7 @@ STACK_OF(type) \
 #define sk_POLICYINFO_shift(st) SKM_sk_shift(POLICYINFO, (st))
 #define sk_POLICYINFO_pop(st) SKM_sk_pop(POLICYINFO, (st))
 #define sk_POLICYINFO_sort(st) SKM_sk_sort(POLICYINFO, (st))
+#define sk_POLICYINFO_is_sorted(st) SKM_sk_is_sorted(POLICYINFO, (st))
 
 #define sk_POLICYQUALINFO_new(st) SKM_sk_new(POLICYQUALINFO, (st))
 #define sk_POLICYQUALINFO_new_null() SKM_sk_new_null(POLICYQUALINFO)
@@ -1002,6 +1043,7 @@ STACK_OF(type) \
 #define sk_POLICYQUALINFO_shift(st) SKM_sk_shift(POLICYQUALINFO, (st))
 #define sk_POLICYQUALINFO_pop(st) SKM_sk_pop(POLICYQUALINFO, (st))
 #define sk_POLICYQUALINFO_sort(st) SKM_sk_sort(POLICYQUALINFO, (st))
+#define sk_POLICYQUALINFO_is_sorted(st) SKM_sk_is_sorted(POLICYQUALINFO, (st))
 
 #define sk_POLICY_MAPPING_new(st) SKM_sk_new(POLICY_MAPPING, (st))
 #define sk_POLICY_MAPPING_new_null() SKM_sk_new_null(POLICY_MAPPING)
@@ -1023,6 +1065,7 @@ STACK_OF(type) \
 #define sk_POLICY_MAPPING_shift(st) SKM_sk_shift(POLICY_MAPPING, (st))
 #define sk_POLICY_MAPPING_pop(st) SKM_sk_pop(POLICY_MAPPING, (st))
 #define sk_POLICY_MAPPING_sort(st) SKM_sk_sort(POLICY_MAPPING, (st))
+#define sk_POLICY_MAPPING_is_sorted(st) SKM_sk_is_sorted(POLICY_MAPPING, (st))
 
 #define sk_SSL_CIPHER_new(st) SKM_sk_new(SSL_CIPHER, (st))
 #define sk_SSL_CIPHER_new_null() SKM_sk_new_null(SSL_CIPHER)
@@ -1044,6 +1087,7 @@ STACK_OF(type) \
 #define sk_SSL_CIPHER_shift(st) SKM_sk_shift(SSL_CIPHER, (st))
 #define sk_SSL_CIPHER_pop(st) SKM_sk_pop(SSL_CIPHER, (st))
 #define sk_SSL_CIPHER_sort(st) SKM_sk_sort(SSL_CIPHER, (st))
+#define sk_SSL_CIPHER_is_sorted(st) SKM_sk_is_sorted(SSL_CIPHER, (st))
 
 #define sk_SSL_COMP_new(st) SKM_sk_new(SSL_COMP, (st))
 #define sk_SSL_COMP_new_null() SKM_sk_new_null(SSL_COMP)
@@ -1065,6 +1109,7 @@ STACK_OF(type) \
 #define sk_SSL_COMP_shift(st) SKM_sk_shift(SSL_COMP, (st))
 #define sk_SSL_COMP_pop(st) SKM_sk_pop(SSL_COMP, (st))
 #define sk_SSL_COMP_sort(st) SKM_sk_sort(SSL_COMP, (st))
+#define sk_SSL_COMP_is_sorted(st) SKM_sk_is_sorted(SSL_COMP, (st))
 
 #define sk_STORE_OBJECT_new(st) SKM_sk_new(STORE_OBJECT, (st))
 #define sk_STORE_OBJECT_new_null() SKM_sk_new_null(STORE_OBJECT)
@@ -1086,6 +1131,7 @@ STACK_OF(type) \
 #define sk_STORE_OBJECT_shift(st) SKM_sk_shift(STORE_OBJECT, (st))
 #define sk_STORE_OBJECT_pop(st) SKM_sk_pop(STORE_OBJECT, (st))
 #define sk_STORE_OBJECT_sort(st) SKM_sk_sort(STORE_OBJECT, (st))
+#define sk_STORE_OBJECT_is_sorted(st) SKM_sk_is_sorted(STORE_OBJECT, (st))
 
 #define sk_SXNETID_new(st) SKM_sk_new(SXNETID, (st))
 #define sk_SXNETID_new_null() SKM_sk_new_null(SXNETID)
@@ -1107,6 +1153,7 @@ STACK_OF(type) \
 #define sk_SXNETID_shift(st) SKM_sk_shift(SXNETID, (st))
 #define sk_SXNETID_pop(st) SKM_sk_pop(SXNETID, (st))
 #define sk_SXNETID_sort(st) SKM_sk_sort(SXNETID, (st))
+#define sk_SXNETID_is_sorted(st) SKM_sk_is_sorted(SXNETID, (st))
 
 #define sk_UI_STRING_new(st) SKM_sk_new(UI_STRING, (st))
 #define sk_UI_STRING_new_null() SKM_sk_new_null(UI_STRING)
@@ -1128,6 +1175,7 @@ STACK_OF(type) \
 #define sk_UI_STRING_shift(st) SKM_sk_shift(UI_STRING, (st))
 #define sk_UI_STRING_pop(st) SKM_sk_pop(UI_STRING, (st))
 #define sk_UI_STRING_sort(st) SKM_sk_sort(UI_STRING, (st))
+#define sk_UI_STRING_is_sorted(st) SKM_sk_is_sorted(UI_STRING, (st))
 
 #define sk_X509_new(st) SKM_sk_new(X509, (st))
 #define sk_X509_new_null() SKM_sk_new_null(X509)
@@ -1149,6 +1197,7 @@ STACK_OF(type) \
 #define sk_X509_shift(st) SKM_sk_shift(X509, (st))
 #define sk_X509_pop(st) SKM_sk_pop(X509, (st))
 #define sk_X509_sort(st) SKM_sk_sort(X509, (st))
+#define sk_X509_is_sorted(st) SKM_sk_is_sorted(X509, (st))
 
 #define sk_X509V3_EXT_METHOD_new(st) SKM_sk_new(X509V3_EXT_METHOD, (st))
 #define sk_X509V3_EXT_METHOD_new_null() SKM_sk_new_null(X509V3_EXT_METHOD)
@@ -1170,6 +1219,7 @@ STACK_OF(type) \
 #define sk_X509V3_EXT_METHOD_shift(st) SKM_sk_shift(X509V3_EXT_METHOD, (st))
 #define sk_X509V3_EXT_METHOD_pop(st) SKM_sk_pop(X509V3_EXT_METHOD, (st))
 #define sk_X509V3_EXT_METHOD_sort(st) SKM_sk_sort(X509V3_EXT_METHOD, (st))
+#define sk_X509V3_EXT_METHOD_is_sorted(st) SKM_sk_is_sorted(X509V3_EXT_METHOD, (st))
 
 #define sk_X509_ALGOR_new(st) SKM_sk_new(X509_ALGOR, (st))
 #define sk_X509_ALGOR_new_null() SKM_sk_new_null(X509_ALGOR)
@@ -1191,6 +1241,7 @@ STACK_OF(type) \
 #define sk_X509_ALGOR_shift(st) SKM_sk_shift(X509_ALGOR, (st))
 #define sk_X509_ALGOR_pop(st) SKM_sk_pop(X509_ALGOR, (st))
 #define sk_X509_ALGOR_sort(st) SKM_sk_sort(X509_ALGOR, (st))
+#define sk_X509_ALGOR_is_sorted(st) SKM_sk_is_sorted(X509_ALGOR, (st))
 
 #define sk_X509_ATTRIBUTE_new(st) SKM_sk_new(X509_ATTRIBUTE, (st))
 #define sk_X509_ATTRIBUTE_new_null() SKM_sk_new_null(X509_ATTRIBUTE)
@@ -1212,6 +1263,7 @@ STACK_OF(type) \
 #define sk_X509_ATTRIBUTE_shift(st) SKM_sk_shift(X509_ATTRIBUTE, (st))
 #define sk_X509_ATTRIBUTE_pop(st) SKM_sk_pop(X509_ATTRIBUTE, (st))
 #define sk_X509_ATTRIBUTE_sort(st) SKM_sk_sort(X509_ATTRIBUTE, (st))
+#define sk_X509_ATTRIBUTE_is_sorted(st) SKM_sk_is_sorted(X509_ATTRIBUTE, (st))
 
 #define sk_X509_CRL_new(st) SKM_sk_new(X509_CRL, (st))
 #define sk_X509_CRL_new_null() SKM_sk_new_null(X509_CRL)
@@ -1233,6 +1285,7 @@ STACK_OF(type) \
 #define sk_X509_CRL_shift(st) SKM_sk_shift(X509_CRL, (st))
 #define sk_X509_CRL_pop(st) SKM_sk_pop(X509_CRL, (st))
 #define sk_X509_CRL_sort(st) SKM_sk_sort(X509_CRL, (st))
+#define sk_X509_CRL_is_sorted(st) SKM_sk_is_sorted(X509_CRL, (st))
 
 #define sk_X509_EXTENSION_new(st) SKM_sk_new(X509_EXTENSION, (st))
 #define sk_X509_EXTENSION_new_null() SKM_sk_new_null(X509_EXTENSION)
@@ -1254,6 +1307,7 @@ STACK_OF(type) \
 #define sk_X509_EXTENSION_shift(st) SKM_sk_shift(X509_EXTENSION, (st))
 #define sk_X509_EXTENSION_pop(st) SKM_sk_pop(X509_EXTENSION, (st))
 #define sk_X509_EXTENSION_sort(st) SKM_sk_sort(X509_EXTENSION, (st))
+#define sk_X509_EXTENSION_is_sorted(st) SKM_sk_is_sorted(X509_EXTENSION, (st))
 
 #define sk_X509_INFO_new(st) SKM_sk_new(X509_INFO, (st))
 #define sk_X509_INFO_new_null() SKM_sk_new_null(X509_INFO)
@@ -1275,6 +1329,7 @@ STACK_OF(type) \
 #define sk_X509_INFO_shift(st) SKM_sk_shift(X509_INFO, (st))
 #define sk_X509_INFO_pop(st) SKM_sk_pop(X509_INFO, (st))
 #define sk_X509_INFO_sort(st) SKM_sk_sort(X509_INFO, (st))
+#define sk_X509_INFO_is_sorted(st) SKM_sk_is_sorted(X509_INFO, (st))
 
 #define sk_X509_LOOKUP_new(st) SKM_sk_new(X509_LOOKUP, (st))
 #define sk_X509_LOOKUP_new_null() SKM_sk_new_null(X509_LOOKUP)
@@ -1296,6 +1351,7 @@ STACK_OF(type) \
 #define sk_X509_LOOKUP_shift(st) SKM_sk_shift(X509_LOOKUP, (st))
 #define sk_X509_LOOKUP_pop(st) SKM_sk_pop(X509_LOOKUP, (st))
 #define sk_X509_LOOKUP_sort(st) SKM_sk_sort(X509_LOOKUP, (st))
+#define sk_X509_LOOKUP_is_sorted(st) SKM_sk_is_sorted(X509_LOOKUP, (st))
 
 #define sk_X509_NAME_new(st) SKM_sk_new(X509_NAME, (st))
 #define sk_X509_NAME_new_null() SKM_sk_new_null(X509_NAME)
@@ -1317,6 +1373,7 @@ STACK_OF(type) \
 #define sk_X509_NAME_shift(st) SKM_sk_shift(X509_NAME, (st))
 #define sk_X509_NAME_pop(st) SKM_sk_pop(X509_NAME, (st))
 #define sk_X509_NAME_sort(st) SKM_sk_sort(X509_NAME, (st))
+#define sk_X509_NAME_is_sorted(st) SKM_sk_is_sorted(X509_NAME, (st))
 
 #define sk_X509_NAME_ENTRY_new(st) SKM_sk_new(X509_NAME_ENTRY, (st))
 #define sk_X509_NAME_ENTRY_new_null() SKM_sk_new_null(X509_NAME_ENTRY)
@@ -1338,6 +1395,7 @@ STACK_OF(type) \
 #define sk_X509_NAME_ENTRY_shift(st) SKM_sk_shift(X509_NAME_ENTRY, (st))
 #define sk_X509_NAME_ENTRY_pop(st) SKM_sk_pop(X509_NAME_ENTRY, (st))
 #define sk_X509_NAME_ENTRY_sort(st) SKM_sk_sort(X509_NAME_ENTRY, (st))
+#define sk_X509_NAME_ENTRY_is_sorted(st) SKM_sk_is_sorted(X509_NAME_ENTRY, (st))
 
 #define sk_X509_OBJECT_new(st) SKM_sk_new(X509_OBJECT, (st))
 #define sk_X509_OBJECT_new_null() SKM_sk_new_null(X509_OBJECT)
@@ -1359,6 +1417,7 @@ STACK_OF(type) \
 #define sk_X509_OBJECT_shift(st) SKM_sk_shift(X509_OBJECT, (st))
 #define sk_X509_OBJECT_pop(st) SKM_sk_pop(X509_OBJECT, (st))
 #define sk_X509_OBJECT_sort(st) SKM_sk_sort(X509_OBJECT, (st))
+#define sk_X509_OBJECT_is_sorted(st) SKM_sk_is_sorted(X509_OBJECT, (st))
 
 #define sk_X509_POLICY_DATA_new(st) SKM_sk_new(X509_POLICY_DATA, (st))
 #define sk_X509_POLICY_DATA_new_null() SKM_sk_new_null(X509_POLICY_DATA)
@@ -1380,6 +1439,7 @@ STACK_OF(type) \
 #define sk_X509_POLICY_DATA_shift(st) SKM_sk_shift(X509_POLICY_DATA, (st))
 #define sk_X509_POLICY_DATA_pop(st) SKM_sk_pop(X509_POLICY_DATA, (st))
 #define sk_X509_POLICY_DATA_sort(st) SKM_sk_sort(X509_POLICY_DATA, (st))
+#define sk_X509_POLICY_DATA_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_DATA, (st))
 
 #define sk_X509_POLICY_NODE_new(st) SKM_sk_new(X509_POLICY_NODE, (st))
 #define sk_X509_POLICY_NODE_new_null() SKM_sk_new_null(X509_POLICY_NODE)
@@ -1401,6 +1461,7 @@ STACK_OF(type) \
 #define sk_X509_POLICY_NODE_shift(st) SKM_sk_shift(X509_POLICY_NODE, (st))
 #define sk_X509_POLICY_NODE_pop(st) SKM_sk_pop(X509_POLICY_NODE, (st))
 #define sk_X509_POLICY_NODE_sort(st) SKM_sk_sort(X509_POLICY_NODE, (st))
+#define sk_X509_POLICY_NODE_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_NODE, (st))
 
 #define sk_X509_POLICY_REF_new(st) SKM_sk_new(X509_POLICY_REF, (st))
 #define sk_X509_POLICY_REF_new_null() SKM_sk_new_null(X509_POLICY_REF)
@@ -1422,6 +1483,7 @@ STACK_OF(type) \
 #define sk_X509_POLICY_REF_shift(st) SKM_sk_shift(X509_POLICY_REF, (st))
 #define sk_X509_POLICY_REF_pop(st) SKM_sk_pop(X509_POLICY_REF, (st))
 #define sk_X509_POLICY_REF_sort(st) SKM_sk_sort(X509_POLICY_REF, (st))
+#define sk_X509_POLICY_REF_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_REF, (st))
 
 #define sk_X509_PURPOSE_new(st) SKM_sk_new(X509_PURPOSE, (st))
 #define sk_X509_PURPOSE_new_null() SKM_sk_new_null(X509_PURPOSE)
@@ -1443,6 +1505,7 @@ STACK_OF(type) \
 #define sk_X509_PURPOSE_shift(st) SKM_sk_shift(X509_PURPOSE, (st))
 #define sk_X509_PURPOSE_pop(st) SKM_sk_pop(X509_PURPOSE, (st))
 #define sk_X509_PURPOSE_sort(st) SKM_sk_sort(X509_PURPOSE, (st))
+#define sk_X509_PURPOSE_is_sorted(st) SKM_sk_is_sorted(X509_PURPOSE, (st))
 
 #define sk_X509_REVOKED_new(st) SKM_sk_new(X509_REVOKED, (st))
 #define sk_X509_REVOKED_new_null() SKM_sk_new_null(X509_REVOKED)
@@ -1464,6 +1527,7 @@ STACK_OF(type) \
 #define sk_X509_REVOKED_shift(st) SKM_sk_shift(X509_REVOKED, (st))
 #define sk_X509_REVOKED_pop(st) SKM_sk_pop(X509_REVOKED, (st))
 #define sk_X509_REVOKED_sort(st) SKM_sk_sort(X509_REVOKED, (st))
+#define sk_X509_REVOKED_is_sorted(st) SKM_sk_is_sorted(X509_REVOKED, (st))
 
 #define sk_X509_TRUST_new(st) SKM_sk_new(X509_TRUST, (st))
 #define sk_X509_TRUST_new_null() SKM_sk_new_null(X509_TRUST)
@@ -1485,6 +1549,7 @@ STACK_OF(type) \
 #define sk_X509_TRUST_shift(st) SKM_sk_shift(X509_TRUST, (st))
 #define sk_X509_TRUST_pop(st) SKM_sk_pop(X509_TRUST, (st))
 #define sk_X509_TRUST_sort(st) SKM_sk_sort(X509_TRUST, (st))
+#define sk_X509_TRUST_is_sorted(st) SKM_sk_is_sorted(X509_TRUST, (st))
 
 #define sk_X509_VERIFY_PARAM_new(st) SKM_sk_new(X509_VERIFY_PARAM, (st))
 #define sk_X509_VERIFY_PARAM_new_null() SKM_sk_new_null(X509_VERIFY_PARAM)
@@ -1506,6 +1571,7 @@ STACK_OF(type) \
 #define sk_X509_VERIFY_PARAM_shift(st) SKM_sk_shift(X509_VERIFY_PARAM, (st))
 #define sk_X509_VERIFY_PARAM_pop(st) SKM_sk_pop(X509_VERIFY_PARAM, (st))
 #define sk_X509_VERIFY_PARAM_sort(st) SKM_sk_sort(X509_VERIFY_PARAM, (st))
+#define sk_X509_VERIFY_PARAM_is_sorted(st) SKM_sk_is_sorted(X509_VERIFY_PARAM, (st))
 
 #define d2i_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
 	SKM_ASN1_SET_OF_d2i(ACCESS_DESCRIPTION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) 
diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c
index 9cc0a82962..d2b2a6d293 100644
--- a/crypto/stack/stack.c
+++ b/crypto/stack/stack.c
@@ -332,3 +332,10 @@ void sk_sort(STACK *st)
 		st->sorted=1;
 		}
 	}
+
+int sk_is_sorted(const STACK *st)
+	{
+	if (st)
+		return 1;
+	return st->sorted;
+	}
diff --git a/crypto/stack/stack.h b/crypto/stack/stack.h
index 0058d50f12..5cbb116a8b 100644
--- a/crypto/stack/stack.h
+++ b/crypto/stack/stack.h
@@ -100,6 +100,7 @@ int (*sk_set_cmp_func(STACK *sk, int (*c)(const char * const *,
 			(const char * const *, const char * const *);
 STACK *sk_dup(STACK *st);
 void sk_sort(STACK *st);
+int sk_is_sorted(const STACK *st);
 
 #ifdef  __cplusplus
 }
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index edf1cd4939..016164cb68 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -435,6 +435,7 @@ typedef struct X509_crl_info_st
 	ASN1_TIME *nextUpdate;
 	STACK_OF(X509_REVOKED) *revoked;
 	STACK_OF(X509_EXTENSION) /* [0] */ *extensions;
+	ASN1_ENCODING enc;
 	} X509_CRL_INFO;
 
 struct X509_crl_st
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index a2c884e497..1e66786bd5 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -706,6 +706,15 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
 	X509_EXTENSION *ext;
 	/* Look for serial number of certificate in CRL */
 	rtmp.serialNumber = X509_get_serialNumber(x);
+	/* Sort revoked into serial number order if not already sorted.
+	 * Do this under a lock to avoid race condition.
+ 	 */
+	if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked))
+		{
+		CRYPTO_w_lock(CRYPTO_LOCK_X509_CRL);
+		sk_X509_REVOKED_sort(crl->crl->revoked);
+		CRYPTO_w_unlock(CRYPTO_LOCK_X509_CRL);
+		}
 	idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
 	/* If found assume revoked: want something cleverer than
 	 * this to handle entry extensions in V2 CRLs.
diff --git a/util/mkstack.pl b/util/mkstack.pl
index be2cb4f1e7..2a968f395f 100755
--- a/util/mkstack.pl
+++ b/util/mkstack.pl
@@ -85,6 +85,7 @@ while(<IN>) {
 #define sk_${type_thing}_shift(st) SKM_sk_shift($type_thing, (st))
 #define sk_${type_thing}_pop(st) SKM_sk_pop($type_thing, (st))
 #define sk_${type_thing}_sort(st) SKM_sk_sort($type_thing, (st))
+#define sk_${type_thing}_is_sorted(st) SKM_sk_is_sorted($type_thing, (st))
 EOF
 	}
 	foreach $type_thing (sort @asn1setlst) {
-- 
2.40.0