def test_verifyServerKeyExchange(self): KeyExchange.verifyServerKeyExchange(self.server_key_exchange, self.srv_pub_key, self.client_hello.random, bytearray(32), [(HashAlgorithm.sha1, SignatureAlgorithm.rsa)])
def test_ECDHE_key_exchange(self): srv_key_ex = self.keyExchange.makeServerKeyExchange('sha1') KeyExchange.verifyServerKeyExchange(srv_key_ex, self.srv_pub_key, self.client_hello.random, self.server_hello.random, [(HashAlgorithm.sha1, SignatureAlgorithm.rsa)]) curveName = GroupName.toStr(srv_key_ex.named_curve) curve = getCurveByName(curveName) generator = curve.generator cln_Xc = ecdsa.util.randrange(generator.order()) cln_Ys = decodeX962Point(srv_key_ex.ecdh_Ys, curve) cln_Yc = encodeX962Point(generator * cln_Xc) cln_key_ex = ClientKeyExchange(self.cipher_suite, (3, 3)) cln_key_ex.createECDH(cln_Yc) cln_S = cln_Ys * cln_Xc cln_premaster = numberToByteArray(cln_S.x(), getPointByteSize(cln_S)) srv_premaster = self.keyExchange.processClientKeyExchange(cln_key_ex) self.assertEqual(cln_premaster, srv_premaster)
def test_SRP_key_exchange(self): srv_key_ex = self.keyExchange.makeServerKeyExchange('sha256') KeyExchange.verifyServerKeyExchange(srv_key_ex, self.srv_pub_key, self.client_hello.random, self.server_hello.random, [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)]) a = bytesToNumber(getRandomBytes(32)) A = powMod(srv_key_ex.srp_g, a, srv_key_ex.srp_N) x = makeX(srv_key_ex.srp_s, bytearray(b'user'), bytearray(b'password')) v = powMod(srv_key_ex.srp_g, x, srv_key_ex.srp_N) u = makeU(srv_key_ex.srp_N, A, srv_key_ex.srp_B) k = makeK(srv_key_ex.srp_N, srv_key_ex.srp_g) S = powMod((srv_key_ex.srp_B - (k*v)) % srv_key_ex.srp_N, a+(u*x), srv_key_ex.srp_N) cln_premaster = numberToByteArray(S) cln_key_ex = ClientKeyExchange(self.cipher_suite, (3, 3)).createSRP(A) srv_premaster = self.keyExchange.processClientKeyExchange(cln_key_ex) self.assertEqual(cln_premaster, srv_premaster)
def test_signServerKeyExchange_with_sha1_in_TLS1_2(self): def m(leght): return bytearray(leght) with mock.patch('tlslite.utils.rsakey.getRandomBytes', m): srv_private_key = parsePEMKey(srv_raw_key, private=True) client_hello = ClientHello() cipher_suite = CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA server_hello = ServerHello().create((3, 3), bytearray(32), bytearray(0), cipher_suite) keyExchange = KeyExchange(cipher_suite, client_hello, server_hello, srv_private_key) server_key_exchange = ServerKeyExchange(cipher_suite, (3, 3)) \ .createDH(5, 2, 3) keyExchange.clientHello.random = bytearray(len(keyExchange.clientHello.random)) keyExchange.serverHello.random = bytearray(len(keyExchange.clientHello.random)) getRandomBytes = mock.Mock( return_value=bytearray(b'0')) keyExchange.signServerKeyExchange(server_key_exchange, 'rsa_pss_sha256') print(repr(server_key_exchange.signature)) self.assertEqual(server_key_exchange.signature,bytearray(b'E\xae\x8e\xbe~RU\n\xab4\x8e\x10y\x94\x01\xdfVr\x8b\x03\xa4\xb7\x9dI\xf1\xb7\x16\xfa\xa0-\x9a\x16^pZ\x979\xc2&\xa5\xfcU\x9a"\xc7~u\x1e_y\xc1w\x91\x98L\x10\xb4\xed\x103\xdf\xac\xba\x19Q\x0e\x8an\x13\x99\x8d1\x17XK\x9a\x00\xcdno\xc7\xae\x92:pU\xf8\xfbl\xeeg\xe0s\x03\xc8\xcb\xe5\xc4\xb9z\xcf\nv\xca\x80`\xbe\xc9\x85\xcfM\x89\xaeE\xf0\xa1\xd8`\x99\x93\xa0Bp\x1cwW\xce\x8e'))
def test_verifyServerKeyExchange_with_invalid_hash(self): with self.assertRaises(TLSIllegalParameterException): KeyExchange.verifyServerKeyExchange(self.server_key_exchange, self.srv_pub_key, self.client_hello.random, bytearray(32), [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)])
def test_verifyServerKeyExchange_with_damaged_signature(self): self.server_key_exchange.signature[-1] ^= 0x01 with self.assertRaises(TLSDecryptionFailed): KeyExchange.verifyServerKeyExchange(self.server_key_exchange, self.srv_pub_key, self.client_hello.random, bytearray(32), [(HashAlgorithm.sha1, SignatureAlgorithm.rsa)])
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 generate(self, status): """Create a CertificateVerify message""" if self.version is None: self.version = status.version if self.sig_type is None and self.version >= (3, 3): cert_req = next((msg for msg in status.handshake_messages[::-1] if isinstance(msg, CertificateRequest)), None) if cert_req is not None: self.sig_type = next((sig for sig in cert_req.supported_signature_algs if sig[1] == SignatureAlgorithm.rsa), None) if self.sig_type is None: self.sig_type = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) # TODO: generate a random key if none provided if self.private_key is None: raise ValueError("Can't create a signature without private key!") verify_bytes = KeyExchange.calcVerifyBytes(status.version, status.handshake_hashes, self.sig_type, status.premaster_secret, status.client_random, status.server_random) signature = self.private_key.sign(verify_bytes) cert_verify = CertificateVerify(status.version) cert_verify.create(signature, self.sig_type) self.msg = cert_verify return cert_verify
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 generate(self, status): """Create a CertificateVerify message""" if self.msg_version is None: self.msg_version = status.version if self.sig_version is None: self.sig_version = self.msg_version if self.msg_alg is None and self.msg_version >= (3, 3): cert_req = next((msg for msg in status.handshake_messages[::-1] if isinstance(msg, CertificateRequest)), None) if cert_req is not None: self.msg_alg = next( (sig for sig in cert_req.supported_signature_algs if sig[1] == SignatureAlgorithm.rsa), None) if self.msg_alg is None: self.msg_alg = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) if self.sig_alg is None: self.sig_alg = self.msg_alg # TODO: generate a random key if none provided if self.private_key is None: raise ValueError("Can't create a signature without private key!") verify_bytes = KeyExchange.calcVerifyBytes(self.sig_version, status.handshake_hashes, self.sig_alg, status.premaster_secret, status.client_random, status.server_random) signature = self.private_key.sign(verify_bytes) cert_verify = CertificateVerify(self.msg_version) cert_verify.create(signature, self.msg_alg) self.msg = cert_verify return cert_verify
def test_signServerKeyExchange_in_TLS1_1(self): srv_private_key = parsePEMKey(srv_raw_key, private=True) client_hello = ClientHello() cipher_suite = CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA server_hello = ServerHello().create((3, 2), bytearray(32), bytearray(0), cipher_suite) keyExchange = KeyExchange(cipher_suite, client_hello, server_hello, srv_private_key) server_key_exchange = ServerKeyExchange(cipher_suite, (3, 2))\ .createDH(5, 2, 3) keyExchange.signServerKeyExchange(server_key_exchange) self.assertEqual(server_key_exchange.write(), self.expected_tls1_1_SKE)
def test_signServerKeyExchange_in_TLS1_1_signature_invalid(self): srv_private_key = parsePEMKey(srv_raw_key, private=True) client_hello = ClientHello() cipher_suite = CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA server_hello = ServerHello().create((3, 2), bytearray(32), bytearray(0), cipher_suite) keyExchange = KeyExchange(cipher_suite, client_hello, server_hello, srv_private_key) server_key_exchange = ServerKeyExchange(cipher_suite, (3, 2)) \ .createDH(5, 2, 3) with self.assertRaises(TLSInternalError): keyExchange.privateKey.sign = mock.Mock( return_value=bytearray(b'wrong')) keyExchange.signServerKeyExchange(server_key_exchange)
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' ))
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_ECDHE_key_exchange_with_invalid_CKE(self): srv_key_ex = self.keyExchange.makeServerKeyExchange('sha1') KeyExchange.verifyServerKeyExchange(srv_key_ex, self.srv_pub_key, self.client_hello.random, self.server_hello.random, [(HashAlgorithm.sha1, SignatureAlgorithm.rsa)]) curveName = GroupName.toStr(srv_key_ex.named_curve) curve = getCurveByName(curveName) generator = curve.generator cln_Xc = ecdsa.util.randrange(generator.order()) cln_Ys = decodeX962Point(srv_key_ex.ecdh_Ys, curve) cln_Yc = encodeX962Point(generator * cln_Xc) cln_key_ex = ClientKeyExchange(self.cipher_suite, (3, 3)) cln_key_ex.createECDH(cln_Yc) cln_key_ex.ecdh_Yc[-1] ^= 0x01 with self.assertRaises(TLSIllegalParameterException): self.keyExchange.processClientKeyExchange(cln_key_ex)
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' ))
def test___init__(self): keyExchange = KeyExchange(0, None, None, None) self.assertIsNotNone(keyExchange)
def test_verifyServerKeyExchange_in_TLS1_1(self): KeyExchange.verifyServerKeyExchange(self.ske_tls1_1, self.srv_pub_key, self.client_hello.random, bytearray(32), None)
def test_makeServerKeyExchange(self): keyExchange = KeyExchange(0, None, None, None) with self.assertRaises(NotImplementedError): keyExchange.makeServerKeyExchange()
def generate(self, status): """Create a CertificateVerify message.""" if self.msg_version is None: self.msg_version = status.version if self.sig_version is None: self.sig_version = self.msg_version if self.msg_alg is None and self.msg_version >= (3, 3): cert_req = next((msg for msg in status.handshake_messages[::-1] if isinstance(msg, CertificateRequest)), None) if cert_req is not None: self.msg_alg = next( (sig for sig in cert_req.supported_signature_algs if sig[1] == SignatureAlgorithm.rsa or sig[0] == 8 and sig[1] in (4, 5, 6)), None) if self.msg_alg is None: self.msg_alg = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) if self.sig_alg is None: self.sig_alg = self.msg_alg # we need a copy of the handshake hashes for use in Extended Master # Secret calculation status.certificate_verify_handshake_hashes = \ status.handshake_hashes.copy() # TODO: generate a random key if none provided if self.signature is not None: signature = self.signature else: if self.private_key is None: raise ValueError("Can't create a signature without " "private key!") verify_bytes = KeyExchange.calcVerifyBytes(self.sig_version, status.handshake_hashes, self.sig_alg, status.premaster_secret, status.client_random, status.server_random) # we don't have to handle non pkcs1 padding because the # calcVerifyBytes does everything scheme = SignatureScheme.toRepr(self.sig_alg) hashName = None saltLen = 0 if scheme is None: padding = "pkcs1" else: padding = SignatureScheme.getPadding(scheme) if padding == 'pss': hashName = SignatureScheme.getHash(scheme) if self.rsa_pss_salt_len is None: self.rsa_pss_salt_len = \ getattr(hashlib, hashName)().digest_size def _newRawPrivateKeyOp(self, m, original_rawPrivateKeyOp, subs=None, xors=None): signBytes = numberToByteArray(m, numBytes(self.n)) signBytes = substitute_and_xor(signBytes, subs, xors) m = bytesToNumber(signBytes) return original_rawPrivateKeyOp(m) oldPrivateKeyOp = self.private_key._rawPrivateKeyOp self.private_key._rawPrivateKeyOp = \ partial(_newRawPrivateKeyOp, self.private_key, original_rawPrivateKeyOp=oldPrivateKeyOp, subs=self.padding_subs, xors=self.padding_xors) signature = self.private_key.sign(verify_bytes, padding, hashName, self.rsa_pss_salt_len) self.private_key._rawPrivateKeyOp = oldPrivateKeyOp cert_verify = CertificateVerify(self.msg_version) cert_verify.create(signature, self.msg_alg) self.msg = cert_verify return cert_verify
def generate(self, status): """Create a CertificateVerify message.""" if self.msg_version is None: self.msg_version = status.version if self.sig_version is None: self.sig_version = self.msg_version if self.msg_alg is None and self.msg_version >= (3, 3): cert_req = next((msg for msg in status.handshake_messages[::-1] if isinstance(msg, CertificateRequest)), None) if cert_req is not None: self.msg_alg = next((sig for sig in cert_req.supported_signature_algs if sig[1] == SignatureAlgorithm.rsa or sig[0] == 8 and sig[1] in (4, 5, 6)), None) if self.msg_alg is None: self.msg_alg = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) if self.sig_alg is None: self.sig_alg = self.msg_alg # TODO: generate a random key if none provided if self.signature is not None: signature = self.signature else: if self.private_key is None: raise ValueError("Can't create a signature without " "private key!") verify_bytes = KeyExchange.calcVerifyBytes(self.sig_version, status.handshake_hashes, self.sig_alg, status.premaster_secret, status.client_random, status.server_random) # we don't have to handle non pkcs1 padding because the # calcVerifyBytes does everything scheme = SignatureScheme.toRepr(self.sig_alg) hashName = None saltLen = 0 if scheme is None: padding = "pkcs1" else: padding = SignatureScheme.getPadding(scheme) if padding == 'pss': hashName = SignatureScheme.getHash(scheme) if self.rsa_pss_salt_len is None: self.rsa_pss_salt_len = \ getattr(hashlib, hashName)().digest_size def _newRawPrivateKeyOp(self, m, original_rawPrivateKeyOp, subs=None, xors=None): signBytes = numberToByteArray(m, numBytes(self.n)) signBytes = substitute_and_xor(signBytes, subs, xors) m = bytesToNumber(signBytes) # RSA operations are defined only on numbers that are smaller # than the modulus, so ensure the XORing or substitutions # didn't break it (especially necessary for pycrypto as # it raises exception in such case) if m > self.n: m %= self.n return original_rawPrivateKeyOp(m) oldPrivateKeyOp = self.private_key._rawPrivateKeyOp self.private_key._rawPrivateKeyOp = \ partial(_newRawPrivateKeyOp, self.private_key, original_rawPrivateKeyOp=oldPrivateKeyOp, subs=self.padding_subs, xors=self.padding_xors) try: signature = self.private_key.sign(verify_bytes, padding, hashName, self.rsa_pss_salt_len) finally: # make sure the changes are undone even if the signing fails self.private_key._rawPrivateKeyOp = oldPrivateKeyOp cert_verify = CertificateVerify(self.msg_version) cert_verify.create(signature, self.msg_alg) self.msg = cert_verify return cert_verify
def test_processClientKeyExchange(self): keyExchange = KeyExchange(0, None, None, None) with self.assertRaises(NotImplementedError): keyExchange.processClientKeyExchange(None)
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())
def test_makeClientKeyExchange(self): srv_h = ServerHello().create((3, 3), bytearray(32), bytearray(0), 0) keyExchange = KeyExchange(0, None, srv_h, None) self.assertIsInstance(keyExchange.makeClientKeyExchange(), ClientKeyExchange)
def test_processServerKeyExchange(self): keyExchange = KeyExchange(0, None, None, None) with self.assertRaises(NotImplementedError): keyExchange.processServerKeyExchange(None, None)