Merge pull request #9046 from kareem-wolfssl/zd20038

Allow setting the CA type when loading into cert manager and unloading specific CA types from the cert manager.
This commit is contained in:
JacobBarthelmeh
2025-08-22 14:43:46 -06:00
committed by GitHub
5 changed files with 270 additions and 9 deletions

View File

@@ -6142,6 +6142,49 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
return ret == 0 ? WOLFSSL_SUCCESS : ret;
}
/* Sets the CA with the passed in subject hash
to the provided type. */
int SetCAType(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type)
{
Signer* current;
int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
word32 row;
WOLFSSL_MSG_EX("Setting CA to type %d", type);
if (cm == NULL || hash == NULL ||
type < WOLFSSL_USER_CA || type > WOLFSSL_USER_INTER) {
return ret;
}
row = HashSigner(hash);
if (wc_LockMutex(&cm->caLock) != 0) {
return ret;
}
current = cm->caTable[row];
while (current) {
byte* subjectHash;
#ifndef NO_SKID
subjectHash = current->subjectKeyIdHash;
#else
subjectHash = current->subjectNameHash;
#endif
if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
current->type = (byte)type;
ret = WOLFSSL_SUCCESS;
break;
}
current = current->next;
}
wc_UnLockMutex(&cm->caLock);
WOLFSSL_LEAVE("SetCAType", ret);
return ret;
}
#endif /* !NO_CERTS */

View File

@@ -453,12 +453,12 @@ int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm)
return ret;
}
static int wolfSSL_CertManagerUnloadIntermediateCertsEx(
int wolfSSL_CertManagerUnloadTypeCerts(
WOLFSSL_CERT_MANAGER* cm, byte type)
{
int ret = WOLFSSL_SUCCESS;
WOLFSSL_ENTER("wolfSSL_CertManagerUnloadIntermediateCertsEx");
WOLFSSL_ENTER("wolfSSL_CertManagerUnloadTypeCerts");
/* Validate parameter. */
if (cm == NULL) {
@@ -485,7 +485,7 @@ static int wolfSSL_CertManagerUnloadTempIntermediateCerts(
WOLFSSL_CERT_MANAGER* cm)
{
WOLFSSL_ENTER("wolfSSL_CertManagerUnloadTempIntermediateCerts");
return wolfSSL_CertManagerUnloadIntermediateCertsEx(cm, WOLFSSL_TEMP_CA);
return wolfSSL_CertManagerUnloadTypeCerts(cm, WOLFSSL_TEMP_CA);
}
#endif
@@ -493,7 +493,7 @@ int wolfSSL_CertManagerUnloadIntermediateCerts(
WOLFSSL_CERT_MANAGER* cm)
{
WOLFSSL_ENTER("wolfSSL_CertManagerUnloadIntermediateCerts");
return wolfSSL_CertManagerUnloadIntermediateCertsEx(cm, WOLFSSL_CHAIN_CA);
return wolfSSL_CertManagerUnloadTypeCerts(cm, WOLFSSL_CHAIN_CA);
}
#ifdef WOLFSSL_TRUST_PEER_CERT
@@ -530,7 +530,7 @@ int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm)
}
#endif /* WOLFSSL_TRUST_PEER_CERT */
/* Load certificate/s from buffer with flags.
/* Load certificate/s from buffer with flags and type.
*
* @param [in] cm Certificate manager.
* @param [in] buff Buffer holding encoding of certificate.
@@ -544,17 +544,26 @@ int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm)
* WOLFSSL_LOAD_FLAG_PEM_CA_ONLY,
* WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR, and
* WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE.
* @param [in] type The CA cert's type, used in the internal CA
table. Defaults to WOLFSSL_USER_CA, passing
in WOLFSSL_USER_CA = noop. Recommended to
set to WOLFSSL_USER_INTER when loading
intermediate certs to allow unloading via
wolfSSL_CertManagerUnloadTypeCerts.
* @return WOLFSSL_SUCCESS on success.
* @return WOLFSSL_FATAL_ERROR when cm is NULL or failed create WOLFSSL_CTX.
* @return Other values on loading failure.
*/
int wolfSSL_CertManagerLoadCABuffer_ex(WOLFSSL_CERT_MANAGER* cm,
const unsigned char* buff, long sz, int format, int userChain, word32 flags)
int wolfSSL_CertManagerLoadCABufferType(WOLFSSL_CERT_MANAGER* cm,
const unsigned char* buff, long sz, int format, int userChain,
word32 flags, int type)
{
int ret = WOLFSSL_SUCCESS;
WOLFSSL_CTX* tmp = NULL;
DecodedCert* dCert = NULL;
DerBuffer* der = NULL;
WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer_ex");
WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABufferType");
/* Validate parameters. */
if (cm == NULL) {
@@ -583,10 +592,77 @@ int wolfSSL_CertManagerLoadCABuffer_ex(WOLFSSL_CERT_MANAGER* cm,
/* Clear certificate manager in WOLFSSL_CTX so it won't be freed. */
tmp->cm = NULL;
}
if (ret == WOLFSSL_SUCCESS && type != WOLFSSL_USER_CA) {
dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
DYNAMIC_TYPE_DCERT);
if (dCert == NULL) {
ret = WOLFSSL_FATAL_ERROR;
} else {
if (format == WOLFSSL_FILETYPE_PEM) {
ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
if (!ret) {
/* Replace buffer pointer and size with DER buffer. */
buff = der->buffer;
sz = (long)der->length;
ret = WOLFSSL_SUCCESS;
} else {
WOLFSSL_ERROR(ret);
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == WOLFSSL_SUCCESS) {
XMEMSET(dCert, 0, sizeof(DecodedCert));
wc_InitDecodedCert(dCert, buff,
(word32)sz, cm->heap);
ret = wc_ParseCert(dCert, CERT_TYPE, NO_VERIFY, NULL);
if (ret) {
ret = WOLFSSL_FATAL_ERROR;
} else {
ret = SetCAType(cm, dCert->extSubjKeyId, type);
}
}
if (dCert) {
wc_FreeDecodedCert(dCert);
XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT);
}
if (der) {
FreeDer(&der);
}
}
}
/* Dispose of temporary WOLFSSL_CTX. */
wolfSSL_CTX_free(tmp);
return ret;
}
/* Load certificate/s from buffer with flags.
*
* @param [in] cm Certificate manager.
* @param [in] buff Buffer holding encoding of certificate.
* @param [in] sz Length in bytes of data in buffer.
* @param [in] format Format of encoding. Valid values:
* WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
* @param [in] userChain Indicates buffer holds chain of certificates.
* @param [in] flags Flags to modify behaviour of loading. Valid flags:
* WOLFSSL_LOAD_FLAG_IGNORE_ERR,
* WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY,
* WOLFSSL_LOAD_FLAG_PEM_CA_ONLY,
* WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR, and
* WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE.
* @return WOLFSSL_SUCCESS on success.
* @return WOLFSSL_FATAL_ERROR when cm is NULL or failed create WOLFSSL_CTX.
* @return Other values on loading failure.
*/
int wolfSSL_CertManagerLoadCABuffer_ex(WOLFSSL_CERT_MANAGER* cm,
const unsigned char* buff, long sz, int format, int userChain, word32 flags)
{
return wolfSSL_CertManagerLoadCABufferType(cm, buff, sz, format, userChain,
flags, WOLFSSL_USER_CA);
}
/* Load certificate/s from buffer into table.

View File

@@ -3143,6 +3143,140 @@ static int test_wolfSSL_CertManagerLoadCABuffer_ex(void)
return EXPECT_RESULT();
}
static int test_wolfSSL_CertManagerLoadCABufferType(void)
{
EXPECT_DECLS;
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \
!defined(NO_RSA) && !defined(WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION)
const char* ca_cert = "./certs/ca-cert.pem";
const char* int1_cert = "./certs/intermediate/ca-int-cert.pem";
const char* int2_cert = "./certs/intermediate/ca-int2-cert.pem";
const char* client_cert = "./certs/intermediate/client-int-cert.pem";
byte* ca_cert_buf = NULL;
byte* int1_cert_buf = NULL;
byte* int2_cert_buf = NULL;
byte* client_cert_buf = NULL;
size_t ca_cert_sz = 0;
size_t int1_cert_sz = 0;
size_t int2_cert_sz = 0;
size_t client_cert_sz = 0;
WOLFSSL_CERT_MANAGER* cm = NULL;
ExpectNotNull(cm = wolfSSL_CertManagerNew());
ExpectIntEQ(load_file(ca_cert, &ca_cert_buf, &ca_cert_sz), 0);
ExpectIntEQ(load_file(int1_cert, &int1_cert_buf, &int1_cert_sz), 0);
ExpectIntEQ(load_file(int2_cert, &int2_cert_buf, &int2_cert_sz), 0);
ExpectIntEQ(load_file(client_cert, &client_cert_buf, &client_cert_sz), 0);
ExpectIntNE(wolfSSL_CertManagerLoadCABufferType(cm, ca_cert_buf,
(sword32)ca_cert_sz, WOLFSSL_FILETYPE_PEM, 0,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS, 0), WOLFSSL_SUCCESS);
ExpectIntNE(wolfSSL_CertManagerLoadCABufferType(cm, ca_cert_buf,
(sword32)ca_cert_sz, WOLFSSL_FILETYPE_PEM, 0,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS, 5), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerLoadCABufferType(cm, ca_cert_buf,
(sword32)ca_cert_sz, WOLFSSL_FILETYPE_PEM, 0,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS, WOLFSSL_USER_CA),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, int1_cert_buf,
int1_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerLoadCABufferType(cm, int1_cert_buf,
(sword32)int1_cert_sz, WOLFSSL_FILETYPE_PEM, 0,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS, WOLFSSL_USER_INTER),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, int2_cert_buf,
int2_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerLoadCABufferType(cm, int2_cert_buf,
(sword32)int2_cert_sz, WOLFSSL_FILETYPE_PEM, 0,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS, WOLFSSL_USER_INTER),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, client_cert_buf,
client_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerLoadCABufferType(cm, client_cert_buf,
(sword32)client_cert_sz, WOLFSSL_FILETYPE_PEM, 0,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS, WOLFSSL_USER_INTER),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerUnloadTypeCerts(cm, WOLFSSL_USER_INTER),
WOLFSSL_SUCCESS);
/* Intermediate certs have been unloaded, but CA cert is still
loaded. Expect first level intermediate to verify, rest to fail. */
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, int1_cert_buf,
int1_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, int2_cert_buf,
int2_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, client_cert_buf,
client_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerLoadCABufferType(cm, int1_cert_buf,
(sword32)int1_cert_sz, WOLFSSL_FILETYPE_PEM, 0,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS, WOLFSSL_TEMP_CA),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, int2_cert_buf,
int2_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerLoadCABufferType(cm, int2_cert_buf,
(sword32)int2_cert_sz, WOLFSSL_FILETYPE_PEM, 0,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS, WOLFSSL_CHAIN_CA),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, client_cert_buf,
client_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerLoadCABufferType(cm, client_cert_buf,
(sword32)client_cert_sz, WOLFSSL_FILETYPE_PEM, 0,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS, WOLFSSL_USER_INTER),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerUnloadTypeCerts(cm, WOLFSSL_USER_INTER),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, int1_cert_buf,
int1_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, int2_cert_buf,
int2_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, client_cert_buf,
client_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerUnloadTypeCerts(cm, WOLFSSL_CHAIN_CA),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, int1_cert_buf,
int1_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, int2_cert_buf,
int2_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, client_cert_buf,
client_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerUnloadTypeCerts(cm, WOLFSSL_TEMP_CA),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, int1_cert_buf,
int1_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, int2_cert_buf,
int2_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, client_cert_buf,
client_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerUnloadTypeCerts(cm, WOLFSSL_USER_CA),
WOLFSSL_SUCCESS);
ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, int1_cert_buf,
int1_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, int2_cert_buf,
int2_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, client_cert_buf,
client_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
if (cm)
wolfSSL_CertManagerFree(cm);
if (ca_cert_buf)
free(ca_cert_buf);
if (int1_cert_buf)
free(int1_cert_buf);
if (int2_cert_buf)
free(int2_cert_buf);
if (client_cert_buf)
free(client_cert_buf);
#endif
return EXPECT_RESULT();
}
static int test_wolfSSL_CertManagerGetCerts(void)
{
@@ -52713,6 +52847,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_CertManagerAPI),
TEST_DECL(test_wolfSSL_CertManagerLoadCABuffer),
TEST_DECL(test_wolfSSL_CertManagerLoadCABuffer_ex),
TEST_DECL(test_wolfSSL_CertManagerLoadCABufferType),
TEST_DECL(test_wolfSSL_CertManagerGetCerts),
TEST_DECL(test_wolfSSL_CertManagerSetVerify),
TEST_DECL(test_wolfSSL_CertManagerNameConstraint),

View File

@@ -4280,6 +4280,7 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
WOLFSSL_LOCAL int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s);
WOLFSSL_LOCAL
int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify);
WOLFSSL_LOCAL int SetCAType(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type);
WOLFSSL_LOCAL
int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash);
#ifdef WOLFSSL_TRUST_PEER_CERT

View File

@@ -3719,8 +3719,9 @@ enum {
WOLFSSL_USER_CA = 1, /* user added as trusted */
WOLFSSL_CHAIN_CA = 2, /* added to cache from trusted chain */
WOLFSSL_TEMP_CA = 3 /* Temp intermediate CA, only for use by
WOLFSSL_TEMP_CA = 3, /* Temp intermediate CA, only for use by
* X509_STORE */
WOLFSSL_USER_INTER = 4 /* user added intermediate cert */
};
WOLFSSL_ABI WOLFSSL_API WC_RNG* wolfSSL_GetRNG(WOLFSSL* ssl);
@@ -4202,6 +4203,9 @@ WOLFSSL_API void wolfSSL_CTX_SetPerformTlsRecordProcessingCb(WOLFSSL_CTX* ctx,
WOLFSSL_API int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm,
const char* f, const char* d);
WOLFSSL_API int wolfSSL_CertManagerLoadCABufferType(WOLFSSL_CERT_MANAGER* cm,
const unsigned char* buff, long sz, int format, int userChain,
word32 flags, int type);
WOLFSSL_API int wolfSSL_CertManagerLoadCABuffer_ex(WOLFSSL_CERT_MANAGER* cm,
const unsigned char* buff, long sz, int format, int userChain,
word32 flags);
@@ -4209,6 +4213,8 @@ WOLFSSL_API void wolfSSL_CTX_SetPerformTlsRecordProcessingCb(WOLFSSL_CTX* ctx,
const unsigned char* buff, long sz, int format);
WOLFSSL_API int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm);
WOLFSSL_API int wolfSSL_CertManagerUnloadTypeCerts(
WOLFSSL_CERT_MANAGER* cm, byte type);
WOLFSSL_API int wolfSSL_CertManagerUnloadIntermediateCerts(
WOLFSSL_CERT_MANAGER* cm);
#ifdef WOLFSSL_TRUST_PEER_CERT