in src/states.js [333:364]
async recvHandshakeMessage(msg) {
if (! (msg instanceof ClientHello)) {
throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
}
// In the spec, this is where we select connection parameters, and maybe
// tell the client to try again if we can't find a compatible set.
// Since we only support a fixed cipherset, the only thing to "negotiate"
// is whether they provided an acceptable PSK.
const pskExt = msg.extensions.get(EXTENSION_TYPE.PRE_SHARED_KEY);
const pskModesExt = msg.extensions.get(EXTENSION_TYPE.PSK_KEY_EXCHANGE_MODES);
if (! pskExt || ! pskModesExt) {
throw new TLSError(ALERT_DESCRIPTION.MISSING_EXTENSION);
}
if (pskModesExt.modes.indexOf(PSK_MODE_KE) === -1) {
throw new TLSError(ALERT_DESCRIPTION.HANDSHAKE_FAILURE);
}
const pskIndex = pskExt.identities.findIndex(pskId => bytesAreEqual(pskId, this.conn.pskId));
if (pskIndex === -1) {
throw new TLSError(ALERT_DESCRIPTION.UNKNOWN_PSK_IDENTITY);
}
await this.conn._keyschedule.addPSK(this.conn.psk);
// Validate the PSK binder.
const keyschedule = this.conn._keyschedule;
const transcript = keyschedule.getTranscript();
// Calculate size occupied by the PSK binders.
let pskBindersSize = 2; // Vector16 representation overhead.
for (const binder of pskExt.binders) {
pskBindersSize += binder.byteLength + 1; // Vector8 representation overhead.
}
await keyschedule.verifyFinishedMAC(keyschedule.extBinderKey, pskExt.binders[pskIndex], transcript.slice(0, -pskBindersSize));
await this.conn._transition(SERVER_NEGOTIATED, msg.sessionId, pskIndex);
}