@@ -43,10 +43,12 @@ const { TCP, constants: TCPConstants } = internalBinding('tcp_wrap');
4343const tls_wrap = internalBinding ( 'tls_wrap' ) ;
4444const { Pipe, constants : PipeConstants } = internalBinding ( 'pipe_wrap' ) ;
4545const { owner_symbol } = require ( 'internal/async_hooks' ) . symbols ;
46+ const { isArrayBufferView } = require ( 'internal/util/types' ) ;
4647const { SecureContext : NativeSecureContext } = internalBinding ( 'crypto' ) ;
4748const { connResetException, codes } = require ( 'internal/errors' ) ;
4849const {
4950 ERR_INVALID_ARG_TYPE ,
51+ ERR_INVALID_ARG_VALUE ,
5052 ERR_INVALID_CALLBACK ,
5153 ERR_MULTIPLE_CALLBACK ,
5254 ERR_SOCKET_CLOSED ,
@@ -58,8 +60,9 @@ const {
5860 ERR_TLS_SESSION_ATTACK ,
5961 ERR_TLS_SNI_FROM_SERVER
6062} = codes ;
63+ const { onpskexchange : kOnPskExchange } = internalBinding ( 'symbols' ) ;
6164const { getOptionValue } = require ( 'internal/options' ) ;
62- const { validateString } = require ( 'internal/validators' ) ;
65+ const { validateString, validateBuffer } = require ( 'internal/validators' ) ;
6366const traceTls = getOptionValue ( '--trace-tls' ) ;
6467const tlsKeylog = getOptionValue ( '--tls-keylog' ) ;
6568const { appendFile } = require ( 'fs' ) ;
@@ -70,6 +73,8 @@ const kHandshakeTimeout = Symbol('handshake-timeout');
7073const kRes = Symbol ( 'res' ) ;
7174const kSNICallback = Symbol ( 'snicallback' ) ;
7275const kEnableTrace = Symbol ( 'enableTrace' ) ;
76+ const kPskCallback = Symbol ( 'pskcallback' ) ;
77+ const kPskIdentityHint = Symbol ( 'pskidentityhint' ) ;
7378
7479const noop = ( ) => { } ;
7580
@@ -289,6 +294,67 @@ function onnewsession(sessionId, session) {
289294 done ( ) ;
290295}
291296
297+ function onPskServerCallback ( identity , maxPskLen ) {
298+ const owner = this [ owner_symbol ] ;
299+ const ret = owner [ kPskCallback ] ( owner , identity ) ;
300+ if ( ret == null )
301+ return undefined ;
302+
303+ let psk ;
304+ if ( isArrayBufferView ( ret ) ) {
305+ psk = ret ;
306+ } else {
307+ if ( typeof ret !== 'object' ) {
308+ throw new ERR_INVALID_ARG_TYPE (
309+ 'ret' ,
310+ [ 'Object' , 'Buffer' , 'TypedArray' , 'DataView' ] ,
311+ ret
312+ ) ;
313+ }
314+ psk = ret . psk ;
315+ validateBuffer ( psk , 'psk' ) ;
316+ }
317+
318+ if ( psk . length > maxPskLen ) {
319+ throw new ERR_INVALID_ARG_VALUE (
320+ 'psk' ,
321+ psk ,
322+ `Pre-shared key exceeds ${ maxPskLen } bytes`
323+ ) ;
324+ }
325+
326+ return psk ;
327+ }
328+
329+ function onPskClientCallback ( hint , maxPskLen , maxIdentityLen ) {
330+ const owner = this [ owner_symbol ] ;
331+ const ret = owner [ kPskCallback ] ( hint ) ;
332+ if ( ret == null )
333+ return undefined ;
334+
335+ if ( typeof ret !== 'object' )
336+ throw new ERR_INVALID_ARG_TYPE ( 'ret' , 'Object' , ret ) ;
337+
338+ validateBuffer ( ret . psk , 'psk' ) ;
339+ if ( ret . psk . length > maxPskLen ) {
340+ throw new ERR_INVALID_ARG_VALUE (
341+ 'psk' ,
342+ ret . psk ,
343+ `Pre-shared key exceeds ${ maxPskLen } bytes`
344+ ) ;
345+ }
346+
347+ validateString ( ret . identity , 'identity' ) ;
348+ if ( Buffer . byteLength ( ret . identity ) > maxIdentityLen ) {
349+ throw new ERR_INVALID_ARG_VALUE (
350+ 'identity' ,
351+ ret . identity ,
352+ `PSK identity exceeds ${ maxIdentityLen } bytes`
353+ ) ;
354+ }
355+
356+ return { psk : ret . psk , identity : ret . identity } ;
357+ }
292358
293359function onkeylogclient ( line ) {
294360 debug ( 'client onkeylog' ) ;
@@ -687,6 +753,32 @@ TLSSocket.prototype._init = function(socket, wrap) {
687753 ssl . setALPNProtocols ( ssl . _secureContext . alpnBuffer ) ;
688754 }
689755
756+ if ( options . pskCallback && ssl . enablePskCallback ) {
757+ if ( typeof options . pskCallback !== 'function' ) {
758+ throw new ERR_INVALID_ARG_TYPE ( 'pskCallback' ,
759+ 'function' ,
760+ options . pskCallback ) ;
761+ }
762+
763+ ssl [ kOnPskExchange ] = options . isServer ?
764+ onPskServerCallback : onPskClientCallback ;
765+
766+ this [ kPskCallback ] = options . pskCallback ;
767+ ssl . enablePskCallback ( ) ;
768+
769+ if ( options . pskIdentityHint ) {
770+ if ( typeof options . pskIdentityHint !== 'string' ) {
771+ throw new ERR_INVALID_ARG_TYPE (
772+ 'options.pskIdentityHint' ,
773+ 'string' ,
774+ options . pskIdentityHint
775+ ) ;
776+ }
777+ ssl . setPskIdentityHint ( options . pskIdentityHint ) ;
778+ }
779+ }
780+
781+
690782 if ( options . handshakeTimeout > 0 )
691783 this . setTimeout ( options . handshakeTimeout , this . _handleTimeout ) ;
692784
@@ -898,7 +990,7 @@ function makeSocketMethodProxy(name) {
898990 TLSSocket . prototype [ method ] = makeSocketMethodProxy ( method ) ;
899991} ) ;
900992
901- // TODO: support anonymous (nocert) and PSK
993+ // TODO: support anonymous (nocert)
902994
903995
904996function onServerSocketSecure ( ) {
@@ -954,6 +1046,8 @@ function tlsConnectionListener(rawSocket) {
9541046 SNICallback : this [ kSNICallback ] || SNICallback ,
9551047 enableTrace : this [ kEnableTrace ] ,
9561048 pauseOnConnect : this . pauseOnConnect ,
1049+ pskCallback : this [ kPskCallback ] ,
1050+ pskIdentityHint : this [ kPskIdentityHint ] ,
9571051 } ) ;
9581052
9591053 socket . on ( 'secure' , onServerSocketSecure ) ;
@@ -1058,6 +1152,8 @@ function Server(options, listener) {
10581152
10591153 this [ kHandshakeTimeout ] = options . handshakeTimeout || ( 120 * 1000 ) ;
10601154 this [ kSNICallback ] = options . SNICallback ;
1155+ this [ kPskCallback ] = options . pskCallback ;
1156+ this [ kPskIdentityHint ] = options . pskIdentityHint ;
10611157
10621158 if ( typeof this [ kHandshakeTimeout ] !== 'number' ) {
10631159 throw new ERR_INVALID_ARG_TYPE (
@@ -1069,6 +1165,18 @@ function Server(options, listener) {
10691165 'options.SNICallback' , 'function' , options . SNICallback ) ;
10701166 }
10711167
1168+ if ( this [ kPskCallback ] && typeof this [ kPskCallback ] !== 'function' ) {
1169+ throw new ERR_INVALID_ARG_TYPE (
1170+ 'options.pskCallback' , 'function' , options . pskCallback ) ;
1171+ }
1172+ if ( this [ kPskIdentityHint ] && typeof this [ kPskIdentityHint ] !== 'string' ) {
1173+ throw new ERR_INVALID_ARG_TYPE (
1174+ 'options.pskIdentityHint' ,
1175+ 'string' ,
1176+ options . pskIdentityHint
1177+ ) ;
1178+ }
1179+
10721180 // constructor call
10731181 net . Server . call ( this , options , tlsConnectionListener ) ;
10741182
@@ -1265,6 +1373,8 @@ Server.prototype.setOptions = deprecate(function(options) {
12651373 . digest ( 'hex' )
12661374 . slice ( 0 , 32 ) ;
12671375 }
1376+ if ( options . pskCallback ) this [ kPskCallback ] = options . pskCallback ;
1377+ if ( options . pskIdentityHint ) this [ kPskIdentityHint ] = options . pskIdentityHint ;
12681378} , 'Server.prototype.setOptions() is deprecated' , 'DEP0122' ) ;
12691379
12701380// SNI Contexts High-Level API
@@ -1440,7 +1550,8 @@ exports.connect = function connect(...args) {
14401550 session : options . session ,
14411551 ALPNProtocols : options . ALPNProtocols ,
14421552 requestOCSP : options . requestOCSP ,
1443- enableTrace : options . enableTrace
1553+ enableTrace : options . enableTrace ,
1554+ pskCallback : options . pskCallback ,
14441555 } ) ;
14451556
14461557 tlssock [ kConnectOptions ] = options ;
0 commit comments