Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dc84c18

Browse filesBrowse files
jasnelldanielleadams
authored andcommitted
tls: add ability to get cert/peer cert as X509Certificate object
Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: #37070 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Filip Skokan <panva.ip@gmail.com>
1 parent 13fe17c commit dc84c18
Copy full SHA for dc84c18

File tree

Expand file treeCollapse file tree

9 files changed

+218
-74
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

9 files changed

+218
-74
lines changed
Open diff view settings
Collapse file

‎doc/api/crypto.md‎

Copy file name to clipboardExpand all lines: doc/api/crypto.md
+10Lines changed: 10 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -1804,6 +1804,16 @@ added: v15.6.0
18041804

18051805
The issuer identification included in this certificate.
18061806

1807+
### `x509.issuerCertificate`
1808+
<!-- YAML
1809+
added: REPLACEME
1810+
-->
1811+
1812+
* Type: {X509Certificate}
1813+
1814+
The issuer certificate or `undefined` if the issuer certificate is not
1815+
available.
1816+
18071817
### `x509.keyUsage`
18081818
<!-- YAML
18091819
added: v15.6.0
Collapse file

‎doc/api/tls.md‎

Copy file name to clipboardExpand all lines: doc/api/tls.md
+59-35Lines changed: 59 additions & 35 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,41 @@ added: v0.11.4
904904
Always returns `true`. This may be used to distinguish TLS sockets from regular
905905
`net.Socket` instances.
906906

907+
### `tlsSocket.exportKeyingMaterial(length, label[, context])`
908+
<!-- YAML
909+
added:
910+
- v13.10.0
911+
- v12.17.0
912+
-->
913+
914+
* `length` {number} number of bytes to retrieve from keying material
915+
* `label` {string} an application specific label, typically this will be a
916+
value from the
917+
[IANA Exporter Label Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels).
918+
* `context` {Buffer} Optionally provide a context.
919+
920+
* Returns: {Buffer} requested bytes of the keying material
921+
922+
Keying material is used for validations to prevent different kind of attacks in
923+
network protocols, for example in the specifications of IEEE 802.1X.
924+
925+
Example
926+
927+
```js
928+
const keyingMaterial = tlsSocket.exportKeyingMaterial(
929+
128,
930+
'client finished');
931+
932+
/**
933+
Example return value of keyingMaterial:
934+
<Buffer 76 26 af 99 c5 56 8e 42 09 91 ef 9f 93 cb ad 6c 7b 65 f8 53 f1 d8 d9
935+
12 5a 33 b8 b5 25 df 7b 37 9f e0 e2 4f b8 67 83 a3 2f cd 5d 41 42 4c 91
936+
74 ef 2c ... 78 more bytes>
937+
*/
938+
```
939+
See the OpenSSL [`SSL_export_keying_material`][] documentation for more
940+
information.
941+
907942
### `tlsSocket.getCertificate()`
908943
<!-- YAML
909944
added: v11.2.0
@@ -1113,6 +1148,18 @@ provided by SSL/TLS is not desired or is not enough.
11131148
Corresponds to the `SSL_get_peer_finished` routine in OpenSSL and may be used
11141149
to implement the `tls-unique` channel binding from [RFC 5929][].
11151150

1151+
### `tlsSocket.getPeerX509Certificate()`
1152+
<!-- YAML
1153+
added: REPLACEME
1154+
-->
1155+
1156+
* Returns: {X509Certificate}
1157+
1158+
Returns the peer certificate as an {X509Certificate} object.
1159+
1160+
If there is no peer certificate, or the socket has been destroyed,
1161+
`undefined` will be returned.
1162+
11161163
### `tlsSocket.getProtocol()`
11171164
<!-- YAML
11181165
added: v5.7.0
@@ -1164,41 +1211,6 @@ See
11641211
[SSL_get_shared_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html)
11651212
for more information.
11661213

1167-
### `tlsSocket.exportKeyingMaterial(length, label[, context])`
1168-
<!-- YAML
1169-
added:
1170-
- v13.10.0
1171-
- v12.17.0
1172-
-->
1173-
1174-
* `length` {number} number of bytes to retrieve from keying material
1175-
* `label` {string} an application specific label, typically this will be a
1176-
value from the
1177-
[IANA Exporter Label Registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#exporter-labels).
1178-
* `context` {Buffer} Optionally provide a context.
1179-
1180-
* Returns: {Buffer} requested bytes of the keying material
1181-
1182-
Keying material is used for validations to prevent different kind of attacks in
1183-
network protocols, for example in the specifications of IEEE 802.1X.
1184-
1185-
Example
1186-
1187-
```js
1188-
const keyingMaterial = tlsSocket.exportKeyingMaterial(
1189-
128,
1190-
'client finished');
1191-
1192-
/**
1193-
Example return value of keyingMaterial:
1194-
<Buffer 76 26 af 99 c5 56 8e 42 09 91 ef 9f 93 cb ad 6c 7b 65 f8 53 f1 d8 d9
1195-
12 5a 33 b8 b5 25 df 7b 37 9f e0 e2 4f b8 67 83 a3 2f cd 5d 41 42 4c 91
1196-
74 ef 2c ... 78 more bytes>
1197-
*/
1198-
```
1199-
See the OpenSSL [`SSL_export_keying_material`][] documentation for more
1200-
information.
1201-
12021214
### `tlsSocket.getTLSTicket()`
12031215
<!-- YAML
12041216
added: v0.11.4
@@ -1213,6 +1225,18 @@ It may be useful for debugging.
12131225

12141226
See [Session Resumption][] for more information.
12151227

1228+
### `tlsSocket.getX509Certificate()`
1229+
<!-- YAML
1230+
added: REPLACEME
1231+
-->
1232+
1233+
* Returns: {X509Certificate}
1234+
1235+
Returns the local certificate as an {X509Certificate} object.
1236+
1237+
If there is no local certificate, or the socket has been destroyed,
1238+
`undefined` will be returned.
1239+
12161240
### `tlsSocket.isSessionReused()`
12171241
<!-- YAML
12181242
added: v0.5.6
Collapse file

‎lib/_tls_wrap.js‎

Copy file name to clipboardExpand all lines: lib/_tls_wrap.js
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ const {
9090
validateString,
9191
validateUint32
9292
} = require('internal/validators');
93+
const {
94+
InternalX509Certificate
95+
} = require('internal/crypto/x509');
9396
const traceTls = getOptionValue('--trace-tls');
9497
const tlsKeylog = getOptionValue('--tls-keylog');
9598
const { appendFile } = require('fs');
@@ -998,6 +1001,16 @@ TLSSocket.prototype.getCertificate = function() {
9981001
return null;
9991002
};
10001003

1004+
TLSSocket.prototype.getPeerX509Certificate = function(detailed) {
1005+
const cert = this._handle?.getPeerX509Certificate();
1006+
return cert ? new InternalX509Certificate(cert) : undefined;
1007+
};
1008+
1009+
TLSSocket.prototype.getX509Certificate = function() {
1010+
const cert = this._handle?.getX509Certificate();
1011+
return cert ? new InternalX509Certificate(cert) : undefined;
1012+
};
1013+
10011014
// Proxy TLSSocket handle methods
10021015
function makeSocketMethodProxy(name) {
10031016
return function socketMethodProxy(...args) {
Collapse file

‎lib/internal/crypto/x509.js‎

Copy file name to clipboardExpand all lines: lib/internal/crypto/x509.js
+20-9Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ function getFlags(options = {}) {
9090
return flags;
9191
}
9292

93+
class InternalX509Certificate extends JSTransferable {
94+
[kInternalState] = new SafeMap();
95+
96+
constructor(handle) {
97+
super();
98+
this[kHandle] = handle;
99+
}
100+
}
101+
93102
class X509Certificate extends JSTransferable {
94103
[kInternalState] = new SafeMap();
95104

@@ -168,6 +177,17 @@ class X509Certificate extends JSTransferable {
168177
return value;
169178
}
170179

180+
get issuerCertificate() {
181+
let value = this[kInternalState].get('issuerCertificate');
182+
if (value === undefined) {
183+
const cert = this[kHandle].getIssuerCert();
184+
if (cert)
185+
value = new InternalX509Certificate(this[kHandle].getIssuerCert());
186+
this[kInternalState].set('issuerCertificate', value);
187+
}
188+
return value;
189+
}
190+
171191
get infoAccess() {
172192
let value = this[kInternalState].get('infoAccess');
173193
if (value === undefined) {
@@ -313,15 +333,6 @@ class X509Certificate extends JSTransferable {
313333
}
314334
}
315335

316-
class InternalX509Certificate extends JSTransferable {
317-
[kInternalState] = new SafeMap();
318-
319-
constructor(handle) {
320-
super();
321-
this[kHandle] = handle;
322-
}
323-
}
324-
325336
InternalX509Certificate.prototype.constructor = X509Certificate;
326337
ObjectSetPrototypeOf(
327338
InternalX509Certificate.prototype,
Collapse file

‎src/crypto/crypto_tls.cc‎

Copy file name to clipboardExpand all lines: src/crypto/crypto_tls.cc
+26Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,20 @@ void TLSWrap::GetPeerCertificate(const FunctionCallbackInfo<Value>& args) {
15911591
args.GetReturnValue().Set(ret);
15921592
}
15931593

1594+
void TLSWrap::GetPeerX509Certificate(const FunctionCallbackInfo<Value>& args) {
1595+
TLSWrap* w;
1596+
ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
1597+
Environment* env = w->env();
1598+
1599+
X509Certificate::GetPeerCertificateFlag flag = w->is_server()
1600+
? X509Certificate::GetPeerCertificateFlag::SERVER
1601+
: X509Certificate::GetPeerCertificateFlag::NONE;
1602+
1603+
Local<Value> ret;
1604+
if (X509Certificate::GetPeerCert(env, w->ssl_, flag).ToLocal(&ret))
1605+
args.GetReturnValue().Set(ret);
1606+
}
1607+
15941608
void TLSWrap::GetCertificate(const FunctionCallbackInfo<Value>& args) {
15951609
TLSWrap* w;
15961610
ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
@@ -1601,6 +1615,15 @@ void TLSWrap::GetCertificate(const FunctionCallbackInfo<Value>& args) {
16011615
args.GetReturnValue().Set(ret);
16021616
}
16031617

1618+
void TLSWrap::GetX509Certificate(const FunctionCallbackInfo<Value>& args) {
1619+
TLSWrap* w;
1620+
ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
1621+
Environment* env = w->env();
1622+
Local<Value> ret;
1623+
if (X509Certificate::GetCert(env, w->ssl_).ToLocal(&ret))
1624+
args.GetReturnValue().Set(ret);
1625+
}
1626+
16041627
void TLSWrap::GetFinished(const FunctionCallbackInfo<Value>& args) {
16051628
Environment* env = Environment::GetCurrent(args);
16061629

@@ -2051,11 +2074,14 @@ void TLSWrap::Initialize(
20512074
env->SetProtoMethodNoSideEffect(t, "getALPNNegotiatedProtocol",
20522075
GetALPNNegotiatedProto);
20532076
env->SetProtoMethodNoSideEffect(t, "getCertificate", GetCertificate);
2077+
env->SetProtoMethodNoSideEffect(t, "getX509Certificate", GetX509Certificate);
20542078
env->SetProtoMethodNoSideEffect(t, "getCipher", GetCipher);
20552079
env->SetProtoMethodNoSideEffect(t, "getEphemeralKeyInfo",
20562080
GetEphemeralKeyInfo);
20572081
env->SetProtoMethodNoSideEffect(t, "getFinished", GetFinished);
20582082
env->SetProtoMethodNoSideEffect(t, "getPeerCertificate", GetPeerCertificate);
2083+
env->SetProtoMethodNoSideEffect(t, "getPeerX509Certificate",
2084+
GetPeerX509Certificate);
20592085
env->SetProtoMethodNoSideEffect(t, "getPeerFinished", GetPeerFinished);
20602086
env->SetProtoMethodNoSideEffect(t, "getProtocol", GetProtocol);
20612087
env->SetProtoMethodNoSideEffect(t, "getSession", GetSession);
Collapse file

‎src/crypto/crypto_tls.h‎

Copy file name to clipboardExpand all lines: src/crypto/crypto_tls.h
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,16 @@ class TLSWrap : public AsyncWrap,
184184
static void GetALPNNegotiatedProto(
185185
const v8::FunctionCallbackInfo<v8::Value>& args);
186186
static void GetCertificate(const v8::FunctionCallbackInfo<v8::Value>& args);
187+
static void GetX509Certificate(
188+
const v8::FunctionCallbackInfo<v8::Value>& args);
187189
static void GetCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
188190
static void GetEphemeralKeyInfo(
189191
const v8::FunctionCallbackInfo<v8::Value>& args);
190192
static void GetFinished(const v8::FunctionCallbackInfo<v8::Value>& args);
191193
static void GetPeerCertificate(
192194
const v8::FunctionCallbackInfo<v8::Value>& args);
195+
static void GetPeerX509Certificate(
196+
const v8::FunctionCallbackInfo<v8::Value>& args);
193197
static void GetPeerFinished(const v8::FunctionCallbackInfo<v8::Value>& args);
194198
static void GetProtocol(const v8::FunctionCallbackInfo<v8::Value>& args);
195199
static void GetServername(const v8::FunctionCallbackInfo<v8::Value>& args);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.