@@ -3071,6 +3071,7 @@ struct WolfSSLContext {
30713071 bool is_server = false;
30723072 bool verify_client = false;
30733073 bool has_verify_callback = false;
3074+ std::string ca_pem_data_; // accumulated PEM for get_ca_names/get_ca_certs
30743075
30753076 WolfSSLContext();
30763077 ~WolfSSLContext();
@@ -3079,6 +3080,11 @@ struct WolfSSLContext {
30793080 WolfSSLContext &operator=(const WolfSSLContext &) = delete;
30803081};
30813082
3083+ // CA store for wolfSSL: holds raw PEM bytes to allow reloading into any ctx
3084+ struct WolfSSLCAStore {
3085+ std::string pem_data;
3086+ };
3087+
30823088} // namespace impl
30833089} // namespace tls
30843090#endif
@@ -18394,6 +18400,7 @@ inline bool load_ca_pem(ctx_t ctx, const char *pem, size_t len) {
1839418400 static_cast<uint64_t>(wolfSSL_ERR_peek_last_error());
1839518401 return false;
1839618402 }
18403+ wctx->ca_pem_data_.append(pem, len);
1839718404 return true;
1839818405}
1839918406
@@ -19135,55 +19142,89 @@ inline std::string error_string(uint64_t code) {
1913519142}
1913619143
1913719144inline ca_store_t create_ca_store(const char *pem, size_t len) {
19138- // Create a temporary CTX to hold the CA certificates
19145+ if (!pem || len == 0) { return nullptr; }
19146+ // Validate by attempting to load into a temporary ctx
1913919147 WOLFSSL_CTX *tmp_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
1914019148 if (!tmp_ctx) { return nullptr; }
19141-
1914219149 int ret = wolfSSL_CTX_load_verify_buffer(
1914319150 tmp_ctx, reinterpret_cast<const unsigned char *>(pem),
1914419151 static_cast<long>(len), SSL_FILETYPE_PEM);
19145- if (ret != SSL_SUCCESS) {
19146- wolfSSL_CTX_free(tmp_ctx);
19147- return nullptr;
19148- }
19149-
19150- return static_cast<ca_store_t>(tmp_ctx);
19152+ wolfSSL_CTX_free(tmp_ctx);
19153+ if (ret != SSL_SUCCESS) { return nullptr; }
19154+ return static_cast<ca_store_t>(
19155+ new impl::WolfSSLCAStore{std::string(pem, len)});
1915119156}
1915219157
1915319158inline void free_ca_store(ca_store_t store) {
19154- if (store) { wolfSSL_CTX_free( static_cast<WOLFSSL_CTX *>(store)); }
19159+ delete static_cast<impl::WolfSSLCAStore *>(store);
1915519160}
1915619161
1915719162inline bool set_ca_store(ctx_t ctx, ca_store_t store) {
1915819163 if (!ctx || !store) { return false; }
1915919164 auto *wctx = static_cast<impl::WolfSSLContext *>(ctx);
19160- auto *store_ctx = static_cast<WOLFSSL_CTX *>(store);
19161-
19162- // Get the cert manager from the store context and load into our context
19163- WOLFSSL_CERT_MANAGER *cm = wolfSSL_CTX_GetCertManager(store_ctx);
19164- if (!cm) { return false; }
19165-
19166- // We need to re-load the certs - wolfSSL doesn't support direct CM sharing
19167- // For now, this is a simplified implementation
19168- (void)wctx;
19169- (void)cm;
19170- return false; // TODO: Implement proper CA store sharing for wolfSSL
19165+ auto *ca = static_cast<impl::WolfSSLCAStore *>(store);
19166+ int ret = wolfSSL_CTX_load_verify_buffer(
19167+ wctx->ctx, reinterpret_cast<const unsigned char *>(ca->pem_data.data()),
19168+ static_cast<long>(ca->pem_data.size()), SSL_FILETYPE_PEM);
19169+ if (ret == SSL_SUCCESS) { wctx->ca_pem_data_ += ca->pem_data; }
19170+ return ret == SSL_SUCCESS;
1917119171}
1917219172
1917319173inline size_t get_ca_certs(ctx_t ctx, std::vector<cert_t> &certs) {
1917419174 certs.clear();
1917519175 if (!ctx) { return 0; }
19176- // wolfSSL doesn't provide easy iteration over loaded CA certs
19177- // This would require accessing internal cert manager structures
19178- (void)ctx;
19179- return 0;
19176+ auto *wctx = static_cast<impl::WolfSSLContext *>(ctx);
19177+ if (wctx->ca_pem_data_.empty()) { return 0; }
19178+
19179+ const std::string &pem = wctx->ca_pem_data_;
19180+ const std::string begin_marker = "-----BEGIN CERTIFICATE-----";
19181+ const std::string end_marker = "-----END CERTIFICATE-----";
19182+ size_t pos = 0;
19183+ while ((pos = pem.find(begin_marker, pos)) != std::string::npos) {
19184+ size_t end_pos = pem.find(end_marker, pos);
19185+ if (end_pos == std::string::npos) { break; }
19186+ end_pos += end_marker.size();
19187+ std::string cert_pem = pem.substr(pos, end_pos - pos);
19188+ WOLFSSL_X509 *x509 = wolfSSL_X509_load_certificate_buffer(
19189+ reinterpret_cast<const unsigned char *>(cert_pem.data()),
19190+ static_cast<int>(cert_pem.size()), WOLFSSL_FILETYPE_PEM);
19191+ if (x509) { certs.push_back(static_cast<cert_t>(x509)); }
19192+ pos = end_pos;
19193+ }
19194+ return certs.size();
1918019195}
1918119196
1918219197inline std::vector<std::string> get_ca_names(ctx_t ctx) {
1918319198 std::vector<std::string> names;
1918419199 if (!ctx) { return names; }
19185- // wolfSSL doesn't provide easy iteration over loaded CA cert names
19186- (void)ctx;
19200+ auto *wctx = static_cast<impl::WolfSSLContext *>(ctx);
19201+ if (wctx->ca_pem_data_.empty()) { return names; }
19202+
19203+ const std::string &pem = wctx->ca_pem_data_;
19204+ const std::string begin_marker = "-----BEGIN CERTIFICATE-----";
19205+ const std::string end_marker = "-----END CERTIFICATE-----";
19206+ size_t pos = 0;
19207+ while ((pos = pem.find(begin_marker, pos)) != std::string::npos) {
19208+ size_t end_pos = pem.find(end_marker, pos);
19209+ if (end_pos == std::string::npos) { break; }
19210+ end_pos += end_marker.size();
19211+ std::string cert_pem = pem.substr(pos, end_pos - pos);
19212+ WOLFSSL_X509 *x509 = wolfSSL_X509_load_certificate_buffer(
19213+ reinterpret_cast<const unsigned char *>(cert_pem.data()),
19214+ static_cast<int>(cert_pem.size()), WOLFSSL_FILETYPE_PEM);
19215+ if (x509) {
19216+ WOLFSSL_X509_NAME *subject = wolfSSL_X509_get_subject_name(x509);
19217+ if (subject) {
19218+ char *name_str = wolfSSL_X509_NAME_oneline(subject, nullptr, 0);
19219+ if (name_str) {
19220+ names.push_back(name_str);
19221+ XFREE(name_str, nullptr, DYNAMIC_TYPE_OPENSSL);
19222+ }
19223+ }
19224+ wolfSSL_X509_free(x509);
19225+ }
19226+ pos = end_pos;
19227+ }
1918719228 return names;
1918819229}
1918919230
0 commit comments