Skip to content

Commit 6b87eab

Browse files
committed
src: modify SecureContext::SetCACert to not use root_certs
1 parent 8253290 commit 6b87eab

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const common = require('../common.js');
2+
const fixtures = require('../../test/common/fixtures');
3+
const tls = require('tls');
4+
5+
const bench = common.createBenchmark(main, {
6+
n: [1, 5],
7+
ca: [0, 1],
8+
});
9+
10+
function main(conf) {
11+
const n = conf.n;
12+
13+
const options = {
14+
key: fixtures.readKey('rsa_private.pem'),
15+
cert: fixtures.readKey('rsa_cert.crt'),
16+
ca: conf.ca === 1 ? [fixtures.readKey('rsa_ca.crt')] : undefined,
17+
};
18+
19+
bench.start();
20+
tls.createSecureContext(options);
21+
bench.end(n);
22+
}

src/crypto/crypto_context.cc

+59-3
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,45 @@ X509_STORE* GetOrCreateRootCertStore() {
6060
return store;
6161
}
6262

63+
// copies an X509_STORE object, including the certificates and crls it contains.
64+
X509_STORE* CopyX509Store(X509_STORE* src) {
65+
// create a new X509_STORE
66+
X509_STORE* dest = X509_STORE_new();
67+
68+
if (*system_cert_path != '\0') {
69+
ERR_set_mark();
70+
X509_STORE_load_locations(dest, system_cert_path, nullptr);
71+
ERR_pop_to_mark();
72+
}
73+
74+
if (per_process::cli_options->ssl_openssl_cert_store) {
75+
CHECK_EQ(1, X509_STORE_set_default_paths(dest));
76+
}
77+
78+
// copy flags
79+
X509_STORE_set1_param(dest, X509_STORE_get0_param(src));
80+
81+
// get the certificates and crls from the source store
82+
STACK_OF(X509_OBJECT)* objs = X509_STORE_get0_objects(src);
83+
for (int i = 0; i < sk_X509_OBJECT_num(objs); i++) {
84+
X509_OBJECT* obj = sk_X509_OBJECT_value(objs, i);
85+
int type = X509_OBJECT_get_type(obj);
86+
if (type == X509_LU_X509) {
87+
// copy certs
88+
X509* x509 = X509_OBJECT_get0_X509(obj);
89+
X509_up_ref(x509);
90+
X509_STORE_add_cert(dest, x509);
91+
} else if (type == X509_LU_CRL) {
92+
// copy crls
93+
X509_CRL* crl = X509_OBJECT_get0_X509_CRL(obj);
94+
X509_CRL_up_ref(crl);
95+
X509_STORE_add_crl(dest, crl);
96+
}
97+
}
98+
99+
return dest;
100+
}
101+
63102
// Takes a string or buffer and loads it into a BIO.
64103
// Caller responsible for BIO_free_all-ing the returned object.
65104
BIOPointer LoadBIO(Environment* env, Local<Value> v) {
@@ -785,9 +824,26 @@ void SecureContext::SetCACert(const BIOPointer& bio) {
785824
if (!bio) return;
786825
while (X509Pointer x509 = X509Pointer(PEM_read_bio_X509_AUX(
787826
bio.get(), nullptr, NoPasswordCallback, nullptr))) {
788-
CHECK_EQ(1,
789-
X509_STORE_add_cert(GetCertStoreOwnedByThisSecureContext(),
790-
x509.get()));
827+
// Avoid calling GetCertStoreOwnedByThisSecureContext() in SetCACert method
828+
// because it will create X509_STORE based on root_certs (more than 150) and
829+
// is very slow
830+
831+
if (!own_cert_store_cache_) {
832+
// Is cert_store here a globally shared root cert store? There are two
833+
// possibilities
834+
// 1. AddRootCerts has been called, and cert_store is a globally shared
835+
// root cert store
836+
// 2. AddRootCerts has not been called, and cert_store is the default cert
837+
// store of OpenSSL Directly creating a new store is not a correct
838+
// implementation of copy on write
839+
SSL_CTX_set_cert_store(ctx_.get(),
840+
own_cert_store_cache_ = CopyX509Store(
841+
SSL_CTX_get_cert_store(ctx_.get())));
842+
// No need to call X509_STORE_free manually, SSL_CTX_set_cert_store will
843+
// take over the ownership of X509_STORE
844+
}
845+
846+
CHECK_EQ(1, X509_STORE_add_cert(own_cert_store_cache_, x509.get()));
791847
CHECK_EQ(1, SSL_CTX_add_client_CA(ctx_.get(), x509.get()));
792848
}
793849
}

0 commit comments

Comments
 (0)