Add a test for accessing an X509_STORE from multiple threads

Check we don't have any threading issues when accessing an X509_STORE
simultaneously

Reviewed-by: Saša Nedvědický <sashan@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/28198)
This commit is contained in:
Matt Caswell 2025-08-19 08:38:07 +01:00 committed by Tomas Mraz
parent 08951fb273
commit 994774b4ca
3 changed files with 86 additions and 1 deletions

View File

@ -0,0 +1,3 @@
#The top level .gitignore ignores certificate files with the .0 extension
#But we actually want them in this directory, so we override the top level rule
!*.0

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDFjCCAf6gAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
IENBMCAXDTIwMTIxMjIwMTEzN1oYDzIxMjAxMjEzMjAxMTM3WjASMRAwDgYDVQQD
DAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4eYA9Qa8
oEY4eQ8/HnEZE20C3yubdmv8rLAh7daRCEI7pWM17FJboKJKxdYAlAOXWj25ZyjS
feMhXKTtxjyNjoTRnVTDPdl0opZ2Z3H5xhpQd7P9eO5b4OOMiSPCmiLsPtQ3ngfN
wCtVERc6NEIcaQ06GLDtFZRexv2eh8Yc55QaksBfBcFzQ+UD3gmRySTO2I6Lfi7g
MUjRhipqVSZ66As2Tpex4KTJ2lxpSwOACFaDox+yKrjBTP7FsU3UwAGq7b7OJb3u
aa32B81uK6GJVPVo65gJ7clgZsszYkoDsGjWDqtfwTVVfv1G7rrr3Laio+2Ff3ff
tWgiQ35mJCOvxQIDAQABo3UwczAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB
BjAdBgNVHQ4EFgQUjvUlrx6ba4Q9fICayVOcTXL3o1IwHwYDVR0jBBgwFoAUjvUl
rx6ba4Q9fICayVOcTXL3o1IwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcN
AQELBQADggEBABWUjaqtkdRDhVAJZTxkJVgohjRrBwp86Y0JZWdCDua/sErmEaGu
nQVxWWFWIgu6sb8tyQo3/7dBIQl3Rpij9bsgKhToO1OzoG3Oi3d0+zRDHfY6xNrj
TUE00FeLHGNWsgZSIvu99DrGApT/+uPdWfJgMu5szillqW+4hcCUPLjG9ekVNt1s
KhdEklo6PrP6eMbm6s22EIVUxqGE6xxAmrvyhlY1zJH9BJ23Ps+xabjG6OeMRZzT
0F/fU7XIFieSO7rqUcjgo1eYc3ghsDxNUJ6TPBgv5z4SPnstoOBj59rjpJ7Qkpyd
L17VfEadezat37Cpeha7vGDduCsyMfN4kiw=
-----END CERTIFICATE-----

View File

@ -49,6 +49,7 @@
static int do_fips = 0; static int do_fips = 0;
static char *privkey; static char *privkey;
static char *storedir;
static char *config_file = NULL; static char *config_file = NULL;
static int multidefault_run = 0; static int multidefault_run = 0;
@ -1141,7 +1142,7 @@ static int test_multi_default(void)
multidefault_run = 1; multidefault_run = 1;
return thread_run_test(&thread_multi_simple_fetch, return thread_run_test(&thread_multi_simple_fetch,
2, &thread_multi_simple_fetch, 0, default_provider); 2, &thread_multi_simple_fetch, 0, NULL);
} }
static int test_multi_load(void) static int test_multi_load(void)
@ -1301,6 +1302,62 @@ static int test_pem_read(void)
&test_pem_read_one, 1, default_provider); &test_pem_read_one, 1, default_provider);
} }
static X509_STORE *store = NULL;
static void test_x509_store_by_subject(void)
{
X509_STORE_CTX *ctx;
X509_OBJECT *obj = NULL;
X509_NAME *name = NULL;
int success = 0;
ctx = X509_STORE_CTX_new();
if (!TEST_ptr(ctx))
goto err;
if (!TEST_true(X509_STORE_CTX_init(ctx, store, NULL, NULL)))
goto err;
name = X509_NAME_new();
if (!TEST_ptr(name))
goto err;
if (!TEST_true(X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
(unsigned char *)"Root CA",
-1, -1, 0)))
goto err;
obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, name);
if (!TEST_ptr(obj))
goto err;
success = 1;
err:
X509_OBJECT_free(obj);
X509_STORE_CTX_free(ctx);
X509_NAME_free(name);
if (!success)
multi_set_success(0);
}
/* Test accessing an X509_STORE from multiple threads */
static int test_x509_store(void)
{
int ret = 0;
store = X509_STORE_new();
if (!TEST_ptr(store))
return 0;
if (!TEST_true(X509_STORE_load_store(store, storedir)))
goto err;
ret = thread_run_test(&test_x509_store_by_subject, MAXIMUM_THREADS,
&test_x509_store_by_subject, 0, NULL);
err:
X509_STORE_free(store);
store = NULL;
return ret;
}
typedef enum OPTION_choice { typedef enum OPTION_choice {
OPT_ERR = -1, OPT_ERR = -1,
OPT_EOF = 0, OPT_EOF = 0,
@ -1347,6 +1404,10 @@ int setup_tests(void)
if (!TEST_ptr(privkey)) if (!TEST_ptr(privkey))
return 0; return 0;
storedir = test_mk_file_path(datadir, "store");
if (!TEST_ptr(storedir))
return 0;
if (!TEST_ptr(global_lock = CRYPTO_THREAD_lock_new())) if (!TEST_ptr(global_lock = CRYPTO_THREAD_lock_new()))
return 0; return 0;
@ -1385,12 +1446,14 @@ int setup_tests(void)
ADD_TEST(test_bio_dgram_pair); ADD_TEST(test_bio_dgram_pair);
#endif #endif
ADD_TEST(test_pem_read); ADD_TEST(test_pem_read);
ADD_TEST(test_x509_store);
return 1; return 1;
} }
void cleanup_tests(void) void cleanup_tests(void)
{ {
OPENSSL_free(privkey); OPENSSL_free(privkey);
OPENSSL_free(storedir);
#ifdef TSAN_REQUIRES_LOCKING #ifdef TSAN_REQUIRES_LOCKING
CRYPTO_THREAD_lock_free(tsan_lock); CRYPTO_THREAD_lock_free(tsan_lock);
#endif #endif