crypto: load system CA certificates off thread · nodejs/node@89fe635

3 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -814,6 +814,23 @@ static std::vector<X509*>& GetSystemStoreCACertificates() {

814814

return system_store_certs;

815815

}

816816
817+

static void LoadSystemCACertificates(void* data) {

818+

GetSystemStoreCACertificates();

819+

}

820+
821+

static uv_thread_t system_ca_thread;

822+

static bool system_ca_thread_started = false;

823+

int LoadSystemCACertificatesOffThread() {

824+

// This is only run once during the initialization of the process, so

825+

// it is safe to use a static thread here.

826+

int r =

827+

uv_thread_create(&system_ca_thread, LoadSystemCACertificates, nullptr);

828+

if (r == 0) {

829+

system_ca_thread_started = true;

830+

}

831+

return r;

832+

}

833+
817834

static std::vector<X509*> InitializeExtraCACertificates() {

818835

std::vector<X509*> extra_certs;

819836

unsigned long err = LoadCertsFromFile( // NOLINT(runtime/int)

@@ -925,6 +942,10 @@ void CleanupCachedRootCertificates() {

925942

X509_free(cert);

926943

}

927944

}

945+

if (system_ca_thread_started) {

946+

uv_thread_join(&system_ca_thread);

947+

system_ca_thread_started = false;

948+

}

928949

}

929950
930951

void GetBundledRootCertificates(const FunctionCallbackInfo<Value>& args) {

Original file line numberDiff line numberDiff line change

@@ -45,6 +45,7 @@ void InitCryptoOnce();

4545

void InitCrypto(v8::Local<v8::Object> target);

4646
4747

extern void UseExtraCaCerts(std::string_view file);

48+

extern int LoadSystemCACertificatesOffThread();

4849

void CleanupCachedRootCertificates();

4950
5051

int PasswordCallback(char* buf, int size, int rwflag, void* u);

Original file line numberDiff line numberDiff line change

@@ -1208,6 +1208,20 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args,

12081208

return result;

12091209

}

12101210
1211+

if (per_process::cli_options->use_system_ca) {

1212+

// Load the system CA certificates eagerly off the main thread to avoid

1213+

// blocking the main thread when the first TLS connection is made. We

1214+

// don't need to wait for the thread to finish with code here, as

1215+

// GetSystemStoreCACertificates() has a function-local static and any

1216+

// actual user of it will wait for that to complete initialization.

1217+

int r = crypto::LoadSystemCACertificatesOffThread();

1218+

if (r != 0) {

1219+

FPrintF(

1220+

stderr,

1221+

"Warning: Failed to load system CA certificates off thread: %s\n",

1222+

uv_strerror(r));

1223+

}

1224+

}

12111225

// Ensure CSPRNG is properly seeded.

12121226

CHECK(ncrypto::CSPRNG(nullptr, 0));

12131227