From 61ccea55ac048a9f075e2e4f0f75754ae5be20bb Mon Sep 17 00:00:00 2001 From: Kareem Date: Wed, 30 Jul 2025 16:33:30 -0700 Subject: [PATCH 1/6] Allow setting the CA type when loading into cert manager and unloading specific CA types from the cert manager. --- src/ssl.c | 43 ++++++++++++++++++++++++++++++ src/ssl_certman.c | 65 +++++++++++++++++++++++++++++++++++++++++++--- wolfssl/internal.h | 1 + wolfssl/ssl.h | 8 +++++- 4 files changed, 112 insertions(+), 5 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 766ad47cd..a4015ba29 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -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 = type; + ret = WOLFSSL_SUCCESS; + break; + } + current = current->next; + } + wc_UnLockMutex(&cm->caLock); + + WOLFSSL_LEAVE("SetCAType", ret); + + return ret; +} #endif /* !NO_CERTS */ diff --git a/src/ssl_certman.c b/src/ssl_certman.c index 286831b9d..7a77e432c 100644 --- a/src/ssl_certman.c +++ b/src/ssl_certman.c @@ -453,7 +453,7 @@ int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm) return ret; } -static int wolfSSL_CertManagerUnloadIntermediateCertsEx( +int wolfSSL_CertManagerUnloadIntermediateCertsEx( WOLFSSL_CERT_MANAGER* cm, byte type) { int ret = WOLFSSL_SUCCESS; @@ -544,17 +544,25 @@ 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_CertManagerUnloadIntermediateCertsEx. * @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_CertManagerLoadCABuffer_ex2(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; - WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer_ex"); + WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer_ex2"); /* Validate parameters. */ if (cm == NULL) { @@ -583,10 +591,59 @@ 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), NULL, + DYNAMIC_TYPE_DCERT); + + if (dCert == NULL) { + ret = WOLFSSL_FATAL_ERROR; + } else { + XMEMSET(dCert, 0, sizeof(DecodedCert)); + wc_InitDecodedCert(dCert, buff, + sz, cm->heap); + ret = wc_ParseCert(dCert, CA_TYPE, NO_VERIFY, NULL); + if (ret) { + ret = WOLFSSL_FATAL_ERROR; + } else { + ret = SetCAType(cm, dCert->extSubjKeyId, type); + } + + if (dCert) { + wc_FreeDecodedCert(dCert); + XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT); + } + } + } /* 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_CertManagerLoadCABuffer_ex2(cm, buff, sz, format, userChain, + flags, WOLFSSL_USER_CA); } /* Load certificate/s from buffer into table. diff --git a/wolfssl/internal.h b/wolfssl/internal.h index c5beafa60..59603477b 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -4276,6 +4276,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 diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 44c5f35f2..5cefabb59 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -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_CertManagerLoadCABuffer_ex2(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_CertManagerUnloadIntermediateCertsEx( + WOLFSSL_CERT_MANAGER* cm, byte type); WOLFSSL_API int wolfSSL_CertManagerUnloadIntermediateCerts( WOLFSSL_CERT_MANAGER* cm); #ifdef WOLFSSL_TRUST_PEER_CERT From ab342978d7cc84c7f9743fc03c6d29e57ede5a33 Mon Sep 17 00:00:00 2001 From: Kareem Date: Wed, 30 Jul 2025 16:54:32 -0700 Subject: [PATCH 2/6] Fix implicit conversion warning. --- src/ssl_certman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ssl_certman.c b/src/ssl_certman.c index 7a77e432c..38ef3babd 100644 --- a/src/ssl_certman.c +++ b/src/ssl_certman.c @@ -600,7 +600,7 @@ int wolfSSL_CertManagerLoadCABuffer_ex2(WOLFSSL_CERT_MANAGER* cm, } else { XMEMSET(dCert, 0, sizeof(DecodedCert)); wc_InitDecodedCert(dCert, buff, - sz, cm->heap); + (word32)sz, cm->heap); ret = wc_ParseCert(dCert, CA_TYPE, NO_VERIFY, NULL); if (ret) { ret = WOLFSSL_FATAL_ERROR; From a652b733e47cee7a3e2dea7a14070f0723f398ec Mon Sep 17 00:00:00 2001 From: Kareem Date: Wed, 30 Jul 2025 17:37:32 -0700 Subject: [PATCH 3/6] Fix conversion warning. --- src/ssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ssl.c b/src/ssl.c index a4015ba29..744bdfb26 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -6173,7 +6173,7 @@ int SetCAType(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type) #endif if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { - current->type = type; + current->type = (byte)type; ret = WOLFSSL_SUCCESS; break; } From 3bcbbd292410af2f826d06bd8d318d852d96f836 Mon Sep 17 00:00:00 2001 From: Kareem Date: Mon, 4 Aug 2025 16:37:41 -0700 Subject: [PATCH 4/6] Fix issue with loading PEM certs. Address code review feedback. Add tests. --- src/ssl_certman.c | 59 +++++++++++++------- tests/api.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++ wolfssl/ssl.h | 4 +- 3 files changed, 175 insertions(+), 21 deletions(-) diff --git a/src/ssl_certman.c b/src/ssl_certman.c index 38ef3babd..f6534663c 100644 --- a/src/ssl_certman.c +++ b/src/ssl_certman.c @@ -453,12 +453,12 @@ int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm) return ret; } -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. @@ -549,20 +549,21 @@ int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm) in WOLFSSL_USER_CA = noop. Recommended to set to WOLFSSL_USER_INTER when loading intermediate certs to allow unloading via - wolfSSL_CertManagerUnloadIntermediateCertsEx. + 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_ex2(WOLFSSL_CERT_MANAGER* cm, +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_ex2"); + WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABufferType"); /* Validate parameters. */ if (cm == NULL) { @@ -592,25 +593,45 @@ int wolfSSL_CertManagerLoadCABuffer_ex2(WOLFSSL_CERT_MANAGER* cm, tmp->cm = NULL; } if (ret == WOLFSSL_SUCCESS && type != WOLFSSL_USER_CA) { - dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap, DYNAMIC_TYPE_DCERT); if (dCert == NULL) { ret = WOLFSSL_FATAL_ERROR; } else { - XMEMSET(dCert, 0, sizeof(DecodedCert)); - wc_InitDecodedCert(dCert, buff, - (word32)sz, cm->heap); - ret = wc_ParseCert(dCert, CA_TYPE, NO_VERIFY, NULL); - if (ret) { - ret = WOLFSSL_FATAL_ERROR; - } else { - ret = SetCAType(cm, dCert->extSubjKeyId, type); + 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); + + if (der != NULL) { + FreeDer(&der); + } + + 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, NULL, DYNAMIC_TYPE_DCERT); + XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT); } } } @@ -642,7 +663,7 @@ int wolfSSL_CertManagerLoadCABuffer_ex2(WOLFSSL_CERT_MANAGER* cm, int wolfSSL_CertManagerLoadCABuffer_ex(WOLFSSL_CERT_MANAGER* cm, const unsigned char* buff, long sz, int format, int userChain, word32 flags) { - return wolfSSL_CertManagerLoadCABuffer_ex2(cm, buff, sz, format, userChain, + return wolfSSL_CertManagerLoadCABufferType(cm, buff, sz, format, userChain, flags, WOLFSSL_USER_CA); } diff --git a/tests/api.c b/tests/api.c index 295c671a1..8de54fd19 100644 --- a/tests/api.c +++ b/tests/api.c @@ -3143,6 +3143,138 @@ 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) + 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; + + 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); + + 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) { @@ -52866,6 +52998,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), diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 5cefabb59..5a66c6773 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -4203,7 +4203,7 @@ 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_CertManagerLoadCABuffer_ex2(WOLFSSL_CERT_MANAGER* cm, + 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, @@ -4213,7 +4213,7 @@ 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_CertManagerUnloadIntermediateCertsEx( + WOLFSSL_API int wolfSSL_CertManagerUnloadTypeCerts( WOLFSSL_CERT_MANAGER* cm, byte type); WOLFSSL_API int wolfSSL_CertManagerUnloadIntermediateCerts( WOLFSSL_CERT_MANAGER* cm); From cb3f7de3f718183f244f8b7b549c50b7970ee78f Mon Sep 17 00:00:00 2001 From: Kareem Date: Mon, 4 Aug 2025 17:10:35 -0700 Subject: [PATCH 5/6] Fix issues found by CI/CD tests. --- src/ssl_certman.c | 8 +++----- tests/api.c | 8 +++++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ssl_certman.c b/src/ssl_certman.c index f6534663c..16f93cecc 100644 --- a/src/ssl_certman.c +++ b/src/ssl_certman.c @@ -608,11 +608,6 @@ int wolfSSL_CertManagerLoadCABufferType(WOLFSSL_CERT_MANAGER* cm, ret = WOLFSSL_SUCCESS; } else { WOLFSSL_ERROR(ret); - - if (der != NULL) { - FreeDer(&der); - } - ret = WOLFSSL_FATAL_ERROR; } } @@ -633,6 +628,9 @@ int wolfSSL_CertManagerLoadCABufferType(WOLFSSL_CERT_MANAGER* cm, wc_FreeDecodedCert(dCert); XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT); } + if (der) { + FreeDer(&der); + } } } diff --git a/tests/api.c b/tests/api.c index 8de54fd19..5bc6422e6 100644 --- a/tests/api.c +++ b/tests/api.c @@ -3146,7 +3146,8 @@ static int test_wolfSSL_CertManagerLoadCABuffer_ex(void) static int test_wolfSSL_CertManagerLoadCABufferType(void) { EXPECT_DECLS; -#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ + !defined(NO_RSA) 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"; @@ -3159,7 +3160,7 @@ static int test_wolfSSL_CertManagerLoadCABufferType(void) size_t int1_cert_sz = 0; size_t int2_cert_sz = 0; size_t client_cert_sz = 0; - WOLFSSL_CERT_MANAGER* cm; + WOLFSSL_CERT_MANAGER* cm = NULL; ExpectNotNull(cm = wolfSSL_CertManagerNew()); ExpectIntEQ(load_file(ca_cert, &ca_cert_buf, &ca_cert_sz), 0); @@ -3262,7 +3263,8 @@ static int test_wolfSSL_CertManagerLoadCABufferType(void) ExpectIntNE(wolfSSL_CertManagerVerifyBuffer(cm, client_cert_buf, client_cert_sz, WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); - wolfSSL_CertManagerFree(cm); + if (cm) + wolfSSL_CertManagerFree(cm); if (ca_cert_buf) free(ca_cert_buf); if (int1_cert_buf) From c535e281c6b761dac610b18e2883ca3ff288b156 Mon Sep 17 00:00:00 2001 From: Kareem Date: Thu, 14 Aug 2025 11:34:04 -0700 Subject: [PATCH 6/6] Skip unit test when using Apple native cert validation. --- tests/api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/api.c b/tests/api.c index 5bc6422e6..30bc607df 100644 --- a/tests/api.c +++ b/tests/api.c @@ -3147,7 +3147,7 @@ static int test_wolfSSL_CertManagerLoadCABufferType(void) { EXPECT_DECLS; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ - !defined(NO_RSA) + !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";