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=None):
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
180 """
181 Handling of RSA key exchange
182
183 NOT stable API, do NOT use
184 """
185
186 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
187 super(RSAKeyExchange, self).__init__(cipherSuite, clientHello,
188 serverHello, privateKey)
189 self.encPremasterSecret = None
190
192 """Don't create a server key exchange for RSA key exchange"""
193 return None
194
196 """Decrypt client key exchange, return premaster secret"""
197 premasterSecret = self.privateKey.decrypt(\
198 clientKeyExchange.encryptedPreMasterSecret)
199
200
201
202 randomPreMasterSecret = getRandomBytes(48)
203 if not premasterSecret:
204 premasterSecret = randomPreMasterSecret
205 elif len(premasterSecret) != 48:
206 premasterSecret = randomPreMasterSecret
207 else:
208 versionCheck = (premasterSecret[0], premasterSecret[1])
209 if versionCheck != self.clientHello.client_version:
210
211 if versionCheck != self.serverHello.server_version:
212 premasterSecret = randomPreMasterSecret
213 return premasterSecret
214
217 """Generate premaster secret for server"""
218 del serverKeyExchange
219 premasterSecret = getRandomBytes(48)
220 premasterSecret[0] = self.clientHello.client_version[0]
221 premasterSecret[1] = self.clientHello.client_version[1]
222
223 self.encPremasterSecret = srvPublicKey.encrypt(premasterSecret)
224 return premasterSecret
225
227 """Return a client key exchange with clients key share"""
228 clientKeyExchange = super(RSAKeyExchange, self).makeClientKeyExchange()
229 clientKeyExchange.createRSA(self.encPremasterSecret)
230 return clientKeyExchange
231
234 """
235 Handling of anonymous Diffie-Hellman Key exchange
236
237 FFDHE without signing serverKeyExchange useful for anonymous DH
238 """
239
240 - def __init__(self, cipherSuite, clientHello, serverHello):
241 super(ADHKeyExchange, self).__init__(cipherSuite, clientHello,
242 serverHello)
243
244 self.dh_Xs = None
245 self.dh_Yc = None
246
247
248
249 dh_g, dh_p = goodGroupParameters[2]
250
251
252 strength = 160
253
268
280
295
301
306 """
307 Handling of ephemeral Diffe-Hellman Key exchange
308
309 NOT stable API, do NOT use
310 """
311
312 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
317
323
326 """
327 Handling of anonymous Eliptic curve Diffie-Hellman Key exchange
328
329 ECDHE without signing serverKeyExchange useful for anonymous ECDH
330 """
331 - def __init__(self, cipherSuite, clientHello, serverHello, acceptedCurves):
332 super(AECDHKeyExchange, self).__init__(cipherSuite, clientHello,
333 serverHello)
334 self.ecdhXs = None
335 self.acceptedCurves = acceptedCurves
336 self.group_id = None
337 self.ecdhYc = None
338
366
380
399
405
411 """Helper class for conducting ECDHE key exchange"""
412
413 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey,
414 acceptedCurves):
415 super(ECDHE_RSAKeyExchange, self).__init__(cipherSuite, clientHello,
416 serverHello,
417 acceptedCurves)
418
419 self.privateKey = privateKey
420
426
429 """Helper class for conducting SRP key exchange"""
430
431 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey,
432 verifierDB, srpUsername=None, password=None, settings=None):
433 """Link Key Exchange options with verifierDB for SRP"""
434 super(SRPKeyExchange, self).__init__(cipherSuite, clientHello,
435 serverHello, privateKey)
436 self.N = None
437 self.v = None
438 self.b = None
439 self.B = None
440 self.verifierDB = verifierDB
441 self.A = None
442 self.srpUsername = srpUsername
443 self.password = password
444 self.settings = settings
445 if srpUsername is not None and not isinstance(srpUsername, bytearray):
446 raise TypeError("srpUsername must be a bytearray object")
447 if password is not None and not isinstance(password, bytearray):
448 raise TypeError("password must be a bytearray object")
449
451 """Create SRP version of Server Key Exchange"""
452 srpUsername = bytes(self.clientHello.srp_username)
453
454 try:
455 entry = self.verifierDB[srpUsername]
456 except KeyError:
457 raise TLSUnknownPSKIdentity("Unknown identity")
458 (self.N, g, s, self.v) = entry
459
460
461 self.b = bytesToNumber(getRandomBytes(32))
462 k = makeK(self.N, g)
463 self.B = (powMod(g, self.b, self.N) + (k * self.v)) % self.N
464
465
466 serverKeyExchange = ServerKeyExchange(self.cipherSuite,
467 self.serverHello.server_version)
468 serverKeyExchange.createSRP(self.N, g, s, self.B)
469 if self.cipherSuite in CipherSuite.srpCertSuites:
470 self.signServerKeyExchange(serverKeyExchange, sigHash)
471 return serverKeyExchange
472
474 """Calculate premaster secret from Client Key Exchange and sent SKE"""
475 A = clientKeyExchange.srp_A
476 if A % self.N == 0:
477 raise TLSIllegalParameterException("Invalid SRP A value")
478
479
480 u = makeU(self.N, A, self.B)
481
482
483 S = powMod((A * powMod(self.v, u, self.N)) % self.N, self.b, self.N)
484 return numberToByteArray(S)
485
487 """Calculate premaster secret from ServerKeyExchange"""
488 del srvPublicKey
489 N = serverKeyExchange.srp_N
490 g = serverKeyExchange.srp_g
491 s = serverKeyExchange.srp_s
492 B = serverKeyExchange.srp_B
493
494 if (g, N) not in goodGroupParameters:
495 raise TLSInsufficientSecurity("Unknown group parameters")
496 if numBits(N) < self.settings.minKeySize:
497 raise TLSInsufficientSecurity("N value is too small: {0}".\
498 format(numBits(N)))
499 if numBits(N) > self.settings.maxKeySize:
500 raise TLSInsufficientSecurity("N value is too large: {0}".\
501 format(numBits(N)))
502 if B % N == 0:
503 raise TLSIllegalParameterException("Suspicious B value")
504
505
506 a = bytesToNumber(getRandomBytes(32))
507 self.A = powMod(g, a, N)
508
509
510 x = makeX(s, self.srpUsername, self.password)
511 v = powMod(g, x, N)
512
513
514 u = makeU(N, self.A, B)
515
516
517 k = makeK(N, g)
518 S = powMod((B - (k*v)) % N, a+(u*x), N)
519 return numberToByteArray(S)
520
526