def test_digest_TLS1_0(self): hh = HandshakeHashes() self.assertEqual( b'\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\t\x98\xec\xf8B~\xda'\ b'9\xa3\xee^kK\r2U\xbf\xef\x95`\x18\x90\xaf\xd8\x07\t', hh.digest())
def test_copy(self): hh = HandshakeHashes() hh.update(b'text') hh2 = hh.copy() self.assertEqual(hh2.digest(), hh.digest())
def test_digest_sha256(self): hh = HandshakeHashes() self.assertEqual( b"\xe3\xb0\xc4B\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99o\xb9$'\xae"\ b"A\xe4d\x9b\x93L\xa4\x95\x99\x1bxR\xb8U", hh.digest('sha256'))
def test_digest_SSL3(self): hh = HandshakeHashes() self.assertEqual(bytearray( b'\xb5Q\x15\xa4\xcd\xff\xfdF\xa6\x9c\xe2\x0f\x83~\x948\xc3\xb5'\ b'\xc1\x8d\xb6|\x10n@a\x97\xccG\xfeI\xa8s T\\'), hh.digestSSL(bytearray(48), b''))
class TestCalcExtendedMasterSecret(unittest.TestCase): def setUp(self): self.handshakeHashes = HandshakeHashes() self.handshakeHashes.update(bytearray(48)) def test_with_TLS_1_0(self): ret = calcExtendedMasterSecret((3, 1), 0, bytearray(48), self.handshakeHashes) self.assertEqual( ret, bytearray( b'/\xe9\x86\xda\xda\xa9)\x1eyJ\xc9\x13E\xe4\xfc\xe7\x842m7(\xb4' b'\x98\xb7\xbc\xa5\xda\x1d\xf3\x15\xea\xdf:i\xeb\x9bA\x8f\xe7' b'\xd4<\xe0\xe8\x1d\xa0\xf0\x10\x83')) def test_with_TLS_1_2(self): ret = calcExtendedMasterSecret((3, 3), 0, bytearray(48), self.handshakeHashes) self.assertEqual( ret, bytearray( b'\x03\xc93Yx\xcbjSEmz*\x0b\xc3\xc04G\xf3\xe3{\xee\x13\x8b\xac' b'\xd7\xb7\xe6\xbaY\x86\xd5\xf2o?\x8f\xc6\xf2\x19\x1d\x06\xe0N' b'\xb5\xcaJX\xe8\x1d')) def test_with_TLS_1_2_and_SHA384_PRF(self): ret = calcExtendedMasterSecret( (3, 3), CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384, bytearray(48), self.handshakeHashes) self.assertEqual( ret, bytearray( b"\xd6\xed}K\xfbo\xb2\xdb\xa4\xee\xa1\x0f\x8f\x07*\x84w/\xbf_" b"\xbd\xc1U^\x93\xcf\xe8\xca\x82\xb7_B\xa3O\xd9V\x86\x12\xfd\x08" b"$\x92\'L\xae\xc0@\x01"))
def setUp(self): cert_chain = X509CertChain([X509().parse(srv_raw_certificate)]) self.clnt_pub_key = cert_chain.getEndEntityPublicKey() self.cipher_suite = CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA self.clnt_private_key = parsePEMKey(srv_raw_key, private=True) self.handshake_hashes = HandshakeHashes() self.handshake_hashes.update(bytearray(b'\xab'*32))
def test_digest_sha224(self): hh = HandshakeHashes() self.assertEqual(( b'\xd1J\x02\x8c*:+\xc9Ga\x02\xbb(\x824\xc4\x15\xa2\xb0' b'\x1f\x82\x8e\xa6*\xc5\xb3\xe4/'), hh.digest('sha224'))
def test_digest_sha512(self): hh = HandshakeHashes() self.assertEqual( (b'\xcf\x83\xe15~\xef\xb8\xbd\xf1T(P\xd6m\x80\x07\xd6 ' b'\xe4\x05\x0bW\x15\xdc\x83\xf4\xa9!\xd3l\xe9\xceG\xd0' b'\xd1<]\x85\xf2\xb0\xff\x83\x18\xd2\x87~\xec/c\xb91' b'\xbdGAz\x81\xa582z\xf9\'\xda>'), hh.digest('sha512'))
def test_digest_with_repeated_calls(self): hh = HandshakeHashes() hh.update(b'text') self.assertEqual(hh.digest(), hh.digest()) hh.update(b'ext') self.assertEqual(hh.digest('sha256'), hh.digest('sha256'))
def test_digest_with_partial_writes(self): hh = HandshakeHashes() hh.update(b'text') hh2 = HandshakeHashes() hh2.update(b'te') hh2.update(b'xt') self.assertEqual(hh.digest(), hh2.digest())
def test_digest_sha512(self): hh = HandshakeHashes() self.assertEqual(( b'\xcf\x83\xe15~\xef\xb8\xbd\xf1T(P\xd6m\x80\x07\xd6 ' b'\xe4\x05\x0bW\x15\xdc\x83\xf4\xa9!\xd3l\xe9\xceG\xd0' b'\xd1<]\x85\xf2\xb0\xff\x83\x18\xd2\x87~\xec/c\xb91' b'\xbdGAz\x81\xa582z\xf9\'\xda>'), hh.digest('sha512'))
def test_with_handshake_hashes(self): secret = bytearray(32) label = bytearray(b'exporter') handshake_hashes = HandshakeHashes() handshake_hashes.update(bytearray(8)) algorithm = "sha256" self.assertEqual(derive_secret(secret, label, handshake_hashes, algorithm), bytearray(b'\t\xec\x01W[Y\xdcP\xac\xebu\x13\xe6\x98' b'\x19\xccu;\xfa\x90\xc9\xe3\xc1\xe7\xb7' b'\xcf\x0c\x97;x\xf0F'))
def test_with_handshake_hashes(self): secret = bytearray(32) label = bytearray(b'exporter') handshake_hashes = HandshakeHashes() handshake_hashes.update(bytearray(8)) algorithm = "sha256" self.assertEqual( derive_secret(secret, label, handshake_hashes, algorithm), bytearray(b'\t\xec\x01W[Y\xdcP\xac\xebu\x13\xe6\x98' b'\x19\xccu;\xfa\x90\xc9\xe3\xc1\xe7\xb7' b'\xcf\x0c\x97;x\xf0F'))
def __init__(self): """Prepare object for keeping connection state""" self.msg_sock = None # cipher negotiated in connection self.cipher = 0 # version proposed in client hello, and later negotiated in connection self.version = (3, 3) # hashes of all handshake messages exchanged so far self.handshake_hashes = HandshakeHashes() # all handshake messages exchanged so far self.handshake_messages = [] # are we a client or server side of connection (influences just the # way encryption and MAC keys are calculated) self.client = True # calculated value for premaster secret self.premaster_secret = bytearray(0) # negotiated value for master secret self.master_secret = bytearray(0) # random values shared by peers self.server_random = bytearray(0) self.client_random = bytearray(0) # Finished message data for secure renegotiation self.client_verify_data = bytearray(0) self.server_verify_data = bytearray(0)
def __init__(self): """Prepare object for keeping connection state""" self.msg_sock = None # cipher negotiated in connection self.cipher = 0 # version proposed in client hello self.client_version = (3, 3) # version negotiated in connection self.version = (3, 3) # hashes of all handshake messages exchanged so far self.handshake_hashes = HandshakeHashes() # hash of all messages exchanged up to Certificate Verify, if CV was # used on connection self.certificate_verify_handshake_hashes = None # all handshake messages exchanged so far self.handshake_messages = [] # are we a client or server side of connection (influences just the # way encryption and MAC keys are calculated) self.client = True # calculated value for premaster secret self.premaster_secret = bytearray(0) # negotiated value for master secret self.master_secret = bytearray(0) # random values shared by peers self.server_random = bytearray(0) self.client_random = bytearray(0) # session ID set by server self.session_id = bytearray(0) # Finished message data for secure renegotiation self.client_verify_data = bytearray(0) self.server_verify_data = bytearray(0) # Whether we are currently resuming a previously negotiated session self.resuming = False # variable holding the intermediate state for DHE (and similar) key # exchanges self.key_exchange = None # Whether the session we're currently using is using extended master # secret calculation defined in RFC 7627 self.extended_master_secret = False # Whether the session we're currently using is using # EncryptThenMAC extension defined in RFC 7366 self.encrypt_then_mac = False
class TestCalcVerifyBytes(unittest.TestCase): def setUp(self): self.handshake_hashes = HandshakeHashes() self.handshake_hashes.update(bytearray(b'\xab'*32)) def test_with_TLS1_2(self): vrfy = KeyExchange.calcVerifyBytes((3, 3), self.handshake_hashes, (HashAlgorithm.sha1, SignatureAlgorithm.rsa), None, None, None) self.assertEqual(vrfy, bytearray( # PKCS#1 prefix b'0!0\t\x06\x05+\x0e\x03\x02\x1a\x05\x00\x04\x14' # SHA1 hash b'L3\x81\xad\x1b\xc2\x14\xc0\x8e\xba\xe4\xb8\xa2\x9d(6V1\xfb\xb0')) def test_with_TLS1_1(self): vrfy = KeyExchange.calcVerifyBytes((3, 2), self.handshake_hashes, None, None, None, None) self.assertEqual(vrfy, bytearray( # MD5 hash b'\xe9\x9f\xb4\xd24\xe9\xf41S\xe6?\xa5\xfe\xad\x16\x14' # SHA1 hash b'L3\x81\xad\x1b\xc2\x14\xc0\x8e\xba\xe4\xb8\xa2\x9d(6V1\xfb\xb0' )) def test_with_SSL3(self): vrfy = KeyExchange.calcVerifyBytes((3, 0), self.handshake_hashes, None, bytearray(b'\x04'*48), bytearray(b'\xaa'*32), bytearray(b'\xbb'*32)) self.assertEqual(vrfy, bytearray( b'r_\x06\xd2(\\}v\x87\xfc\xf5\xa2h\xd6S\xd8' b'\xed=\x9b\xe3\xd9_%qe\xa3k\xf5\x85\x0e?\x9fr\xfaML' ))
class TestCalcExtendedMasterSecret(unittest.TestCase): def setUp(self): self.handshakeHashes = HandshakeHashes() self.handshakeHashes.update(bytearray(48)) def test_with_TLS_1_0(self): ret = calcExtendedMasterSecret((3, 1), 0, bytearray(48), self.handshakeHashes) self.assertEqual(ret, bytearray( b'/\xe9\x86\xda\xda\xa9)\x1eyJ\xc9\x13E\xe4\xfc\xe7\x842m7(\xb4' b'\x98\xb7\xbc\xa5\xda\x1d\xf3\x15\xea\xdf:i\xeb\x9bA\x8f\xe7' b'\xd4<\xe0\xe8\x1d\xa0\xf0\x10\x83' )) def test_with_TLS_1_2(self): ret = calcExtendedMasterSecret((3, 3), 0, bytearray(48), self.handshakeHashes) self.assertEqual(ret, bytearray( b'\x03\xc93Yx\xcbjSEmz*\x0b\xc3\xc04G\xf3\xe3{\xee\x13\x8b\xac' b'\xd7\xb7\xe6\xbaY\x86\xd5\xf2o?\x8f\xc6\xf2\x19\x1d\x06\xe0N' b'\xb5\xcaJX\xe8\x1d' )) def test_with_TLS_1_2_and_SHA384_PRF(self): ret = calcExtendedMasterSecret((3, 3), CipherSuite. TLS_RSA_WITH_AES_256_GCM_SHA384, bytearray(48), self.handshakeHashes) self.assertEqual(ret, bytearray( b"\xd6\xed}K\xfbo\xb2\xdb\xa4\xee\xa1\x0f\x8f\x07*\x84w/\xbf_" b"\xbd\xc1U^\x93\xcf\xe8\xca\x82\xb7_B\xa3O\xd9V\x86\x12\xfd\x08" b"$\x92\'L\xae\xc0@\x01" ))
def _setup_tls13_handshake_keys(self, state): """Prepare handshake ciphers for the HRR handling""" prf_name = state.prf_name ch_hash = self._ch_hh.digest(prf_name) new_hh = HandshakeHashes() writer = Writer() writer.add(HandshakeType.message_hash, 1) writer.addVarSeq(ch_hash, 1, 3) new_hh.update(writer.bytes) new_hh.update(self._msg.write()) state.handshake_hashes = new_hh
def test_digest_md5(self): hh = HandshakeHashes() self.assertEqual( b"\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\t\x98\xec\xf8B~", hh.digest('md5'))
class TestCalcFinished(unittest.TestCase): def setUp(self): self.hhashes = HandshakeHashes() self.hhashes.update(bytearray(10))
def setUp(self): self.hhashes = HandshakeHashes() self.hhashes.update(bytearray(10))
def test___init__(self): hh = HandshakeHashes() self.assertIsNotNone(hh)
def test_update_with_str(self): hh = HandshakeHashes() hh.update(b'text')
def test_update(self): hh = HandshakeHashes() hh.update(bytearray(10))
def setUp(self): self.handshake_hashes = HandshakeHashes() self.handshake_hashes.update(bytearray(b'\xab'*32))
def test_digest_sha1(self): hh = HandshakeHashes() self.assertEqual( b"\xda9\xa3\xee^kK\r2U\xbf\xef\x95`\x18\x90\xaf\xd8\x07\t", hh.digest('sha1'))
class TestMakeCertificateVerify(unittest.TestCase): def setUp(self): cert_chain = X509CertChain([X509().parse(srv_raw_certificate)]) self.clnt_pub_key = cert_chain.getEndEntityPublicKey() self.cipher_suite = CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA self.clnt_private_key = parsePEMKey(srv_raw_key, private=True) self.handshake_hashes = HandshakeHashes() self.handshake_hashes.update(bytearray(b'\xab'*32)) def test_with_TLS1_2(self): certificate_request = CertificateRequest((3, 3)) certificate_request.create([CertificateType.x509], [], [(HashAlgorithm.sha256, SignatureAlgorithm.rsa), (HashAlgorithm.sha1, SignatureAlgorithm.rsa)]) certVerify = KeyExchange.makeCertificateVerify((3, 3), self.handshake_hashes, [(HashAlgorithm.sha1, SignatureAlgorithm.rsa), (HashAlgorithm.sha512, SignatureAlgorithm.rsa)], self.clnt_private_key, certificate_request, None, None, None) self.assertIsNotNone(certVerify) self.assertEqual(certVerify.version, (3, 3)) self.assertEqual(certVerify.signatureAlgorithm, (HashAlgorithm.sha1, SignatureAlgorithm.rsa)) self.assertEqual(certVerify.signature, bytearray( b'.\x03\xa2\xf0\xa0\xfb\xbeUs\xdb\x9b\xea\xcc(\xa6:l\x84\x8e\x13' b'\xa1\xaa\xdb1P\xe9\x06\x876\xbe+\xe92\x89\xaa\xa5EU\x07\x9a\xde' b'\xd37\xafGCR\xdam\xa2v\xde\xceeFI\x80:ZtL\x96\xafZ\xe2\xe2\xce/' b'\x9f\x82\xfe\xdb*\x94\xa8\xbd\xd9Hl\xdc\xc8\xbf\x9b=o\xda\x06' b'\xfa\x9e\xbfB+05\xc6\xda\xdf\x05\xf2m[\x18\x11\xaf\x184\x12\x9d' b'\xb4:\x9b\xc1U\x1c\xba\xa3\x05\xceOn\x0fY\xcaK*\x0b\x04\xa5' )) def test_with_TLS1_2_and_no_overlap(self): certificate_request = CertificateRequest((3, 3)) certificate_request.create([CertificateType.x509], [], [(HashAlgorithm.sha256, SignatureAlgorithm.rsa), (HashAlgorithm.sha224, SignatureAlgorithm.rsa)]) certVerify = KeyExchange.makeCertificateVerify((3, 3), self.handshake_hashes, [(HashAlgorithm.sha1, SignatureAlgorithm.rsa), (HashAlgorithm.sha512, SignatureAlgorithm.rsa)], self.clnt_private_key, certificate_request, None, None, None) self.assertIsNotNone(certVerify) self.assertEqual(certVerify.version, (3, 3)) # when there's no overlap, we select the most wanted from our side self.assertEqual(certVerify.signatureAlgorithm, (HashAlgorithm.sha1, SignatureAlgorithm.rsa)) self.assertEqual(certVerify.signature, bytearray( b'.\x03\xa2\xf0\xa0\xfb\xbeUs\xdb\x9b\xea\xcc(\xa6:l\x84\x8e\x13' b'\xa1\xaa\xdb1P\xe9\x06\x876\xbe+\xe92\x89\xaa\xa5EU\x07\x9a\xde' b'\xd37\xafGCR\xdam\xa2v\xde\xceeFI\x80:ZtL\x96\xafZ\xe2\xe2\xce/' b'\x9f\x82\xfe\xdb*\x94\xa8\xbd\xd9Hl\xdc\xc8\xbf\x9b=o\xda\x06' b'\xfa\x9e\xbfB+05\xc6\xda\xdf\x05\xf2m[\x18\x11\xaf\x184\x12\x9d' b'\xb4:\x9b\xc1U\x1c\xba\xa3\x05\xceOn\x0fY\xcaK*\x0b\x04\xa5' )) def test_with_TLS1_1(self): certificate_request = CertificateRequest((3, 2)) certificate_request.create([CertificateType.x509], [], None) certVerify = KeyExchange.makeCertificateVerify((3, 2), self.handshake_hashes, None, self.clnt_private_key, certificate_request, None, None, None) self.assertIsNotNone(certVerify) self.assertEqual(certVerify.version, (3, 2)) self.assertIsNone(certVerify.signatureAlgorithm) self.assertEqual(certVerify.signature, bytearray( b'=X\x14\xf3\r6\x0b\x84\xde&J\x15\xa02M\xc8\xf1?\xa0\x10U\x1e\x0b' b'\x95^\xa19\x14\xf5\xf1$\xe3U[\xb4/\xe7AY(\xee]\xff\x97H\xb8\xa9' b'\x8b\x96n\xa6\xf5\x0f\xffd\r\x08/Hs6`wi8\xc4\x02\xa4}a\xcbS\x99' b'\x01;\x0e\x88oj\x9a\x02\x98Y\xb5\x00$f@>\xd8\x0cS\x95\xa8\x9e' b'\x14uU\\Z\xd0.\xe7\x01_y\x1d\xea\xad\x1b\xf8c\xa6\xc9@\xc6\x90' b'\x19~&\xd9\xaa\xc2\t,s\xde\xb1' ))
printTestVectorBytes("SERVER_CHANGE_CIPHER_SPEC", s_sent[0][-6:]) printTestVectorBytes("SERVER_ENCRYPTED_EXTENSIONS_AND_FINISHED", s_sent[1]) printTestVectorBytes("SERVER_APP_DATA", s_sent[2]) printTestVectorBytes("SERVER_APP_DATA_2", s_sent[3]) printTestVectorBytes("SERVER_CLOSE", s_sent[4]) assert len(s_sent) == 5 print("\n") # For some additional tests of key generation, we use tlslite-ng's low-level # derivation functions to run the TLS1.3 keyschedule. It doesn't seem to expose # a nice API that encapsulates these calculations directly. printComment("Testcases for key derivation") prf = "sha256" transcript = HandshakeHashes() earlySecret = secureHMAC(bytearray(32), PSK, prf) printTestVectorBytes( "KEYS_EXT_BINDER", derive_secret(earlySecret, b"ext binder", None, prf) ) handshakeSecret = secureHMAC( derive_secret(earlySecret, b"derived", None, prf), bytearray(32), # No ECDHE, so use zeros. prf ) printTestVectorStr("KEYS_PLAINTEXT_TRANSCRIPT", b'fake plaintext transcript') transcript.update(b'fake plaintext transcript') printTestVectorBytes( "KEYS_CLIENT_HANDSHAKE_TRAFFIC_SECRET",
def test_digest_with_invalid_hash(self): hh = HandshakeHashes() with self.assertRaises(ValueError): hh.digest('md2')
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"))
def process(self, state): """Reset current running handshake protocol hashes""" state.handshake_hashes = HandshakeHashes()
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 """))
def test_digest_sha224(self): hh = HandshakeHashes() self.assertEqual( (b'\xd1J\x02\x8c*:+\xc9Ga\x02\xbb(\x824\xc4\x15\xa2\xb0' b'\x1f\x82\x8e\xa6*\xc5\xb3\xe4/'), hh.digest('sha224'))