Skip to content

Commit 07ea486

Browse files
authored
Merge pull request #10073 from anhu/certmgr
Ensure certificates are getting into cert manager
2 parents 71a8a55 + 7718510 commit 07ea486

6 files changed

Lines changed: 198 additions & 2 deletions

File tree

src/ssl_api_cert.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,17 @@ void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
15361536
ctx->x509_store_pt = str;
15371537
/* Context has ownership and free it with context free. */
15381538
ctx->cm->x509_store_p = ctx->x509_store_pt;
1539+
1540+
#ifdef OPENSSL_EXTRA
1541+
/* Non-self-signed certs (intermediates) added via
1542+
* X509_STORE_add_cert only go into store->certs, not the
1543+
* CertManager. Push them into the CM now so that all
1544+
* verification paths can find them. */
1545+
if (X509StorePushCertsToCM(str) != WOLFSSL_SUCCESS) {
1546+
WOLFSSL_MSG("wolfSSL_CTX_set_cert_store: failed to push some "
1547+
"certs to CertManager");
1548+
}
1549+
#endif
15391550
}
15401551
}
15411552

src/x509_str.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,6 +1690,72 @@ static int X509StoreAddCa(WOLFSSL_X509_STORE* store,
16901690
return result;
16911691
}
16921692

1693+
/* Push certificates from the store's X509 stacks (certs and trusted) into the
1694+
* CertManager, then free and NULL the stacks to signal that this store is now
1695+
* owned by an SSL_CTX.
1696+
*
1697+
* This is needed when an X509_STORE is attached to an SSL_CTX via
1698+
* SSL_CTX_set_cert_store: self-signed CAs are already in the CM (added by
1699+
* X509StoreAddCa during X509_STORE_add_cert), but non-self-signed intermediates
1700+
* are only in store->certs and must be explicitly added to the CM so that all
1701+
* verification paths (including CertManagerVerify) can find them. */
1702+
WOLFSSL_LOCAL int X509StorePushCertsToCM(WOLFSSL_X509_STORE* store)
1703+
{
1704+
int i;
1705+
int num;
1706+
int ret;
1707+
int anyFail = 0;
1708+
WOLFSSL_X509* x509;
1709+
1710+
WOLFSSL_ENTER("X509StorePushCertsToCM");
1711+
1712+
if (store == NULL || store->cm == NULL)
1713+
return WOLFSSL_SUCCESS;
1714+
1715+
/* Push non-self-signed intermediates from store->certs into the CM. */
1716+
if (store->certs != NULL) {
1717+
num = wolfSSL_sk_X509_num(store->certs);
1718+
for (i = 0; i < num; i++) {
1719+
x509 = wolfSSL_sk_X509_value(store->certs, i);
1720+
if (x509 != NULL) {
1721+
ret = X509StoreAddCa(store, x509, WOLFSSL_USER_CA);
1722+
if (ret != WOLFSSL_SUCCESS) {
1723+
WOLFSSL_MSG("X509StorePushCertsToCM: failed to add cert");
1724+
anyFail = 1;
1725+
}
1726+
}
1727+
}
1728+
/* Free and NULL to mark store as CTX-owned. Future add_cert calls
1729+
* will go directly to the CertManager. */
1730+
wolfSSL_sk_X509_pop_free(store->certs, NULL);
1731+
store->certs = NULL;
1732+
}
1733+
1734+
/* Push trusted certs too. Self-signed CAs are typically already in the CM
1735+
* (added during X509_STORE_add_cert), but AddCA handles duplicates. */
1736+
if (store->trusted != NULL) {
1737+
num = wolfSSL_sk_X509_num(store->trusted);
1738+
for (i = 0; i < num; i++) {
1739+
x509 = wolfSSL_sk_X509_value(store->trusted, i);
1740+
if (x509 != NULL) {
1741+
ret = X509StoreAddCa(store, x509, WOLFSSL_USER_CA);
1742+
if (ret != WOLFSSL_SUCCESS) {
1743+
WOLFSSL_MSG("X509StorePushCertsToCM: failed to add "
1744+
"trusted cert");
1745+
anyFail = 1;
1746+
}
1747+
}
1748+
}
1749+
wolfSSL_sk_X509_pop_free(store->trusted, NULL);
1750+
store->trusted = NULL;
1751+
}
1752+
1753+
if (anyFail) {
1754+
return WOLFSSL_FATAL_ERROR;
1755+
}
1756+
return WOLFSSL_SUCCESS;
1757+
}
1758+
16931759
int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509)
16941760
{
16951761
int result = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);

tests/api/test_ossl_x509_str.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,3 +1974,119 @@ int test_X509_STORE_No_SSL_CTX(void)
19741974
#endif
19751975
return EXPECT_RESULT();
19761976
}
1977+
1978+
/* Test that SSL_CTX_set_cert_store propagates certificates (including
1979+
* non-self-signed intermediates) into the CertManager, and that certs
1980+
* added to the store after set_cert_store also reach the CertManager.
1981+
* Regression test for ZD 19760 / GitHub PR #8708.
1982+
*/
1983+
int test_wolfSSL_CTX_set_cert_store(void)
1984+
{
1985+
EXPECT_DECLS;
1986+
#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \
1987+
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
1988+
SSL_CTX* ctx = NULL;
1989+
X509_STORE* store = NULL;
1990+
X509* rootCa = NULL;
1991+
X509* intCa = NULL;
1992+
X509* int2Ca = NULL;
1993+
X509_STORE_CTX* storeCtx = NULL;
1994+
X509* svrCert = NULL;
1995+
1996+
const char caCert[] = "./certs/ca-cert.pem";
1997+
const char intCaCert[] = "./certs/intermediate/ca-int-cert.pem";
1998+
const char int2CaCert[] = "./certs/intermediate/ca-int2-cert.pem";
1999+
const char svrIntCert[] = "./certs/intermediate/server-int-cert.pem";
2000+
2001+
/* --- Part 1: Add certs to store BEFORE set_cert_store ---
2002+
* Non-self-signed intermediates should be pushed into the CertManager
2003+
* when set_cert_store is called. */
2004+
ExpectNotNull(store = X509_STORE_new());
2005+
ExpectNotNull(rootCa = wolfSSL_X509_load_certificate_file(caCert,
2006+
SSL_FILETYPE_PEM));
2007+
ExpectNotNull(intCa = wolfSSL_X509_load_certificate_file(intCaCert,
2008+
SSL_FILETYPE_PEM));
2009+
ExpectNotNull(int2Ca = wolfSSL_X509_load_certificate_file(int2CaCert,
2010+
SSL_FILETYPE_PEM));
2011+
2012+
ExpectIntEQ(X509_STORE_add_cert(store, rootCa), SSL_SUCCESS);
2013+
ExpectIntEQ(X509_STORE_add_cert(store, intCa), SSL_SUCCESS);
2014+
ExpectIntEQ(X509_STORE_add_cert(store, int2Ca), SSL_SUCCESS);
2015+
2016+
ExpectNotNull(ctx = SSL_CTX_new(TLS_client_method()));
2017+
2018+
/* This should push intermediates from store->certs into the CM */
2019+
SSL_CTX_set_cert_store(ctx, store);
2020+
2021+
/* After set_cert_store, store->certs and store->trusted should be NULLed
2022+
* to signal CTX ownership */
2023+
if (EXPECT_SUCCESS()) {
2024+
ExpectNull(store->certs);
2025+
ExpectNull(store->trusted);
2026+
}
2027+
2028+
/* Verify using CertManagerVerify - this only checks the CM, not the
2029+
* store's certs stack, so it proves the intermediates were pushed */
2030+
ExpectIntEQ(wolfSSL_CertManagerVerify(wolfSSL_CTX_GetCertManager(ctx),
2031+
svrIntCert, SSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
2032+
2033+
/* Also verify using X509_verify_cert for completeness */
2034+
ExpectNotNull(svrCert = wolfSSL_X509_load_certificate_file(svrIntCert,
2035+
SSL_FILETYPE_PEM));
2036+
ExpectNotNull(storeCtx = X509_STORE_CTX_new());
2037+
if (EXPECT_SUCCESS()) {
2038+
ExpectIntEQ(X509_STORE_CTX_init(storeCtx,
2039+
SSL_CTX_get_cert_store(ctx), svrCert, NULL), SSL_SUCCESS);
2040+
ExpectIntEQ(X509_verify_cert(storeCtx), SSL_SUCCESS);
2041+
}
2042+
2043+
X509_STORE_CTX_free(storeCtx);
2044+
storeCtx = NULL;
2045+
X509_free(svrCert);
2046+
svrCert = NULL;
2047+
SSL_CTX_free(ctx);
2048+
ctx = NULL;
2049+
/* store is freed by SSL_CTX_free */
2050+
store = NULL;
2051+
2052+
X509_free(rootCa);
2053+
rootCa = NULL;
2054+
X509_free(intCa);
2055+
intCa = NULL;
2056+
X509_free(int2Ca);
2057+
int2Ca = NULL;
2058+
2059+
/* --- Part 2: Add certs to store AFTER set_cert_store ---
2060+
* When store->certs is NULL (CTX-owned), X509_STORE_add_cert should
2061+
* route non-self-signed certs directly to the CertManager. */
2062+
ExpectNotNull(store = X509_STORE_new());
2063+
ExpectNotNull(ctx = SSL_CTX_new(TLS_client_method()));
2064+
2065+
/* Attach empty store first */
2066+
SSL_CTX_set_cert_store(ctx, store);
2067+
2068+
/* Now add certs after ownership transfer */
2069+
ExpectNotNull(rootCa = wolfSSL_X509_load_certificate_file(caCert,
2070+
SSL_FILETYPE_PEM));
2071+
ExpectNotNull(intCa = wolfSSL_X509_load_certificate_file(intCaCert,
2072+
SSL_FILETYPE_PEM));
2073+
ExpectNotNull(int2Ca = wolfSSL_X509_load_certificate_file(int2CaCert,
2074+
SSL_FILETYPE_PEM));
2075+
2076+
ExpectIntEQ(X509_STORE_add_cert(store, rootCa), SSL_SUCCESS);
2077+
ExpectIntEQ(X509_STORE_add_cert(store, intCa), SSL_SUCCESS);
2078+
ExpectIntEQ(X509_STORE_add_cert(store, int2Ca), SSL_SUCCESS);
2079+
2080+
/* Verify that certs added after set_cert_store are in the CM */
2081+
ExpectIntEQ(wolfSSL_CertManagerVerify(wolfSSL_CTX_GetCertManager(ctx),
2082+
svrIntCert, SSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
2083+
2084+
SSL_CTX_free(ctx);
2085+
/* store freed by SSL_CTX_free */
2086+
X509_free(rootCa);
2087+
X509_free(intCa);
2088+
X509_free(int2Ca);
2089+
#endif
2090+
return EXPECT_RESULT();
2091+
}
2092+

tests/api/test_ossl_x509_str.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ int test_wolfSSL_X509_STORE_get1_certs(void);
4242
int test_wolfSSL_X509_STORE_set_get_crl(void);
4343
int test_wolfSSL_X509_CA_num(void);
4444
int test_X509_STORE_No_SSL_CTX(void);
45+
int test_wolfSSL_CTX_set_cert_store(void);
4546

4647
#define TEST_OSSL_X509_STORE_DECLS \
4748
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_CTX_set_time), \
@@ -65,6 +66,7 @@ int test_X509_STORE_No_SSL_CTX(void);
6566
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_get1_certs), \
6667
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_set_get_crl), \
6768
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_CA_num), \
68-
TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_No_SSL_CTX)
69+
TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_No_SSL_CTX), \
70+
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_CTX_set_cert_store)
6971

7072
#endif /* WOLFCRYPT_TEST_OSSL_X509_STR_H */

wolfssl/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2747,6 +2747,7 @@ WOLFSSL_LOCAL void CleanupStoreCtxCallback(WOLFSSL_X509_STORE_CTX* store,
27472747
#endif /* !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH) */
27482748
WOLFSSL_LOCAL int X509StoreLoadCertBuffer(WOLFSSL_X509_STORE *str,
27492749
byte *buf, word32 bufLen, int type);
2750+
WOLFSSL_LOCAL int X509StorePushCertsToCM(WOLFSSL_X509_STORE* store);
27502751
#endif /* !defined NO_CERTS */
27512752

27522753
/* wolfSSL Sock Addr */

wolfssl/wolfcrypt/types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2089,7 +2089,7 @@ WOLFSSL_API word32 CheckRunTimeSettings(void);
20892089
#define WC_MP_TO_RADIX
20902090
#endif
20912091

2092-
#if defined(__GNUC__) && __GNUC__ > 5
2092+
#if defined(__GNUC__) && (__GNUC__ > 5) && !defined(__clang__)
20932093
#define PRAGMA_GCC_DIAG_PUSH _Pragma("GCC diagnostic push")
20942094
#define PRAGMA_GCC(str) _Pragma(str)
20952095
#define PRAGMA_GCC_DIAG_POP _Pragma("GCC diagnostic pop")

0 commit comments

Comments
 (0)