Parse a CA store PEM through a NUL-terminated copy on Mbed TLS

tls::create_ca_store() on Mbed TLS parsed the caller's buffer with one
byte more than its length, so it read past the end of the buffer, and
when that byte was not a NUL the PEM was not recognized and the call
returned NULL. Parse a NUL-terminated copy instead, as load_ca_pem()
does. DER input still parses, since its own length ends it.
This commit is contained in:
yhirose committed 2026-10-21 23:28:19 -04:00
1 parent 3599533c24
commit 3b8b9cf9d5
2 files changed
+22 -12

No files matched your search

+11 -12
View File
@@ -21986,24 +21986,23 @@ inline ca_store_t create_ca_store(const char *pem, size_t len) {
if (!detail::ensure_mbedtls_psa_crypto()) { return nullptr; }
#endif
if (!pem) { return nullptr; }
// mbedtls_x509_crt_parse expects null-terminated PEM
std::string pem_str(pem, len);
auto *ca_chain = new (std::nothrow) mbedtls_x509_crt;
if (!ca_chain) { return nullptr; }
mbedtls_x509_crt_init(ca_chain);
// mbedtls_x509_crt_parse expects null-terminated PEM
int ret = mbedtls_x509_crt_parse(ca_chain,
reinterpret_cast<const unsigned char *>(pem),
len + 1); // +1 for null terminator
auto ret = mbedtls_x509_crt_parse(
ca_chain, reinterpret_cast<const unsigned char *>(pem_str.c_str()),
pem_str.size() + 1);
if (ret != 0) {
// Try without +1 in case PEM is already null-terminated
ret = mbedtls_x509_crt_parse(
ca_chain, reinterpret_cast<const unsigned char *>(pem), len);
if (ret != 0) {
mbedtls_x509_crt_free(ca_chain);
delete ca_chain;
return nullptr;
}
mbedtls_x509_crt_free(ca_chain);
delete ca_chain;
return nullptr;
}
return static_cast<ca_store_t>(ca_chain);
+11
View File
@@ -18304,6 +18304,17 @@ TEST(SSLClientTest, EmptyCustomCaKeepsSystemCasOut) {
}
#endif
// A PEM given to create_ca_store() needs no NUL after it
TEST(SSLClientTest, CreateCaStoreFromPemWithoutNul) {
std::string pem;
read_file(SERVER_CERT2_FILE, pem);
auto buf = pem + "X";
auto store = tls::create_ca_store(buf.data(), pem.size());
EXPECT_TRUE(store != nullptr);
SSLClient cli("localhost");
cli.set_ca_cert_store(store);
}
// enable_system_ca(false) prevents system CA loading entirely
TEST(SSLClientTest, DisableSystemCa_Online) {
SSLClient cli("google.com");