1
2
3
4
5 """Handling of cryptographic operations for key exchange"""
6
7 from .mathtls import goodGroupParameters, makeK, makeU, makeX, calcMasterSecret
8 from .errors import TLSInsufficientSecurity, TLSUnknownPSKIdentity, \
9 TLSIllegalParameterException, TLSDecryptionFailed, TLSInternalError
10 from .messages import ServerKeyExchange, ClientKeyExchange, CertificateVerify
11 from .constants import SignatureAlgorithm, HashAlgorithm, CipherSuite, \
12 ExtensionType, GroupName, ECCurveType
13 from .utils.ecc import decodeX962Point, encodeX962Point, getCurveByName, \
14 getPointByteSize
15 from .utils.rsakey import RSAKey
16 from .utils.cryptomath import bytesToNumber, getRandomBytes, powMod, \
17 numBits, numberToByteArray
18 import ecdsa
21 """
22 Common API for calculating Premaster secret
23
24 NOT stable, will get moved from this file
25 """
26
27 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
28 """Initialize KeyExchange. privateKey is the signing private key"""
29 self.cipherSuite = cipherSuite
30 self.clientHello = clientHello
31 self.serverHello = serverHello
32 self.privateKey = privateKey
33
35 """
36 Create a ServerKeyExchange object
37
38 Returns a ServerKeyExchange object for the server's initial leg in the
39 handshake. If the key exchange method does not send ServerKeyExchange
40 (e.g. RSA), it returns None.
41 """
42 raise NotImplementedError()
43
45 """
46 Create a ClientKeyExchange object
47
48 Returns a ClientKeyExchange for the second flight from client in the
49 handshake.
50 """
51 return ClientKeyExchange(self.cipherSuite,
52 self.serverHello.server_version)
53
55 """
56 Process ClientKeyExchange and return premaster secret
57
58 Processes the client's ClientKeyExchange message and returns the
59 premaster secret. Raises TLSLocalAlert on error.
60 """
61 raise NotImplementedError()
62
65 """Process the server KEX and return premaster secret"""
66 raise NotImplementedError()
67
69 """
70 Sign a server key best matching supported algorithms
71
72 @type sigHash: str
73 @param sigHash: name of the hash used for signing
74 """
75 if self.serverHello.server_version >= (3, 3):
76 serverKeyExchange.signAlg = SignatureAlgorithm.rsa
77 serverKeyExchange.hashAlg = getattr(HashAlgorithm, sigHash)
78 hashBytes = serverKeyExchange.hash(self.clientHello.random,
79 self.serverHello.random)
80
81 if self.serverHello.server_version >= (3, 3):
82 hashBytes = RSAKey.addPKCS1Prefix(hashBytes, sigHash)
83
84 serverKeyExchange.signature = self.privateKey.sign(hashBytes)
85
86 if not serverKeyExchange.signature:
87 raise TLSInternalError("Empty signature")
88
89 if not self.privateKey.verify(serverKeyExchange.signature, hashBytes):
90 raise TLSInternalError("Server Key Exchange signature invalid")
91
92 @staticmethod
95 """Verify signature on the Server Key Exchange message
96
97 the only acceptable signature algorithms are specified by validSigAlgs
98 """
99 if serverKeyExchange.version >= (3, 3):
100 if (serverKeyExchange.hashAlg, serverKeyExchange.signAlg) not in \
101 validSigAlgs:
102 raise TLSIllegalParameterException("Server selected "
103 "invalid signature "
104 "algorithm")
105 assert serverKeyExchange.signAlg == SignatureAlgorithm.rsa
106 hashName = HashAlgorithm.toRepr(serverKeyExchange.hashAlg)
107 if hashName is None:
108 raise TLSIllegalParameterException("Unknown signature "
109 "algorithm")
110 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom)
111
112 if serverKeyExchange.version == (3, 3):
113 hashBytes = RSAKey.addPKCS1Prefix(hashBytes, hashName)
114
115 sigBytes = serverKeyExchange.signature
116 if not sigBytes:
117 raise TLSIllegalParameterException("Empty signature")
118
119 if not publicKey.verify(sigBytes, hashBytes):
120 raise TLSDecryptionFailed("Server Key Exchange signature "
121 "invalid")
122
123 @staticmethod
124 - def calcVerifyBytes(version, handshakeHashes, signatureAlg,
125 premasterSecret, clientRandom, serverRandom):
126 """Calculate signed bytes for Certificate Verify"""
127 if version == (3, 0):
128 masterSecret = calcMasterSecret(version,
129 0,
130 premasterSecret,
131 clientRandom,
132 serverRandom)
133 verifyBytes = handshakeHashes.digestSSL(masterSecret, b"")
134 elif version in ((3, 1), (3, 2)):
135 verifyBytes = handshakeHashes.digest()
136 elif version == (3, 3):
137 hashName = HashAlgorithm.toRepr(signatureAlg[0])
138 verifyBytes = handshakeHashes.digest(hashName)
139 verifyBytes = RSAKey.addPKCS1Prefix(verifyBytes, hashName)
140 return verifyBytes
141
142 @staticmethod
143 - def makeCertificateVerify(version, handshakeHashes, validSigAlgs,
144 privateKey, certificateRequest, premasterSecret,
145 clientRandom, serverRandom):
146 """Create a Certificate Verify message
147
148 @param version: protocol version in use
149 @param handshakeHashes: the running hash of all handshake messages
150 @param validSigAlgs: acceptable signature algorithms for client side,
151 applicable only to TLSv1.2 (or later)
152 @param certificateRequest: the server provided Certificate Request
153 message
154 @param premasterSecret: the premaster secret, needed only for SSLv3
155 @param clientRandom: client provided random value, needed only for SSLv3
156 @param serverRandom: server provided random value, needed only for SSLv3
157 """
158 signatureAlgorithm = None
159
160 if version == (3, 3):
161 serverSigAlgs = certificateRequest.supported_signature_algs
162 signatureAlgorithm = next((sigAlg for sigAlg in validSigAlgs \
163 if sigAlg in serverSigAlgs), None)
164
165 if signatureAlgorithm is None:
166 signatureAlgorithm = validSigAlgs[0]
167 verifyBytes = KeyExchange.calcVerifyBytes(version, handshakeHashes,
168 signatureAlgorithm,
169 premasterSecret,
170 clientRandom,
171 serverRandom)
172 signedBytes = privateKey.sign(verifyBytes)
173 certificateVerify = CertificateVerify(version)
174 certificateVerify.create(signedBytes, signatureAlgorithm)
175
176 return certificateVerify
177
179 """
180 Handling of RSA key exchange
181
182 NOT stable API, do NOT use
183 """
184
185 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
186 super(RSAKeyExchange, self).__init__(cipherSuite, clientHello,
187 serverHello, privateKey)
188 self.encPremasterSecret = None
189
191 """Don't create a server key exchange for RSA key exchange"""
192 return None
193
195 """Decrypt client key exchange, return premaster secret"""
196 premasterSecret = self.privateKey.decrypt(\
197 clientKeyExchange.encryptedPreMasterSecret)
198
199
200
201 randomPreMasterSecret = getRandomBytes(48)
202 if not premasterSecret:
203 premasterSecret = randomPreMasterSecret
204 elif len(premasterSecret) != 48:
205 premasterSecret = randomPreMasterSecret
206 else:
207 versionCheck = (premasterSecret[0], premasterSecret[1])
208 if versionCheck != self.clientHello.client_version:
209
210 if versionCheck != self.serverHello.server_version:
211 premasterSecret = randomPreMasterSecret
212 return premasterSecret
213
216 """Generate premaster secret for server"""
217 del serverKeyExchange
218 premasterSecret = getRandomBytes(48)
219 premasterSecret[0] = self.clientHello.client_version[0]
220 premasterSecret[1] = self.clientHello.client_version[1]
221
222 self.encPremasterSecret = srvPublicKey.encrypt(premasterSecret)
223 return premasterSecret
224
226 """Return a client key exchange with clients key share"""
227 clientKeyExchange = super(RSAKeyExchange, self).makeClientKeyExchange()
228 clientKeyExchange.createRSA(self.encPremasterSecret)
229 return clientKeyExchange
230
234 """
235 Handling of ephemeral Diffe-Hellman Key exchange
236
237 NOT stable API, do NOT use
238 """
239
240 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
241 super(DHE_RSAKeyExchange, self).__init__(cipherSuite, clientHello,
242 serverHello, privateKey)
243
244 self.dh_Xs = None
245 self.dh_Yc = None
246
247
248 dh_g, dh_p = goodGroupParameters[2]
249
250
251 strength = 160
252
265
277
292
298
303 """Helper class for conducting ECDHE key exchange"""
304
305 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey,
306 acceptedCurves):
307 super(ECDHE_RSAKeyExchange, self).__init__(cipherSuite, clientHello,
308 serverHello, privateKey)
309
310 self.ecdhXs = None
311 self.acceptedCurves = acceptedCurves
312 self.group_id = None
313 self.ecdhYc = None
314
343
357
376
382
384 """Helper class for conducting SRP key exchange"""
385
386 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey,
387 verifierDB, srpUsername=None, password=None, settings=None):
388 """Link Key Exchange options with verifierDB for SRP"""
389 super(SRPKeyExchange, self).__init__(cipherSuite, clientHello,
390 serverHello, privateKey)
391 self.N = None
392 self.v = None
393 self.b = None
394 self.B = None
395 self.verifierDB = verifierDB
396 self.A = None
397 self.srpUsername = srpUsername
398 self.password = password
399 self.settings = settings
400
402 """Create SRP version of Server Key Exchange"""
403 srpUsername = self.clientHello.srp_username.decode("utf-8")
404
405 try:
406 entry = self.verifierDB[srpUsername]
407 except KeyError:
408 raise TLSUnknownPSKIdentity("Unknown identity")
409 (self.N, g, s, self.v) = entry
410
411
412 self.b = bytesToNumber(getRandomBytes(32))
413 k = makeK(self.N, g)
414 self.B = (powMod(g, self.b, self.N) + (k * self.v)) % self.N
415
416
417 serverKeyExchange = ServerKeyExchange(self.cipherSuite,
418 self.serverHello.server_version)
419 serverKeyExchange.createSRP(self.N, g, s, self.B)
420 if self.cipherSuite in CipherSuite.srpCertSuites:
421 self.signServerKeyExchange(serverKeyExchange, sigHash)
422 return serverKeyExchange
423
425 """Calculate premaster secret from Client Key Exchange and sent SKE"""
426 A = clientKeyExchange.srp_A
427 if A % self.N == 0:
428 raise TLSIllegalParameterException("Invalid SRP A value")
429
430
431 u = makeU(self.N, A, self.B)
432
433
434 S = powMod((A * powMod(self.v, u, self.N)) % self.N, self.b, self.N)
435 return numberToByteArray(S)
436
438 """Calculate premaster secret from ServerKeyExchange"""
439 del srvPublicKey
440 N = serverKeyExchange.srp_N
441 g = serverKeyExchange.srp_g
442 s = serverKeyExchange.srp_s
443 B = serverKeyExchange.srp_B
444
445 if (g, N) not in goodGroupParameters:
446 raise TLSInsufficientSecurity("Unknown group parameters")
447 if numBits(N) < self.settings.minKeySize:
448 raise TLSInsufficientSecurity("N value is too small: {0}".\
449 format(numBits(N)))
450 if numBits(N) > self.settings.maxKeySize:
451 raise TLSInsufficientSecurity("N value is too large: {0}".\
452 format(numBits(N)))
453 if B % N == 0:
454 raise TLSIllegalParameterException("Suspicious B value")
455
456
457 a = bytesToNumber(getRandomBytes(32))
458 self.A = powMod(g, a, N)
459
460
461 x = makeX(s, bytearray(self.srpUsername, "utf-8"),
462 bytearray(self.password, "utf-8"))
463 v = powMod(g, x, N)
464
465
466 u = makeU(N, self.A, B)
467
468
469 k = makeK(N, g)
470 S = powMod((B - (k*v)) % N, a+(u*x), N)
471 return numberToByteArray(S)
472
478