in src/messages.js [169:216]
static _read(buf) {
// The legacy_version field may indicate an earlier version of TLS
// for backwards compatibility, but must not predate TLS 1.0!
if (buf.readUint16() < VERSION_TLS_1_0) {
throw new TLSError(ALERT_DESCRIPTION.PROTOCOL_VERSION);
}
// The random bytes provided by the peer.
const random = buf.readBytes(32);
// Read legacy_session_id, so the server can echo it.
const sessionId = buf.readVectorBytes8();
// We only support a single ciphersuite, but the peer may offer several.
// Scan the list to confirm that the one we want is present.
let found = false;
buf.readVector16(buf => {
const cipherSuite = buf.readUint16();
if (cipherSuite === TLS_AES_128_GCM_SHA256) {
found = true;
}
});
if (! found) {
throw new TLSError(ALERT_DESCRIPTION.HANDSHAKE_FAILURE);
}
// legacy_compression_methods must be a single zero byte for TLS1.3 ClientHellos.
// It can be non-zero in previous versions of TLS, but we're not going to
// make a successful handshake with such versions, so better to just bail out now.
const legacyCompressionMethods = buf.readVectorBytes8();
if (legacyCompressionMethods.byteLength !== 1) {
throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
}
if (legacyCompressionMethods[0] !== 0x00) {
throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
}
// Read and check the extensions.
const extensions = this._readExtensions(HANDSHAKE_TYPE.CLIENT_HELLO, buf);
if (! extensions.has(EXTENSION_TYPE.SUPPORTED_VERSIONS)) {
throw new TLSError(ALERT_DESCRIPTION.MISSING_EXTENSION);
}
if (extensions.get(EXTENSION_TYPE.SUPPORTED_VERSIONS).versions.indexOf(VERSION_TLS_1_3) === -1) {
throw new TLSError(ALERT_DESCRIPTION.PROTOCOL_VERSION);
}
// Was the PreSharedKey extension the last one?
if (extensions.has(EXTENSION_TYPE.PRE_SHARED_KEY)) {
if (extensions.lastSeenExtension !== EXTENSION_TYPE.PRE_SHARED_KEY) {
throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
}
}
return new this(random, sessionId, extensions);
}