def test_get_with_too_few_bytes_left(self): p = Parser(bytearray(b'\x02\x01')) p.get(1) with self.assertRaises(SyntaxError): p.get(2)
def filter(packetNo, data, source, target): bytes = stringToBytes(data) if packetNo == 0 and 'Client2Server' in str(source): p = Parser(bytes[5:]) p.get(1) clientHello = ClientHello() clientHello.parse(p) print bcolors.OKGREEN + "Client supports TLS version: %s" % \ str(clientHello.client_version) print "Client supports ciphersuites: %s" % \ str([CIPHER_MAP.get(i,i) for i in clientHello.cipher_suites]) \ + bcolors.ENDC elif packetNo == 0 and 'Client2Server' not in str(source): p = Parser(bytes[5:]) p.get(1) serverHello = ServerHello() serverHello.parse(p) print bcolors.OKGREEN + "Server selected TLS version: %s" % \ str(serverHello.server_version) print "Server selected ciphersuite: %s" % \ str(CIPHER_MAP.get(serverHello.cipher_suite, serverHello.cipher_suite)) + bcolors.ENDC target.write(data) return data
def test_getRemainingLength(self): p = Parser(bytearray(b'\x00\x01\x05')) self.assertEqual(1, p.get(2)) self.assertEqual(1, p.getRemainingLength()) self.assertEqual(5, p.get(1)) self.assertEqual(0, p.getRemainingLength())
def test_getRemainingLength(self): p = Parser(bytearray(b"\x00\x01\x05")) self.assertEqual(1, p.get(2)) self.assertEqual(1, p.getRemainingLength()) self.assertEqual(5, p.get(1)) self.assertEqual(0, p.getRemainingLength())
def test_get_with_too_few_bytes_left(self): p = Parser(bytearray(b'\x02\x01')) p.get(1) with self.assertRaises(SyntaxError): p.get(2)
def test_atLengthCheck(self): p = Parser(bytearray(b"\x00\x06" + b"\x05" + b"\x01\xff" + b"\x07" + b"\x01\xf0")) p.startLengthCheck(2) while not p.atLengthCheck(): p.get(1) p.getVarBytes(1) p.stopLengthCheck()
def process(self, state, msg): """Analyse the error message""" assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == SSL2HandshakeType.error if self.error is not None: assert self.error == parser.get(2)
def process(self, state, msg): """Analyse the error message""" assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == SSL2HandshakeType.error if self.error is not None: assert self.error == parser.get(2)
def test_atLengthCheck(self): p = Parser( bytearray(b'\x00\x06' + b'\x05' + b'\x01\xff' + b'\x07' + b'\x01\xf0')) p.startLengthCheck(2) while not p.atLengthCheck(): p.get(1) p.getVarBytes(1) p.stopLengthCheck()
def test_atLengthCheck(self): p = Parser(bytearray( b'\x00\x06' + b'\x05' + b'\x01\xff' + b'\x07' + b'\x01\xf0' )) p.startLengthCheck(2) while not p.atLengthCheck(): p.get(1) p.getVarBytes(1) p.stopLengthCheck()
def process(self, state, msg): """ @type state: ConnectionState @type msg: Message """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.finished if self.version is None: self.version = state.version finished = Finished(self.version) finished.parse(parser) verify_expected = calcFinished(state.version, state.master_secret, state.cipher, state.handshake_hashes, not state.client) assert finished.verify_data == verify_expected state.handshake_messages.append(finished) state.server_verify_data = finished.verify_data state.handshake_hashes.update(msg.write())
def process(self, state, msg): """Check if the VERIFY message has expected value""" assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) msg_type = parser.get(1) assert msg_type == SSL2HandshakeType.server_verify
def process(self, state, msg): """ @type state: ConnectionState @type msg: Message """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == self.handshake_type if self.version is None: self.version = state.version if self.version in ((0, 2), (2, 0)): finished = ServerFinished() else: finished = Finished(self.version) finished.parse(parser) if self.version in ((0, 2), (2, 0)): state.session_id = finished.verify_data else: verify_expected = calcFinished(state.version, state.master_secret, state.cipher, state.handshake_hashes, not state.client) assert finished.verify_data == verify_expected state.handshake_messages.append(finished) state.server_verify_data = finished.verify_data state.handshake_hashes.update(msg.write()) if self.version in ((0, 2), (2, 0)): state.msg_sock.handshake_finished = True
def process(self, state, msg): """Check if the VERIFY message has expected value""" assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) msg_type = parser.get(1) assert msg_type == SSL2HandshakeType.server_verify
def process(self, state, msg): assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.new_session_ticket ticket = NewSessionTicket().parse(parser) state.session_tickets.append(ticket)
def process(self, state, msg): """ Process the message and update state accordingly @type state: ConnectionState @param state: overall state of TLS connection @type msg: Message @param msg: TLS Message read from socket """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.server_hello srv_hello = ServerHello() srv_hello.parse(parser) # extract important info state.server_random = srv_hello.random # check for session_id based session resumption if self.resume: assert state.session_id == srv_hello.session_id if (state.session_id == srv_hello.session_id and srv_hello.session_id != bytearray(0)): state.resuming = True assert state.cipher == srv_hello.cipher_suite assert state.version == srv_hello.server_version state.session_id = srv_hello.session_id if self.version is not None: assert self.version == srv_hello.server_version state.cipher = srv_hello.cipher_suite state.version = srv_hello.server_version # update the state of connection state.msg_sock.version = srv_hello.server_version state.handshake_messages.append(srv_hello) state.handshake_hashes.update(msg.write()) # check if the message has expected values if self.extensions is not None: for ext_id in self.extensions: ext = srv_hello.getExtension(ext_id) assert ext is not None # run extension-specific checker if present if self.extensions[ext_id] is not None: self.extensions[ext_id](state, ext) # not supporting any extensions is valid if srv_hello.extensions is not None: for ext_id in (ext.extType for ext in srv_hello.extensions): assert ext_id in self.extensions
def process(self, state, msg): assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.certificate_status cert_status = CertificateStatus().parse(parser) state.handshake_messages.append(cert_status) state.handshake_hashes.update(msg.write())
def process(self, state, msg): """ @type state: ConnectionState @type msg: Message """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == self.handshake_type if self.version is None: self.version = state.version if self.version in ((0, 2), (2, 0)): finished = ServerFinished() else: finished = Finished(self.version, state.prf_size) finished.parse(parser) if self.version in ((0, 2), (2, 0)): state.session_id = finished.verify_data elif self.version <= (3, 3): verify_expected = calcFinished(state.version, state.key['master_secret'], state.cipher, state.handshake_hashes, not state.client) assert finished.verify_data == verify_expected else: # TLS 1.3 finished_key = HKDF_expand_label( state.key['server handshake traffic secret'], b'finished', b'', state.prf_size, state.prf_name) transcript_hash = state.handshake_hashes.digest(state.prf_name) verify_expected = secureHMAC(finished_key, transcript_hash, state.prf_name) assert finished.verify_data == verify_expected state.handshake_messages.append(finished) state.key['server_verify_data'] = finished.verify_data state.handshake_hashes.update(msg.write()) if self.version in ((0, 2), (2, 0)): state.msg_sock.handshake_finished = True # in TLS 1.3 ChangeCipherSpec is a no-op, we need to attach # the change to some message if self.version > (3, 3): state.msg_sock.changeWriteState()
def process(self, state, msg): """Process the Server Key Exchange message""" assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.server_key_exchange if self.version is None: self.version = state.version if self.cipher_suite is None: self.cipher_suite = state.cipher valid_sig_algs = self.valid_sig_algs server_key_exchange = ServerKeyExchange(self.cipher_suite, self.version) server_key_exchange.parse(parser) client_random = state.client_random server_random = state.server_random public_key = state.get_server_public_key() server_hello = state.get_last_message_of_type(ServerHello) if server_hello is None: server_hello = ServerHello server_hello.server_version = state.version if valid_sig_algs is None: # if the value was unset in script, get the advertised value from # Client Hello client_hello = state.get_last_message_of_type(ClientHello) if client_hello is not None: sig_algs_ext = client_hello.getExtension(ExtensionType. signature_algorithms) if sig_algs_ext is not None: valid_sig_algs = sig_algs_ext.sigalgs if valid_sig_algs is None: # no advertised means support for sha1 only valid_sig_algs = [(HashAlgorithm.sha1, SignatureAlgorithm.rsa)] KeyExchange.verifyServerKeyExchange(server_key_exchange, public_key, client_random, server_random, valid_sig_algs) state.key_exchange = DHE_RSAKeyExchange(self.cipher_suite, clientHello=None, serverHello=server_hello, privateKey=None) state.premaster_secret = state.key_exchange.\ processServerKeyExchange(public_key, server_key_exchange) state.handshake_messages.append(server_key_exchange) state.handshake_hashes.update(msg.write())
def process(self, state, msg): assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == self.handshake_type exts = EncryptedExtensions().parse(parser) # TODO check if received extensions match the set extensions assert self.extensions is None state.handshake_messages.append(exts) state.handshake_hashes.update(msg.write())
def process(self, state, msg): """ @type state: ConnectionState """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.certificate cert = Certificate(self.cert_type) cert.parse(parser) state.handshake_messages.append(cert) state.handshake_hashes.update(msg.write())
def process(self, state, msg): """ @type state: ConnectionState """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.certificate cert = Certificate(self.cert_type) cert.parse(parser) state.handshake_messages.append(cert) state.handshake_hashes.update(msg.write())
def process(self, state, msg): """ @type state: ConnectionState @type msg: Message """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.server_hello_done srv_hello_done = ServerHelloDone() srv_hello_done.parse(parser) state.handshake_messages.append(srv_hello_done) state.handshake_hashes.update(msg.write())
def process(self, state, msg): """ @type state: ConnectionState @type msg: Message """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.server_hello_done srv_hello_done = ServerHelloDone() srv_hello_done.parse(parser) state.handshake_messages.append(srv_hello_done) state.handshake_hashes.update(msg.write())
def process(state, msg): """ Check received Certificate Request @type state: ConnectionState """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.certificate_request cert_request = CertificateRequest(state.version) cert_request.parse(parser) state.handshake_messages.append(cert_request) state.handshake_hashes.update(msg.write())
def process(self, state, msg): """ Process the message and update state accordingly @type state: ConnectionState @param state: overall state of TLS connection @type msg: Message @param msg: TLS Message read from socket """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.server_hello srv_hello = ServerHello() srv_hello.parse(parser) # extract important info state.cipher = srv_hello.cipher_suite state.version = srv_hello.server_version state.server_random = srv_hello.random # update the state of connection state.msg_sock.version = srv_hello.server_version state.handshake_messages.append(srv_hello) state.handshake_hashes.update(msg.write()) # check if the message has expected values if self.extensions is not None: for ext_id in self.extensions: ext = srv_hello.getExtension(ext_id) assert ext is not None # run extension-specific checker if present if self.extensions[ext_id] is not None: self.extensions[ext_id](state, ext) # not supporting any extensions is valid if srv_hello.extensions is not None: for ext_id in (ext.extType for ext in srv_hello.extensions): assert ext_id in self.extensions
def process(self, state, msg): """ @type state: ConnectionState """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.certificate_verify if self.version is None: self.version = state.version cert_v = CertificateVerify(self.version) cert_v.parse(parser) if self.sig_alg: assert self.sig_alg == cert_v.signatureAlgorithm else: c_hello = state.get_last_message_of_type(ClientHello) ext = c_hello.getExtension(ExtensionType.signature_algorithms) assert cert_v.signatureAlgorithm in ext.sigalgs salg = cert_v.signatureAlgorithm scheme = SignatureScheme.toRepr(salg) hash_name = SignatureScheme.getHash(scheme) transcript_hash = state.handshake_hashes.digest(state.prf_name) sig_context = bytearray(b'\x20' * 64 + b'TLS 1.3, server CertificateVerify' + b'\x00') + transcript_hash if not state.get_server_public_key().hashAndVerify( cert_v.signature, sig_context, SignatureScheme.getPadding(scheme), hash_name, getattr(hashlib, hash_name)().digest_size): raise AssertionError("Signature verification failed") state.handshake_messages.append(cert_v) state.handshake_hashes.update(msg.write())
def process(self, state, msg): """ @type state: ConnectionState @type msg: Message """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.finished finished = Finished(self.version) finished.parse(parser) verify_expected = calcFinished(state.version, state.master_secret, state.cipher, state.handshake_hashes, not state.client) assert finished.verify_data == verify_expected state.handshake_messages.append(finished) state.server_verify_data = finished.verify_data
def process(self, state, msg): """ Check received Certificate Request @type state: ConnectionState """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.certificate_request cert_request = CertificateRequest(state.version) cert_request.parse(parser) if self.sig_algs is not None and \ cert_request.supported_signature_algs != self.sig_algs: raise AssertionError("Unexpected algorithms found: {0}".format( cert_request.supported_signature_algs)) state.handshake_messages.append(cert_request) state.handshake_hashes.update(msg.write())
def process(self, state, msg): """ Process the message and update state accordingly @type state: ConnectionState @param state: overall state of TLS connection @type msg: Message @param msg: TLS Message read from socket """ # the value is faked for SSLv2 protocol, but let's just check sanity assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == SSL2HandshakeType.server_hello server_hello = ServerHello2().parse(parser) state.handshake_messages.append(server_hello) state.handshake_hashes.update(msg.write()) if self.version is not None: assert self.version == server_hello.server_version if server_hello.session_id_hit: state.resuming = True state.session_id = server_hello.session_id state.server_random = server_hello.session_id state.version = server_hello.server_version state.msg_sock.version = server_hello.server_version # fake a certificate message so finding the server public key works x509 = X509() x509.parseBinary(server_hello.certificate) cert_chain = X509CertChain([x509]) certificate = Certificate(CertificateType.x509) certificate.create(cert_chain) state.handshake_messages.append(certificate)
def process(self, state, msg): """ Process the message and update state accordingly @type state: ConnectionState @param state: overall state of TLS connection @type msg: Message @param msg: TLS Message read from socket """ # the value is faked for SSLv2 protocol, but let's just check sanity assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == SSL2HandshakeType.server_hello server_hello = ServerHello2().parse(parser) state.handshake_messages.append(server_hello) state.handshake_hashes.update(msg.write()) if self.version is not None: assert self.version == server_hello.server_version if server_hello.session_id_hit: state.resuming = True state.session_id = server_hello.session_id state.server_random = server_hello.session_id state.version = server_hello.server_version state.msg_sock.version = server_hello.server_version # fake a certificate message so finding the server public key works x509 = X509() x509.parseBinary(server_hello.certificate) cert_chain = X509CertChain([x509]) certificate = Certificate(CertificateType.x509) certificate.create(cert_chain) state.handshake_messages.append(certificate)
def process(self, state, msg): """ @type state: ConnectionState @type msg: Message """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == self.handshake_type if self.version is None: self.version = state.version if self.version in ((0, 2), (2, 0)): finished = ServerFinished() else: finished = Finished(self.version) finished.parse(parser) if self.version in ((0, 2), (2, 0)): state.session_id = finished.verify_data else: verify_expected = calcFinished(state.version, state.master_secret, state.cipher, state.handshake_hashes, not state.client) assert finished.verify_data == verify_expected state.handshake_messages.append(finished) state.server_verify_data = finished.verify_data state.handshake_hashes.update(msg.write()) if self.version in ((0, 2), (2, 0)): state.msg_sock.handshake_finished = True
def test_get(self): p = Parser(bytearray(b'\x02\x01\x00')) self.assertEqual(2, p.get(1)) self.assertEqual(256, p.get(2)) self.assertEqual(3, p.index)
def process(self, state, msg): """ @type state: ConnectionState @type msg: Message """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == self.handshake_type if self.version is None: self.version = state.version if self.version in ((0, 2), (2, 0)): finished = ServerFinished() else: finished = Finished(self.version, state.prf_size) finished.parse(parser) if self.version in ((0, 2), (2, 0)): state.session_id = finished.verify_data elif self.version <= (3, 3): verify_expected = calcFinished(state.version, state.key['master_secret'], state.cipher, state.handshake_hashes, not state.client) assert finished.verify_data == verify_expected else: # TLS 1.3 finished_key = HKDF_expand_label( state.key['server handshake traffic secret'], b'finished', b'', state.prf_size, state.prf_name) transcript_hash = state.handshake_hashes.digest(state.prf_name) verify_expected = secureHMAC(finished_key, transcript_hash, state.prf_name) assert finished.verify_data == verify_expected state.handshake_messages.append(finished) state.key['server_verify_data'] = finished.verify_data state.handshake_hashes.update(msg.write()) if self.version in ((0, 2), (2, 0)): state.msg_sock.handshake_finished = True if self.version > (3, 3): # in TLS 1.3 ChangeCipherSpec is a no-op, so we need to attach # the change for reading to some message that is always sent state.msg_sock.changeWriteState() # we now need to calculate application traffic keys to allow # correct interpretation of the alerts regarding Certificate, # CertificateVerify and Finished # derive the master secret secret = derive_secret(state.key['handshake secret'], b'derived', None, state.prf_name) secret = secureHMAC(secret, bytearray(state.prf_size), state.prf_name) state.key['master secret'] = secret # derive encryption keys c_traff_sec = derive_secret(secret, b'c ap traffic', state.handshake_hashes, state.prf_name) state.key['client application traffic secret'] = c_traff_sec s_traff_sec = derive_secret(secret, b's ap traffic', state.handshake_hashes, state.prf_name) state.key['server application traffic secret'] = s_traff_sec # derive TLS exporter key exp_ms = derive_secret(secret, b'exp master', state.handshake_hashes, state.prf_name) state.key['exporter master secret'] = exp_ms # set up the encryption keys for application data state.msg_sock.calcTLS1_3PendingState(state.cipher, c_traff_sec, s_traff_sec, None) state.msg_sock.changeReadState()
def process(self, state, msg): """ Process the message and update state accordingly @type state: ConnectionState @param state: overall state of TLS connection @type msg: Message @param msg: TLS Message read from socket """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.server_hello srv_hello = ServerHello() srv_hello.parse(parser) # extract important info state.server_random = srv_hello.random # check for session_id based session resumption if self.resume: assert state.session_id == srv_hello.session_id if (state.session_id == srv_hello.session_id and srv_hello.session_id != bytearray(0)): state.resuming = True assert state.cipher == srv_hello.cipher_suite assert state.version == srv_hello.server_version state.session_id = srv_hello.session_id if self.version is not None: assert self.version == srv_hello.server_version state.cipher = srv_hello.cipher_suite state.version = srv_hello.server_version # update the state of connection state.msg_sock.version = srv_hello.server_version state.handshake_messages.append(srv_hello) state.handshake_hashes.update(msg.write()) # Reset value of the session-wide settings state.extended_master_secret = False # check if the message has expected values if self.extensions is not None: for ext_id in self.extensions: ext = srv_hello.getExtension(ext_id) assert ext is not None # run extension-specific checker if present if self.extensions[ext_id] is not None: self.extensions[ext_id](state, ext) if ext_id == ExtensionType.extended_master_secret: state.extended_master_secret = True # not supporting any extensions is valid if srv_hello.extensions is not None: for ext_id in (ext.extType for ext in srv_hello.extensions): assert ext_id in self.extensions
def test_get(self): p = Parser(bytearray(b'\x02\x01\x00')) self.assertEqual(2, p.get(1)) self.assertEqual(256, p.get(2)) self.assertEqual(3, p.index)
def process(self, state, msg): """ Process the message and update state accordingly @type state: ConnectionState @param state: overall state of TLS connection @type msg: Message @param msg: TLS Message read from socket """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.server_hello srv_hello = ServerHello() srv_hello.parse(parser) # extract important info state.server_random = srv_hello.random # check for session_id based session resumption if self.resume: assert state.session_id == srv_hello.session_id if (state.session_id == srv_hello.session_id and srv_hello.session_id != bytearray(0)): state.resuming = True assert state.cipher == srv_hello.cipher_suite assert state.version == srv_hello.server_version state.session_id = srv_hello.session_id if self.version is not None: assert self.version == srv_hello.server_version if self.cipher is not None: assert self.cipher == srv_hello.cipher_suite state.cipher = srv_hello.cipher_suite state.version = srv_hello.server_version # update the state of connection state.msg_sock.version = srv_hello.server_version state.handshake_messages.append(srv_hello) state.handshake_hashes.update(msg.write()) # Reset value of the session-wide settings state.extended_master_secret = False state.encrypt_then_mac = False # check if the message has expected values if self.extensions is not None: for ext_id in self.extensions: ext = srv_hello.getExtension(ext_id) if ext is None: raise AssertionError( "Required extension {0} missing".format( ExtensionType.toStr(ext_id))) # run extension-specific checker if present if self.extensions[ext_id] is not None: if callable(self.extensions[ext_id]): self.extensions[ext_id](state, ext) elif isinstance(self.extensions[ext_id], TLSExtension): if not self.extensions[ext_id] == ext: raise AssertionError( "Expected extension " "not matched, received: {0}".format(ext)) else: raise ValueError( "Bad extension, id: {0}".format(ext_id)) continue if ext_id == ExtensionType.extended_master_secret: state.extended_master_secret = True if ext_id == ExtensionType.encrypt_then_mac: state.encrypt_then_mac = True # not supporting any extensions is valid if srv_hello.extensions is not None: for ext_id in (ext.extType for ext in srv_hello.extensions): if ext_id not in self.extensions: raise AssertionError( "unexpected extension: {0}".format( ExtensionType.toStr(ext_id)))
def process(self, state, msg): """ Process the message and update state accordingly @type state: ConnectionState @param state: overall state of TLS connection @type msg: Message @param msg: TLS Message read from socket """ assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.server_hello srv_hello = ServerHello() srv_hello.parse(parser) # extract important info state.server_random = srv_hello.random # check for session_id based session resumption if self.resume: assert state.session_id == srv_hello.session_id if (state.session_id == srv_hello.session_id and srv_hello.session_id != bytearray(0) and self._extract_version(srv_hello) < (3, 4)): # TLS 1.2 resumption, TLS 1.3 is based on PSKs state.resuming = True assert state.cipher == srv_hello.cipher_suite assert state.version == self._extract_version(srv_hello) state.session_id = srv_hello.session_id if self.version is not None: assert self.version == srv_hello.server_version if self.cipher is not None: assert self.cipher == srv_hello.cipher_suite # check if server sent cipher matches what we advertised in CH cln_hello = state.get_last_message_of_type(ClientHello) if srv_hello.cipher_suite not in cln_hello.cipher_suites: cipher = srv_hello.cipher_suite if cipher in CipherSuite.ietfNames: name = "{0} ({1:#06x})".format(CipherSuite.ietfNames[cipher], cipher) else: name = "{0:#06x}".format(cipher) raise AssertionError("Server responded with cipher we did" " not advertise: {0}".format(name)) state.cipher = srv_hello.cipher_suite state.version = self._extract_version(srv_hello) # update the state of connection state.msg_sock.version = state.version state.msg_sock.tls13record = state.version > (3, 3) self._check_against_hrr(state, srv_hello) state.handshake_messages.append(srv_hello) state.handshake_hashes.update(msg.write()) # Reset value of the session-wide settings state.extended_master_secret = False state.encrypt_then_mac = False if srv_hello.extensions: self._process_extensions(state, cln_hello, srv_hello) self._compare_extensions(srv_hello) if state.version > (3, 3): self._setup_tls13_handshake_keys(state) return srv_hello
def process(self, state, msg): """Process the Server Key Exchange message""" assert msg.contentType == ContentType.handshake parser = Parser(msg.write()) hs_type = parser.get(1) assert hs_type == HandshakeType.server_key_exchange if self.version is None: self.version = state.version if self.cipher_suite is None: self.cipher_suite = state.cipher valid_sig_algs = self.valid_sig_algs valid_groups = self.valid_groups server_key_exchange = ServerKeyExchange(self.cipher_suite, self.version) server_key_exchange.parse(parser) client_random = state.client_random server_random = state.server_random public_key = state.get_server_public_key() server_hello = state.get_last_message_of_type(ServerHello) if server_hello is None: server_hello = ServerHello server_hello.server_version = state.version if valid_sig_algs is None: # if the value was unset in script, get the advertised value from # Client Hello client_hello = state.get_last_message_of_type(ClientHello) if client_hello is not None: sig_algs_ext = client_hello.getExtension( ExtensionType.signature_algorithms) if sig_algs_ext is not None: valid_sig_algs = sig_algs_ext.sigalgs if valid_sig_algs is None: # no advertised means support for sha1 only valid_sig_algs = [(HashAlgorithm.sha1, SignatureAlgorithm.rsa)] KeyExchange.verifyServerKeyExchange(server_key_exchange, public_key, client_random, server_random, valid_sig_algs) if self.cipher_suite in CipherSuite.dhAllSuites: if valid_groups and any(i in range(256, 512) for i in valid_groups): self._checkParams(server_key_exchange) state.key_exchange = DHE_RSAKeyExchange(self.cipher_suite, clientHello=None, serverHello=server_hello, privateKey=None) elif self.cipher_suite in CipherSuite.ecdhAllSuites: # extract valid groups from Client Hello if valid_groups is None: client_hello = state.get_last_message_of_type(ClientHello) if client_hello is not None: groups_ext = client_hello.getExtension( ExtensionType.supported_groups) if groups_ext is not None: valid_groups = groups_ext.groups if valid_groups is None: # no advertised means support for all valid_groups = GroupName.allEC state.key_exchange = \ ECDHE_RSAKeyExchange(self.cipher_suite, clientHello=None, serverHello=server_hello, privateKey=None, acceptedCurves=valid_groups) else: raise AssertionError("Unsupported cipher selected") state.premaster_secret = state.key_exchange.\ processServerKeyExchange(public_key, server_key_exchange) state.handshake_messages.append(server_key_exchange) state.handshake_hashes.update(msg.write())