Skip to content

Commit bdd75d0

Browse files
bnoordhuistargos
authored andcommitted
tls: expose built-in root certificates
Fixes: #25824 PR-URL: #26415 Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Rich Trott <[email protected]> Reviewed-By: Ron Korving <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: Vse Mozhet Byt <[email protected]>
1 parent a8a1186 commit bdd75d0

File tree

6 files changed

+225
-143
lines changed

6 files changed

+225
-143
lines changed

doc/api/tls.md

+13
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,7 @@ changes:
13841384
provided.
13851385
For PEM encoded certificates, supported types are "TRUSTED CERTIFICATE",
13861386
"X509 CERTIFICATE", and "CERTIFICATE".
1387+
See also [`tls.rootCertificates`].
13871388
* `cert` {string|string[]|Buffer|Buffer[]} Cert chains in PEM format. One cert
13881389
chain should be provided per private key. Each cert chain should consist of
13891390
the PEM formatted certificate for a provided private `key`, followed by the
@@ -1599,6 +1600,17 @@ TLSv1.2 and below.
15991600
console.log(tls.getCiphers()); // ['aes128-gcm-sha256', 'aes128-sha', ...]
16001601
```
16011602

1603+
## tls.rootCertificates
1604+
<!-- YAML
1605+
added: REPLACEME
1606+
-->
1607+
1608+
* {string[]}
1609+
1610+
An immutable array of strings representing the root certificates (in PEM format)
1611+
used for verifying peer certificates. This is the default value of the `ca`
1612+
option to [`tls.createSecureContext()`].
1613+
16021614
## tls.DEFAULT_ECDH_CURVE
16031615
<!-- YAML
16041616
added: v0.11.13
@@ -1784,6 +1796,7 @@ where `secureSocket` has the same API as `pair.cleartext`.
17841796
[`tls.createSecurePair()`]: #tls_tls_createsecurepair_context_isserver_requestcert_rejectunauthorized_options
17851797
[`tls.createServer()`]: #tls_tls_createserver_options_secureconnectionlistener
17861798
[`tls.getCiphers()`]: #tls_tls_getciphers
1799+
[`tls.rootCertificates`]: #tls_tls_rootcertificates
17871800
[Chrome's 'modern cryptography' setting]: https://www.chromium.org/Home/chromium-security/education/tls#TOC-Cipher-Suites
17881801
[DHE]: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
17891802
[ECDHE]: https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman

lib/tls.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
'use strict';
2323

24+
const { Object } = primordials;
25+
2426
const {
2527
ERR_TLS_CERT_ALTNAME_INVALID,
2628
ERR_OUT_OF_RANGE
@@ -33,7 +35,7 @@ const { isArrayBufferView } = require('internal/util/types');
3335
const net = require('net');
3436
const { getOptionValue } = require('internal/options');
3537
const url = require('url');
36-
const binding = internalBinding('crypto');
38+
const { getRootCertificates, getSSLCiphers } = internalBinding('crypto');
3739
const { Buffer } = require('buffer');
3840
const EventEmitter = require('events');
3941
const { URL } = require('internal/url');
@@ -76,9 +78,25 @@ else
7678

7779

7880
exports.getCiphers = internalUtil.cachedResult(
79-
() => internalUtil.filterDuplicateStrings(binding.getSSLCiphers(), true)
81+
() => internalUtil.filterDuplicateStrings(getSSLCiphers(), true)
8082
);
8183

84+
let rootCertificates;
85+
86+
function cacheRootCertificates() {
87+
rootCertificates = Object.freeze(getRootCertificates());
88+
}
89+
90+
Object.defineProperty(exports, 'rootCertificates', {
91+
configurable: false,
92+
enumerable: true,
93+
get: () => {
94+
// Out-of-line caching to promote inlining the getter.
95+
if (!rootCertificates) cacheRootCertificates();
96+
return rootCertificates;
97+
},
98+
});
99+
82100
// Convert protocols array into valid OpenSSL protocols list
83101
// ("\x06spdy/2\x08http/1.1\x08http/1.0")
84102
function convertProtocols(protocols) {

src/node_crypto.cc

+20
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,24 @@ static X509_STORE* NewRootCertStore() {
944944
}
945945

946946

947+
void GetRootCertificates(const FunctionCallbackInfo<Value>& args) {
948+
Environment* env = Environment::GetCurrent(args);
949+
Local<Array> result = Array::New(env->isolate(), arraysize(root_certs));
950+
951+
for (size_t i = 0; i < arraysize(root_certs); i++) {
952+
Local<Value> value;
953+
if (!String::NewFromOneByte(env->isolate(),
954+
reinterpret_cast<const uint8_t*>(root_certs[i]),
955+
NewStringType::kNormal).ToLocal(&value) ||
956+
!result->Set(env->context(), i, value).FromMaybe(false)) {
957+
return;
958+
}
959+
}
960+
961+
args.GetReturnValue().Set(result);
962+
}
963+
964+
947965
void SecureContext::AddCACert(const FunctionCallbackInfo<Value>& args) {
948966
Environment* env = Environment::GetCurrent(args);
949967

@@ -6870,6 +6888,8 @@ void Initialize(Local<Object> target,
68706888
env->SetMethodNoSideEffect(target, "certVerifySpkac", VerifySpkac);
68716889
env->SetMethodNoSideEffect(target, "certExportPublicKey", ExportPublicKey);
68726890
env->SetMethodNoSideEffect(target, "certExportChallenge", ExportChallenge);
6891+
env->SetMethodNoSideEffect(target, "getRootCertificates",
6892+
GetRootCertificates);
68736893
// Exposed for testing purposes only.
68746894
env->SetMethodNoSideEffect(target, "isExtraRootCertsFileLoaded",
68756895
IsExtraRootCertsFileLoaded);

0 commit comments

Comments
 (0)