def test__getNextRecord_with_too_big_record(self):
        mockSock = MockSocket(
            bytearray(b'\x16' +  # type - handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\xff\xff' +  # length
                      b'\x00' * 65536))

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        with self.assertRaises(TLSLocalAlert) as context:
            next(gen)

        self.assertEqual(str(context.exception), "record_overflow")
    def test__getNextRecord_with_empty_handshake(self):

        mock_sock = MockSocket(
            bytearray(b'\x16' +  # handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x00'  # length
                      ))

        record_layer = TLSRecordLayer(mock_sock)

        with self.assertRaises(TLSLocalAlert):
            for result in record_layer._getNextRecord():
                if result in (0, 1):
                    raise Exception("blocking socket")
                else:
                    break
    def test__getNextRecord_with_malformed_record(self):
        mockSock = MockSocket(
            bytearray(b'\x01' +  # wrong type
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x01' +  # length
                      b'\x00'))

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        gen = sock._getNextRecord()

        with self.assertRaises(TLSLocalAlert) as context:
            next(gen)

        self.assertEqual(str(context.exception), "illegal_parameter")
示例#4
0
    def test_keyingMaterialExporter_tls1_3_sha256(self):
        sock = MockSocket(bytearray(0))
        conn = TLSConnection(sock)
        conn._recordLayer.version = (3, 4)
        conn.session = Session()
        conn.session.cipherSuite = \
            CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        conn.session.exporterMasterSecret = \
            bytearray(b'0123456789abcdef0123456789abcdef' +
                      b'0123456789abcdef0123456789abcdef')

        mat = conn.keyingMaterialExporter(bytearray(b'test'), 20)
        self.assertEqual(
            mat,
            bytearray(
                b'W_h\x10\x83\xc0XD\x0fw\x0e\xfc/\x92\x8f\xb3\xfd\x13\x96\xd9')
        )
示例#5
0
    def test_recvMessage(self):
        defragmenter = Defragmenter()
        defragmenter.addStaticSize(21, 2)

        sock = MockSocket(bytearray(
            b'\x15' +           # message type
            b'\x03\x03' +       # TLS version
            b'\x00\x04' +       # payload length
            b'\xff\xff' +       # first message
            b'\xbb\xbb'         # second message
            ))

        msgSock = MessageSocket(sock, defragmenter)

        for res in msgSock.recvMessage():
            if res in (0, 1):
                self.assertTrue(False, "Blocking read")
            else:
                break

        self.assertIsNotNone(res)

        header, parser = res

        self.assertEqual(header.type, 21)
        self.assertEqual(header.version, (3, 3))
        self.assertEqual(header.length, 0)
        self.assertEqual(parser.bytes, bytearray(b'\xff\xff'))

        res = None

        for res in msgSock.recvMessage():
            if res in (0, 1):
                self.assertTrue(False, "Blocking read")
            else:
                break

        self.assertIsNotNone(res)

        header, parser = res

        self.assertEqual(header.type, 21)
        self.assertEqual(header.version, (3, 3))
        self.assertEqual(header.length, 0)
        self.assertEqual(parser.bytes, bytearray(b'\xbb\xbb'))
示例#6
0
    def test_queueMessage_with_conflicting_types(self):
        sock = MockSocket(bytearray())

        msgSock = MessageSocket(sock, None)
        msgSock.version = (3, 3)

        msg = Message(ContentType.handshake, bytearray(b'\xaa\xaa\xaa'))

        for res in msgSock.queueMessage(msg):
            if res in (0, 1):
                self.assertTrue(False, "Blocking queue")
            else:
                break

        self.assertEqual(len(sock.sent), 0)

        msg = Message(ContentType.alert, bytearray(b'\x02\x01'))

        for res in msgSock.queueMessage(msg):
            if res in (0, 1):
                self.assertTrue(False, "Blocking queue")
            else:
                break

        self.assertEqual(len(sock.sent), 1)
        self.assertEqual(bytearray(
            b'\x16' +
            b'\x03\x03' +
            b'\x00\x03' +
            b'\xaa'*3), sock.sent[0])

        for res in msgSock.flush():
            if res in (0, 1):
                self.assertTrue(False, "Blocking flush")
            else:
                break

        self.assertEqual(len(sock.sent), 2)
        self.assertEqual(bytearray(
            b'\x15' +
            b'\x03\x03' +
            b'\x00\x02' +
            b'\x02\x01'), sock.sent[1])
    def test_flushBlocking_with_data(self):
        sock = MockSocket(bytearray(), blockEveryOther=True)
        sock.blockWrite = True

        msgSock = MessageSocket(sock, None)
        msgSock.version = (3, 3)

        msg = Message(ContentType.handshake, bytearray(b'\xaa\xaa\xaa'))

        msgSock.queueMessageBlocking(msg)

        self.assertEqual(len(sock.sent), 0)

        msgSock.flushBlocking()

        self.assertEqual(len(sock.sent), 1)
        self.assertEqual(
            bytearray(b'\x16' + b'\x03\x03' + b'\x00\x03' + b'\xaa' * 3),
            sock.sent[0])
示例#8
0
    def test_flush(self):
        sock = MockSocket(bytearray())

        msgSock = MessageSocket(sock, None)

        for res in msgSock.flush():
            if res in (0, 1):
                self.assertTrue(False, "Blocking flush")
            else:
                break

        self.assertEqual(len(sock.sent), 0)

        for res in msgSock.flush():
            if res in (0, 1):
                self.assertTrue(False, "Blocking flush")
            else:
                break

        self.assertEqual(len(sock.sent), 0)
示例#9
0
    def test_sendMessage(self):
        sock = MockSocket(bytearray(), blockEveryOther=True)
        sock.blockWrite = True

        msgSock = MessageSocket(sock, None)
        msgSock.version = (3, 3)

        msg = Message(ContentType.handshake, bytearray(b'\xaa\xaa\xaa'))

        blocked = False
        for res in msgSock.queueMessage(msg):
            if res in (0, 1):
                blocked = True
            else:
                break

        # no write so no blocking
        self.assertFalse(blocked)
        self.assertEqual(len(sock.sent), 0)

        msg = Message(ContentType.alert, bytearray(b'\x02\x01'))

        blocked = False
        for res in msgSock.sendMessage(msg):
            if res in (0, 1):
                blocked = True
            else:
                break

        self.assertTrue(blocked)
        self.assertEqual(len(sock.sent), 2)
        self.assertEqual(bytearray(
            b'\x16' +
            b'\x03\x03' +
            b'\x00\x03' +
            b'\xaa'*3), sock.sent[0])
        self.assertEqual(bytearray(
            b'\x15' +
            b'\x03\x03' +
            b'\x00\x02' +
            b'\x02\x01'), sock.sent[1])
    def test__getNextRecord_with_trickling_socket(self):
        mockSock = MockSocket(
            bytearray(b'\x16' +  # type - handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x04' +  # length
                      b'\x00' * 4),
            maxRet=1)

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                self.assertTrue(False, "blocking socket")
            else:
                break

        header, data = result
        data = data.bytes

        self.assertEqual(bytearray(4), data)
    def test__getMsg_with_fragmented_message(self):

        mock_sock = MockSocket(
            bytearray(b'\x16' +  # handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x06' +  # payload length
                      b'\x02' +  # Server Hello
                      b'\x00\x00\x36' +  # hello length
                      b'\x03\x03' +  # TLSv1.2
                      # fragment end
                      b'\x16' +  # type - handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x34' +  # payload length:
                      b'\x00' * 32 +  # random
                      b'\x00' +  # session ID length
                      b'\x00\x2f' +  # cipher suite selected (AES128-SHA)
                      b'\x00' +  # compression null
                      b'\x00\x0e' +  # extensions length
                      b'\xff\x01' +  # renegotiation_info
                      b'\x00\x01' +  # ext length
                      b'\x00' +  # renegotiation info ext length - 0
                      b'\x00\x23' +  # session_ticket
                      b'\x00\x00' +  # ext length
                      b'\x00\x0f' +  # heartbeat extension
                      b'\x00\x01' +  # ext length
                      b'\x01'))  # peer is allowed to send requests

        record_layer = TLSRecordLayer(mock_sock)

        gen = record_layer._getMsg(ContentType.handshake,
                                   HandshakeType.server_hello)

        message = next(gen)

        if message in (0, 1):
            raise Exception("blocking")

        self.assertEqual(ServerHello, type(message))
        self.assertEqual((3, 3), message.server_version)
        self.assertEqual(0x002f, message.cipher_suite)
    def test__sendMsg_with_large_message(self):

        mock_sock = MockSocket(bytearray(0))

        record_layer = TLSRecordLayer(mock_sock)

        client_hello = ClientHello().create(
            (3, 3), bytearray(32), bytearray(0), [x for x in range(2**15 - 1)])

        gen = record_layer._sendMsg(client_hello)

        for result in gen:
            if result in (0, 1):
                self.assertTrue(False, "blocking")
            else:
                break

        # The maximum length that can be sent in single record is 2**14
        # record layer adds 5 byte on top of that
        self.assertEqual(len(mock_sock.sent), 5)
        for msg in mock_sock.sent:
            self.assertTrue(len(msg) <= 2**14 + 5)
    def test__sendMsg(self):
        mockSock = MockSocket(bytearray(0))
        sock = TLSRecordLayer(mockSock)
        sock.version = (3, 3)

        msg = Message(ContentType.handshake, bytearray(10))

        # XXX using private method
        for result in sock._sendMsg(msg, False):
            if result in (0, 1):
                self.assertTrue(False, "Blocking socket")
            else:
                break

        self.assertEqual(len(mockSock.sent), 1)
        self.assertEqual(
            bytearray(b'\x16' +  # handshake message
                      b'\x03\x03' +  # version
                      b'\x00\x0a' +  # payload length
                      b'\x00' * 10  # payload
                      ),
            mockSock.sent[0])
示例#14
0
    def test_queueMessage(self):
        sock = MockSocket(bytearray())

        msgSocket = MessageSocket(sock, None)

        msg = Message(ContentType.alert, bytearray(b'\xff\xbb'))

        for res in msgSocket.queueMessage(msg):
            if res in (0, 1):
                self.assertTrue(False, "Blocking queue")
            else:
                break

        self.assertEqual(len(sock.sent), 0)

        msg = Message(ContentType.alert, bytearray(b'\xff\xaa'))

        for res in msgSocket.queueMessage(msg):
            if res in (0, 1):
                self.assertTrue(False, "Blocking queue")
            else:
                break

        self.assertEqual(len(sock.sent), 0)

        for res in msgSocket.flush():
            if res in (0, 1):
                self.assertTrue(False, "Blocking flush")
            else:
                break

        self.assertEqual(len(sock.sent), 1)
        self.assertEqual(sock.sent[0], bytearray(
            b'\x15' +
            b'\x00\x00' +
            b'\x00\x04' +
            b'\xff\xbb' +
            b'\xff\xaa'))
    def test_write_with_BEAST_record_splitting_and_empty_write(self):
        mock_sock = MockSocket(bytearray(0))
        record_layer = TLSRecordLayer(mock_sock)

        record_layer.version = (3, 1)
        record_layer.closed = False
        record_layer._recordLayer.calcPendingStates(
            CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, bytearray(48),
            bytearray(32), bytearray(32), None)
        record_layer._recordLayer.changeWriteState()

        record_layer.write(bytearray(0))

        self.assertEqual(len(mock_sock.sent), 1)
        msg1 = mock_sock.sent[0]
        self.assertEqual(
            bytearray(
                b'\x17' +  # application data
                b'\x03\x01' +  # TLSv1.0
                b'\x00\x20'  # length 32 bytes = data(0) + MAC(20) + padding(12)
            ),
            msg1[:5])
        self.assertEqual(len(msg1[5:]), 32)
    def test__getNextRecord(self):
        mockSock = MockSocket(
            bytearray(b'\x16' +  # type - handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x04' +  # length
                      b'\x00' * 4))
        sock = TLSRecordLayer(mockSock)
        sock.version = (3, 3)

        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                self.assertTrue(False, "blocking socket")
            else:
                break

        header, data = result
        data = data.bytes

        self.assertEqual(data, bytearray(4))
        self.assertEqual(header.type, ContentType.handshake)
        self.assertEqual(header.version, (3, 3))
        self.assertEqual(header.length, 0)
示例#17
0
    def test_recvMessageBlocking(self):
        defragmenter = Defragmenter()
        defragmenter.addStaticSize(21, 2)

        sock = MockSocket(bytearray(
            b'\x15' +           # message type
            b'\x03\x03' +       # TLS version
            b'\x00\x02' +       # payload length
            b'\xff\xff'         # message
            ),
            blockEveryOther=True,
            maxRet=1)

        msgSock = MessageSocket(sock, defragmenter)

        res = msgSock.recvMessageBlocking()

        self.assertIsNotNone(res)

        header, parser = res

        self.assertEqual(header.type, 21)
        self.assertEqual(parser.bytes, bytearray(b'\xff\xff'))
    def test__getNextRecord_with_slow_socket(self):
        mockSock = MockSocket(
            bytearray(b'\x16' +  # type - handshake
                      b'\x03\x03' +  # TLSv1.2
                      b'\x00\x04' +  # length
                      b'\x00' * 4),
            maxRet=1,
            blockEveryOther=True)

        sock = TLSRecordLayer(mockSock)

        gotRetry = False
        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                gotRetry = True
            else:
                break

        header, data = result
        data = data.bytes

        self.assertTrue(gotRetry)
        self.assertEqual(bytearray(4), data)
    def test__getNextRecord_with_SSL2_record(self):
        mockSock = MockSocket(
            bytearray(b'\x80' +  # tag
                      b'\x04' +  # length
                      b'\x00' * 4))

        sock = TLSRecordLayer(mockSock)

        # XXX using private method!
        for result in sock._getNextRecord():
            if result in (0, 1):
                self.assertTrue(False, "blocking socket")
            else:
                break

        header, data = result
        data = data.bytes

        self.assertTrue(header.ssl2)
        self.assertEqual(ContentType.handshake, header.type)
        self.assertEqual(4, header.length)
        self.assertEqual((2, 0), header.version)

        self.assertEqual(bytearray(4), data)
示例#20
0
    def test(self):

        sock = MockSocket(server_hello_ciphertext)

        record_layer = RecordLayer(sock)

        ext = [SNIExtension().create(bytearray(b'server')),
               TLSExtension(extType=ExtensionType.renegotiation_info)
               .create(bytearray(b'\x00')),
               SupportedGroupsExtension().create([GroupName.x25519,
                                                  GroupName.secp256r1,
                                                  GroupName.secp384r1,
                                                  GroupName.secp521r1,
                                                  GroupName.ffdhe2048,
                                                  GroupName.ffdhe3072,
                                                  GroupName.ffdhe4096,
                                                  GroupName.ffdhe6144,
                                                  GroupName.ffdhe8192]),
               ECPointFormatsExtension().create([ECPointFormat.uncompressed]),
               TLSExtension(extType=35),
               ClientKeyShareExtension().create([KeyShareEntry().create(GroupName.x25519,
                                                client_key_public,
                                                client_key_private)]),
               SupportedVersionsExtension().create([TLS_1_3_DRAFT,
                                                    (3, 3), (3, 2)]),
               SignatureAlgorithmsExtension().create([(HashAlgorithm.sha256,
                                                       SignatureAlgorithm.ecdsa),
                                                      (HashAlgorithm.sha384,
                                                       SignatureAlgorithm.ecdsa),
                                                      (HashAlgorithm.sha512,
                                                       SignatureAlgorithm.ecdsa),
                                                      (HashAlgorithm.sha1,
                                                       SignatureAlgorithm.ecdsa),
                                                      SignatureScheme.rsa_pss_sha256,
                                                      SignatureScheme.rsa_pss_sha384,
                                                      SignatureScheme.rsa_pss_sha512,
                                                      SignatureScheme.rsa_pkcs1_sha256,
                                                      SignatureScheme.rsa_pkcs1_sha384,
                                                      SignatureScheme.rsa_pkcs1_sha512,
                                                      SignatureScheme.rsa_pkcs1_sha1,
                                                      (HashAlgorithm.sha256,
                                                       SignatureAlgorithm.dsa),
                                                      (HashAlgorithm.sha384,
                                                       SignatureAlgorithm.dsa),
                                                      (HashAlgorithm.sha512,
                                                       SignatureAlgorithm.dsa),
                                                      (HashAlgorithm.sha1,
                                                       SignatureAlgorithm.dsa)]),
                TLSExtension(extType=45).create(bytearray(b'\x01\x01')),
                TLSExtension(extType=ExtensionType.client_hello_padding)
                .create(bytearray(252))
               ]
        client_hello = ClientHello()
        client_hello.create((3, 3),
                            bytearray(b'\xaf!\x15k\x04\xdbc\x9ef\x15J\x1f\xe5'
                                      b'\xad\xfa\xea\xdf\x9eA4\x16\x00\rW\xb8'
                                      b'\xe1\x12mM\x11\x9a\x8b'),
                            bytearray(b''),
                            [CipherSuite.TLS_AES_128_GCM_SHA256,
                             CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
                             CipherSuite.TLS_AES_256_GCM_SHA384,
                             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                             CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                             0xCCA9,
                             CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
                             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
                             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
                             CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
                             CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
                             CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
                             CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
                             CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
                             CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
                             CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
                             0x0032,
                             CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
                             CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
                             0x0038,
                             CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
                             CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
                             0x0013,
                             CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
                             CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
                             CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256,
                             CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
                             CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256,
                             CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
                             CipherSuite.TLS_RSA_WITH_RC4_128_SHA,
                             CipherSuite.TLS_RSA_WITH_RC4_128_MD5],
                            extensions=ext)

        self.assertEqual(client_hello.write(), client_hello_ciphertext[5:])

        for result in record_layer.recvRecord():
            # check if non-blocking
            self.assertNotIn(result, (0, 1))
        header, parser = result
        hs_type = parser.get(1)
        self.assertEqual(hs_type, HandshakeType.server_hello)
        server_hello = ServerHello().parse(parser)

        self.assertEqual(server_hello.server_version, TLS_1_3_DRAFT)
        self.assertEqual(server_hello.cipher_suite, CipherSuite.TLS_AES_128_GCM_SHA256)

        server_key_share = server_hello.getExtension(ExtensionType.key_share)
        server_key_share = server_key_share.server_share

        self.assertEqual(server_key_share.group, GroupName.x25519)

        # for TLS_AES_128_GCM_SHA256:
        prf_name = 'sha256'
        prf_size = 256 // 8
        secret = bytearray(prf_size)
        psk = bytearray(prf_size)

        # early secret
        secret = secureHMAC(secret, psk, prf_name)

        self.assertEqual(secret,
                         str_to_bytearray(
                             "33ad0a1c607ec03b 09e6cd9893680ce2"
                             "10adf300aa1f2660 e1b22e10f170f92a"))

        # derive secret for handshake
        secret = derive_secret(secret, b"derived", None, prf_name)

        self.assertEqual(secret,
                         str_to_bytearray(
                             "6f2615a108c702c5 678f54fc9dbab697"
                             "16c076189c48250c ebeac3576c3611ba"))

        # extract secret "handshake"
        Z = x25519(client_key_private, server_key_share.key_exchange)

        self.assertEqual(Z,
                         str_to_bytearray(
                             "f677c3cdac26a755 455b130efa9b1a3f"
                             "3cafb153544ca46a ddf670df199d996e"))

        secret = secureHMAC(secret, Z, prf_name)

        self.assertEqual(secret,
                         str_to_bytearray(
                             "0cefce00d5d29fd0 9f5de36c86fc8e72"
                             "99b4ad11ba4211c6 7063c2cc539fc4f9"))

        handshake_hashes = HandshakeHashes()
        handshake_hashes.update(client_hello_plaintext)
        handshake_hashes.update(server_hello_payload)

        # derive "tls13 c hs traffic"
        c_hs_traffic = derive_secret(secret,
                                     bytearray(b'c hs traffic'),
                                     handshake_hashes,
                                     prf_name)
        self.assertEqual(c_hs_traffic,
                         str_to_bytearray(
                             "5a63db760b817b1b da96e72832333aec"
                             "6a177deeadb5b407 501ac10c17dac0a4"))
        s_hs_traffic = derive_secret(secret,
                                     bytearray(b's hs traffic'),
                                     handshake_hashes,
                                     prf_name)
        self.assertEqual(s_hs_traffic,
                         str_to_bytearray(
                             "3aa72a3c77b791e8 f4de243f9ccce172"
                             "941f8392aeb05429 320f4b572ccfe744"))

        # derive master secret
        secret = derive_secret(secret, b"derived", None, prf_name)

        self.assertEqual(secret,
                         str_to_bytearray(
                             "32cadf38f3089048 5c54bf4f1184eaa5"
                             "569eeef15a43f3c7 6ab33965a47c9ff6"))

        # extract secret "master
        secret = secureHMAC(secret, bytearray(prf_size), prf_name)

        self.assertEqual(secret,
                         str_to_bytearray(
                             "6c6d4b3e7c925460 82d7b7a32f6ce219"
                             "3804f1bb930fed74 5c6b93c71397f424"))
示例#21
0
 def prepare_mock_socket_with_handshake_failure(self):
     alertObj = Alert().create(AlertDescription.handshake_failure)
     alert = alertObj.write()
     header = RecordHeader3().create((3, 3), ContentType.alert, len(alert))
     return MockSocket(header.write() + alert)
示例#22
0
    def test(self):

        sock = MockSocket(server_hello_ciphertext)

        record_layer = RecordLayer(sock)

        ext = [
            SNIExtension().create(bytearray(b'server')),
            TLSExtension(extType=ExtensionType.renegotiation_info).create(
                bytearray(b'\x00')),
            SupportedGroupsExtension().create([
                GroupName.x25519, GroupName.secp256r1, GroupName.secp384r1,
                GroupName.secp521r1, GroupName.ffdhe2048, GroupName.ffdhe3072,
                GroupName.ffdhe4096, GroupName.ffdhe6144, GroupName.ffdhe8192
            ]),
            TLSExtension(extType=35),
            ClientKeyShareExtension().create([
                KeyShareEntry().create(GroupName.x25519, client_key_public,
                                       client_key_private)
            ]),
            SupportedVersionsExtension().create([(3, 4)]),
            SignatureAlgorithmsExtension().create([
                SignatureScheme.ecdsa_secp256r1_sha256,
                SignatureScheme.ecdsa_secp384r1_sha384,
                SignatureScheme.ecdsa_secp521r1_sha512,
                (HashAlgorithm.sha1, SignatureAlgorithm.ecdsa),
                SignatureScheme.rsa_pss_rsae_sha256,
                SignatureScheme.rsa_pss_rsae_sha384,
                SignatureScheme.rsa_pss_rsae_sha512,
                SignatureScheme.rsa_pkcs1_sha256,
                SignatureScheme.rsa_pkcs1_sha384,
                SignatureScheme.rsa_pkcs1_sha512,
                SignatureScheme.rsa_pkcs1_sha1,
                (HashAlgorithm.sha256, SignatureAlgorithm.dsa),
                (HashAlgorithm.sha384, SignatureAlgorithm.dsa),
                (HashAlgorithm.sha512, SignatureAlgorithm.dsa),
                (HashAlgorithm.sha1, SignatureAlgorithm.dsa)
            ]),
            TLSExtension(extType=45).create(bytearray(b'\x01\x01')),
            RecordSizeLimitExtension().create(16385)
        ]
        client_hello = ClientHello()
        client_hello.create((3, 3),
                            bytearray(b'\xcb4\xec\xb1\xe7\x81c'
                                      b'\xba\x1c8\xc6\xda\xcb'
                                      b'\x19jm\xff\xa2\x1a\x8d'
                                      b'\x99\x12\xec\x18\xa2'
                                      b'\xefb\x83\x02M\xec\xe7'),
                            bytearray(b''), [
                                CipherSuite.TLS_AES_128_GCM_SHA256,
                                CipherSuite.TLS_CHACHA20_POLY1305_SHA256,
                                CipherSuite.TLS_AES_256_GCM_SHA384
                            ],
                            extensions=ext)

        self.assertEqual(client_hello.write(), client_hello_ciphertext[5:])

        for result in record_layer.recvRecord():
            # check if non-blocking
            self.assertNotIn(result, (0, 1))
            break

        header, parser = result
        hs_type = parser.get(1)
        self.assertEqual(hs_type, HandshakeType.server_hello)
        server_hello = ServerHello().parse(parser)

        self.assertEqual(server_hello.server_version, (3, 3))
        self.assertEqual(server_hello.cipher_suite,
                         CipherSuite.TLS_AES_128_GCM_SHA256)

        server_key_share = server_hello.getExtension(ExtensionType.key_share)
        server_key_share = server_key_share.server_share

        self.assertEqual(server_key_share.group, GroupName.x25519)

        # for TLS_AES_128_GCM_SHA256:
        prf_name = 'sha256'
        prf_size = 256 // 8
        secret = bytearray(prf_size)
        psk = bytearray(prf_size)

        # early secret
        secret = secureHMAC(secret, psk, prf_name)

        self.assertEqual(
            secret,
            clean("""
                         33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c
                         e2 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a
                         """))

        # derive secret for handshake
        secret = derive_secret(secret, b"derived", None, prf_name)

        self.assertEqual(
            secret,
            clean("""
                         6f 26 15 a1 08 c7 02 c5 67 8f 54 fc 9d ba
                         b6 97 16 c0 76 18 9c 48 25 0c eb ea c3 57 6c 36 11 ba
                         """))

        # extract secret "handshake"
        Z = x25519(client_key_private, server_key_share.key_exchange)

        self.assertEqual(
            Z,
            clean("""
                         8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d
                         35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d
                         """))

        secret = secureHMAC(secret, Z, prf_name)

        self.assertEqual(
            secret,
            clean("""
                         1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b
                         01 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac
                         """))

        handshake_hashes = HandshakeHashes()
        handshake_hashes.update(client_hello_plaintext)
        handshake_hashes.update(server_hello_payload)

        # derive "tls13 c hs traffic"
        c_hs_traffic = derive_secret(secret, bytearray(b'c hs traffic'),
                                     handshake_hashes, prf_name)
        self.assertEqual(
            c_hs_traffic,
            clean("""
                         b3 ed db 12 6e 06 7f 35 a7 80 b3 ab f4 5e
                         2d 8f 3b 1a 95 07 38 f5 2e 96 00 74 6a 0e 27 a5 5a 21
                         """))
        s_hs_traffic = derive_secret(secret, bytearray(b's hs traffic'),
                                     handshake_hashes, prf_name)
        self.assertEqual(
            s_hs_traffic,
            clean("""
                         b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d
                         37 b4 e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38
                         """))

        # derive master secret
        secret = derive_secret(secret, b"derived", None, prf_name)

        self.assertEqual(
            secret,
            clean("""
                         43 de 77 e0 c7 77 13 85 9a 94 4d b9 db 25
                         90 b5 31 90 a6 5b 3e e2 e4 f1 2d d7 a0 bb 7c e2 54 b4
                         """))

        # extract secret "master"
        secret = secureHMAC(secret, bytearray(prf_size), prf_name)

        self.assertEqual(
            secret,
            clean("""
                         18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a
                         47 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19
                         """))

        # derive write keys for handshake data
        server_hs_write_trafic_key = HKDF_expand_label(s_hs_traffic, b"key",
                                                       b"", 16, prf_name)

        self.assertEqual(
            server_hs_write_trafic_key,
            clean("""
                         3f ce 51 60 09 c2 17 27 d0 f2 e4 e8 6e
                         e4 03 bc
                         """))

        server_hs_write_trafic_iv = HKDF_expand_label(s_hs_traffic, b"iv", b"",
                                                      12, prf_name)

        self.assertEqual(
            server_hs_write_trafic_iv,
            clean("""
                         5d 31 3e b2 67 12 76 ee 13 00 0b 30
                         """))

        # derive key for Finished message
        server_finished_key = HKDF_expand_label(s_hs_traffic, b"finished", b"",
                                                prf_size, prf_name)
        self.assertEqual(
            server_finished_key,
            clean("""
                         00 8d 3b 66 f8 16 ea 55 9f 96 b5 37 e8 85
                         c3 1f c0 68 bf 49 2c 65 2f 01 f2 88 a1 d8 cd c1 9f c8
                         """))

        # Update the handshake transcript
        handshake_hashes.update(server_encrypted_extensions)
        handshake_hashes.update(server_certificate_message)
        handshake_hashes.update(server_certificateverify_message)
        hs_transcript = handshake_hashes.digest(prf_name)

        server_finished = secureHMAC(server_finished_key, hs_transcript,
                                     prf_name)

        self.assertEqual(
            server_finished,
            clean("""
                         9b 9b 14 1d 90 63 37 fb d2 cb dc e7 1d f4
                         de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07 18
                         """))

        server_finished_message = Finished((3, 4)).create(server_finished)
        server_finished_payload = server_finished_message.write()

        # update handshake transcript to include Finished payload
        handshake_hashes.update(server_finished_payload)

        # derive keys for client application traffic
        c_ap_traffic = derive_secret(secret, b"c ap traffic", handshake_hashes,
                                     prf_name)

        self.assertEqual(
            c_ap_traffic,
            clean("""
                         9e 40 64 6c e7 9a 7f 9d c0 5a f8 88 9b ce
                         65 52 87 5a fa 0b 06 df 00 87 f7 92 eb b7 c1 75 04 a5
                         """))

        # derive keys for server application traffic
        s_ap_traffic = derive_secret(secret, b"s ap traffic", handshake_hashes,
                                     prf_name)

        self.assertEqual(
            s_ap_traffic,
            clean("""
                         a1 1a f9 f0 55 31 f8 56 ad 47 11 6b 45 a9
                         50 32 82 04 b4 f4 4b fb 6b 3a 4b 4f 1f 3f cb 63 16 43
                         """))

        # derive exporter master secret
        exp_master = derive_secret(secret, b"exp master", handshake_hashes,
                                   prf_name)

        self.assertEqual(
            exp_master,
            clean("""
                         fe 22 f8 81 17 6e da 18 eb 8f 44 52 9e 67
                         92 c5 0c 9a 3f 89 45 2f 68 d8 ae 31 1b 43 09 d3 cf 50
                         """))

        # derive write traffic keys for app data
        server_write_traffic_key = HKDF_expand_label(s_ap_traffic, b"key", b"",
                                                     16, prf_name)

        self.assertEqual(
            server_write_traffic_key,
            clean("""
                         9f 02 28 3b 6c 9c 07 ef c2 6b b9 f2 ac
                         92 e3 56
                         """))

        server_write_traffic_iv = HKDF_expand_label(s_ap_traffic, b"iv", b"",
                                                    12, prf_name)

        self.assertEqual(
            server_write_traffic_iv,
            clean("""
                         cf 78 2b 88 dd 83 54 9a ad f1 e9 84
                         """))

        # derive read traffic keys for app data
        server_read_hs_key = HKDF_expand_label(c_hs_traffic, b"key", b"", 16,
                                               prf_name)

        self.assertEqual(
            server_read_hs_key,
            clean("""
                         db fa a6 93 d1 76 2c 5b 66 6a f5 d9 50
                         25 8d 01
                         """))

        server_read_hs_iv = HKDF_expand_label(c_hs_traffic, b"iv", b"", 12,
                                              prf_name)

        self.assertEqual(
            server_read_hs_iv,
            clean("""
                         5b d3 c7 1b 83 6e 0b 76 bb 73 26 5f
                         """))