Ver código fonte

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.
yhirose 1 dia atrás
pai
commit
3b8b9cf9d5
2 arquivos alterados com 22 adições e 12 exclusões
  1. 11 12
      httplib.h
  2. 11 0
      test/test.cc

+ 11 - 12
httplib.h

@@ -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 - 0
test/test.cc

@@ -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");