Skip to content

Commit dc5adc0

Browse files
committed
Fix wolfSSL issues
1 parent b8ef6b9 commit dc5adc0

File tree

2 files changed

+70
-26
lines changed

2 files changed

+70
-26
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ cpp-httplib supports multiple TLS backends through an abstraction layer:
7575
> [!NOTE]
7676
> wolfSSL must be built with OpenSSL compatibility layer enabled (`--enable-opensslall`). wolfSSL 5.x is supported.
7777
78+
> [!NOTE]
79+
> **Mbed TLS / wolfSSL limitation:** `get_ca_certs()` and `get_ca_names()` only reflect CA certificates loaded via `load_ca_cert_store()` or `load_ca_cert_store(pem, size)`. Certificates loaded through `set_ca_cert_path()` or system certificates (`load_system_certs`) are not enumerable with these backends.
80+
7881
> [!TIP]
7982
> For macOS: cpp-httplib can use system certs with `CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN`. `CoreFoundation` and `Security` should be linked with `-framework`.
8083

httplib.h

Lines changed: 67 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -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

1913719144
inline 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

1915319158
inline 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

1915719162
inline 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

1917319173
inline 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

1918219197
inline 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

Comments
 (0)