in src/states.js [368:401]
async initialize(sessionId, pskIndex) {
await this.conn._sendHandshakeMessage(new ServerHello(
// Server random
await getRandomBytes(32),
sessionId,
[
new SupportedVersionsExtension(null, VERSION_TLS_1_3),
new PreSharedKeyExtension(null, null, pskIndex),
]
));
// If the client sent a non-empty sessionId, the server *must* send a change-cipher-spec for b/w compat.
if (sessionId.byteLength > 0) {
await this.conn._sendChangeCipherSpec();
}
// We can now transition to the encrypted part of the handshake.
const keyschedule = this.conn._keyschedule;
await keyschedule.addECDHE(null);
await this.conn._setSendKey(keyschedule.serverHandshakeTrafficSecret);
await this.conn._setRecvKey(keyschedule.clientHandshakeTrafficSecret);
// Send an empty EncryptedExtensions message.
await this.conn._sendHandshakeMessage(new EncryptedExtensions([]));
// Send the Finished message.
const serverFinishedMAC = await keyschedule.calculateFinishedMAC(keyschedule.serverHandshakeTrafficSecret);
await this.conn._sendHandshakeMessage(new Finished(serverFinishedMAC));
// We can now *send* using the application traffic key,
// but have to wait to receive the client Finished before receiving under that key.
// We need to remember the handshake state from before the client Finished
// in order to successfully verify the client Finished.
const clientFinishedTranscript = await keyschedule.getTranscript();
const clientHandshakeTrafficSecret = keyschedule.clientHandshakeTrafficSecret;
await keyschedule.finalize();
await this.conn._setSendKey(keyschedule.serverApplicationTrafficSecret);
await this.conn._transition(SERVER_WAIT_FINISHED, clientHandshakeTrafficSecret, clientFinishedTranscript);
}