1
2
3
4
5 """Handling of cryptographic operations for key exchange"""
6
7 from .mathtls import goodGroupParameters, makeK, makeU, makeX, \
8 calcMasterSecret, paramStrength, RFC7919_GROUPS
9 from .errors import TLSInsufficientSecurity, TLSUnknownPSKIdentity, \
10 TLSIllegalParameterException, TLSDecryptionFailed, TLSInternalError
11 from .messages import ServerKeyExchange, ClientKeyExchange, CertificateVerify
12 from .constants import SignatureAlgorithm, HashAlgorithm, CipherSuite, \
13 ExtensionType, GroupName, ECCurveType
14 from .utils.ecc import decodeX962Point, encodeX962Point, getCurveByName, \
15 getPointByteSize
16 from .utils.rsakey import RSAKey
17 from .utils.cryptomath import bytesToNumber, getRandomBytes, powMod, \
18 numBits, numberToByteArray, divceil
19 from .utils.lists import getFirstMatching
20 import ecdsa
23 """
24 Common API for calculating Premaster secret
25
26 NOT stable, will get moved from this file
27 """
28
29 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey=None):
30 """Initialize KeyExchange. privateKey is the signing private key"""
31 self.cipherSuite = cipherSuite
32 self.clientHello = clientHello
33 self.serverHello = serverHello
34 self.privateKey = privateKey
35
37 """
38 Create a ServerKeyExchange object
39
40 Returns a ServerKeyExchange object for the server's initial leg in the
41 handshake. If the key exchange method does not send ServerKeyExchange
42 (e.g. RSA), it returns None.
43 """
44 raise NotImplementedError()
45
47 """
48 Create a ClientKeyExchange object
49
50 Returns a ClientKeyExchange for the second flight from client in the
51 handshake.
52 """
53 return ClientKeyExchange(self.cipherSuite,
54 self.serverHello.server_version)
55
57 """
58 Process ClientKeyExchange and return premaster secret
59
60 Processes the client's ClientKeyExchange message and returns the
61 premaster secret. Raises TLSLocalAlert on error.
62 """
63 raise NotImplementedError()
64
67 """Process the server KEX and return premaster secret"""
68 raise NotImplementedError()
69
71 """
72 Sign a server key best matching supported algorithms
73
74 @type sigHash: str
75 @param sigHash: name of the hash used for signing
76 """
77 if self.serverHello.server_version >= (3, 3):
78 serverKeyExchange.signAlg = SignatureAlgorithm.rsa
79 serverKeyExchange.hashAlg = getattr(HashAlgorithm, sigHash)
80 hashBytes = serverKeyExchange.hash(self.clientHello.random,
81 self.serverHello.random)
82
83 if self.serverHello.server_version >= (3, 3):
84 hashBytes = RSAKey.addPKCS1Prefix(hashBytes, sigHash)
85
86 serverKeyExchange.signature = self.privateKey.sign(hashBytes)
87
88 if not serverKeyExchange.signature:
89 raise TLSInternalError("Empty signature")
90
91 if not self.privateKey.verify(serverKeyExchange.signature, hashBytes):
92 raise TLSInternalError("Server Key Exchange signature invalid")
93
94 @staticmethod
97 """Verify signature on the Server Key Exchange message
98
99 the only acceptable signature algorithms are specified by validSigAlgs
100 """
101 if serverKeyExchange.version >= (3, 3):
102 if (serverKeyExchange.hashAlg, serverKeyExchange.signAlg) not in \
103 validSigAlgs:
104 raise TLSIllegalParameterException("Server selected "
105 "invalid signature "
106 "algorithm")
107 assert serverKeyExchange.signAlg == SignatureAlgorithm.rsa
108 hashName = HashAlgorithm.toRepr(serverKeyExchange.hashAlg)
109 if hashName is None:
110 raise TLSIllegalParameterException("Unknown signature "
111 "algorithm")
112 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom)
113
114 if serverKeyExchange.version == (3, 3):
115 hashBytes = RSAKey.addPKCS1Prefix(hashBytes, hashName)
116
117 sigBytes = serverKeyExchange.signature
118 if not sigBytes:
119 raise TLSIllegalParameterException("Empty signature")
120
121 if not publicKey.verify(sigBytes, hashBytes):
122 raise TLSDecryptionFailed("Server Key Exchange signature "
123 "invalid")
124
125 @staticmethod
126 - def calcVerifyBytes(version, handshakeHashes, signatureAlg,
127 premasterSecret, clientRandom, serverRandom):
128 """Calculate signed bytes for Certificate Verify"""
129 if version == (3, 0):
130 masterSecret = calcMasterSecret(version,
131 0,
132 premasterSecret,
133 clientRandom,
134 serverRandom)
135 verifyBytes = handshakeHashes.digestSSL(masterSecret, b"")
136 elif version in ((3, 1), (3, 2)):
137 verifyBytes = handshakeHashes.digest()
138 elif version == (3, 3):
139 hashName = HashAlgorithm.toRepr(signatureAlg[0])
140 verifyBytes = handshakeHashes.digest(hashName)
141 verifyBytes = RSAKey.addPKCS1Prefix(verifyBytes, hashName)
142 return verifyBytes
143
144 @staticmethod
145 - def makeCertificateVerify(version, handshakeHashes, validSigAlgs,
146 privateKey, certificateRequest, premasterSecret,
147 clientRandom, serverRandom):
148 """Create a Certificate Verify message
149
150 @param version: protocol version in use
151 @param handshakeHashes: the running hash of all handshake messages
152 @param validSigAlgs: acceptable signature algorithms for client side,
153 applicable only to TLSv1.2 (or later)
154 @param certificateRequest: the server provided Certificate Request
155 message
156 @param premasterSecret: the premaster secret, needed only for SSLv3
157 @param clientRandom: client provided random value, needed only for SSLv3
158 @param serverRandom: server provided random value, needed only for SSLv3
159 """
160 signatureAlgorithm = None
161
162 if version == (3, 3):
163 serverSigAlgs = certificateRequest.supported_signature_algs
164 signatureAlgorithm = getFirstMatching(validSigAlgs, serverSigAlgs)
165
166 if signatureAlgorithm is None:
167 signatureAlgorithm = validSigAlgs[0]
168 verifyBytes = KeyExchange.calcVerifyBytes(version, handshakeHashes,
169 signatureAlgorithm,
170 premasterSecret,
171 clientRandom,
172 serverRandom)
173 signedBytes = privateKey.sign(verifyBytes)
174 if not privateKey.verify(signedBytes, verifyBytes):
175 raise TLSInternalError("Certificate Verify signature invalid")
176 certificateVerify = CertificateVerify(version)
177 certificateVerify.create(signedBytes, signatureAlgorithm)
178
179 return certificateVerify
180
182 """
183 Common methods for key exchanges that authenticate Server Key Exchange
184
185 Methods for signing Server Key Exchange message
186 """
187
193
196 """
197 Handling of RSA key exchange
198
199 NOT stable API, do NOT use
200 """
201
202 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
203 super(RSAKeyExchange, self).__init__(cipherSuite, clientHello,
204 serverHello, privateKey)
205 self.encPremasterSecret = None
206
208 """Don't create a server key exchange for RSA key exchange"""
209 return None
210
212 """Decrypt client key exchange, return premaster secret"""
213 premasterSecret = self.privateKey.decrypt(\
214 clientKeyExchange.encryptedPreMasterSecret)
215
216
217
218 randomPreMasterSecret = getRandomBytes(48)
219 if not premasterSecret:
220 premasterSecret = randomPreMasterSecret
221 elif len(premasterSecret) != 48:
222 premasterSecret = randomPreMasterSecret
223 else:
224 versionCheck = (premasterSecret[0], premasterSecret[1])
225 if versionCheck != self.clientHello.client_version:
226
227 if versionCheck != self.serverHello.server_version:
228 premasterSecret = randomPreMasterSecret
229 return premasterSecret
230
233 """Generate premaster secret for server"""
234 del serverKeyExchange
235 premasterSecret = getRandomBytes(48)
236 premasterSecret[0] = self.clientHello.client_version[0]
237 premasterSecret[1] = self.clientHello.client_version[1]
238
239 self.encPremasterSecret = srvPublicKey.encrypt(premasterSecret)
240 return premasterSecret
241
243 """Return a client key exchange with clients key share"""
244 clientKeyExchange = super(RSAKeyExchange, self).makeClientKeyExchange()
245 clientKeyExchange.createRSA(self.encPremasterSecret)
246 return clientKeyExchange
247
250 """
251 Handling of anonymous Diffie-Hellman Key exchange
252
253 FFDHE without signing serverKeyExchange useful for anonymous DH
254 """
255
256 - def __init__(self, cipherSuite, clientHello, serverHello,
257 dhParams=None, dhGroups=None):
258 super(ADHKeyExchange, self).__init__(cipherSuite, clientHello,
259 serverHello)
260
261 self.dh_Xs = None
262 self.dh_Yc = None
263 if dhParams:
264 self.dh_g, self.dh_p = dhParams
265 else:
266
267 self.dh_g, self.dh_p = goodGroupParameters[2]
268 self.dhGroups = dhGroups
269
271 """
272 Prepare server side of anonymous key exchange with selected parameters
273 """
274
275 ext = self.clientHello.getExtension(ExtensionType.supported_groups)
276 if ext and self.dhGroups:
277 commonGroup = getFirstMatching(ext.groups, self.dhGroups)
278 if commonGroup:
279 self.dh_g, self.dh_p = RFC7919_GROUPS[commonGroup - 256]
280 elif getFirstMatching(ext.groups, range(256, 512)):
281 raise TLSInternalError("DHE key exchange attempted despite no "
282 "overlap between supported groups")
283
284
285
286 randBytesNeeded = divceil(paramStrength(self.dh_p) * 2, 8)
287 self.dh_Xs = bytesToNumber(getRandomBytes(randBytesNeeded))
288 dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p)
289
290 version = self.serverHello.server_version
291 serverKeyExchange = ServerKeyExchange(self.cipherSuite, version)
292 serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys)
293
294 return serverKeyExchange
295
310
337
343
348 """
349 Handling of authenticated ephemeral Diffe-Hellman Key exchange.
350 """
351
352 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey,
353 dhParams=None, dhGroups=None):
354 """
355 Create helper object for Diffie-Hellamn key exchange.
356
357 @param dhParams: Diffie-Hellman parameters that will be used by
358 server. First element of the tuple is the generator, the second
359 is the prime. If not specified it will use a secure set (currently
360 a 2048-bit safe prime).
361 @type dhParams: 2-element tuple of int
362 """
363 super(DHE_RSAKeyExchange, self).__init__(cipherSuite, clientHello,
364 serverHello, dhParams,
365 dhGroups)
366
367 self.privateKey = privateKey
368
371 """
372 Handling of anonymous Eliptic curve Diffie-Hellman Key exchange
373
374 ECDHE without signing serverKeyExchange useful for anonymous ECDH
375 """
376 - def __init__(self, cipherSuite, clientHello, serverHello, acceptedCurves):
377 super(AECDHKeyExchange, self).__init__(cipherSuite, clientHello,
378 serverHello)
379 self.ecdhXs = None
380 self.acceptedCurves = acceptedCurves
381 self.group_id = None
382 self.ecdhYc = None
383
410
424
443
449
455 """Helper class for conducting ECDHE key exchange"""
456
457 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey,
458 acceptedCurves):
459 super(ECDHE_RSAKeyExchange, self).__init__(cipherSuite, clientHello,
460 serverHello,
461 acceptedCurves)
462
463 self.privateKey = privateKey
464
467 """Helper class for conducting SRP key exchange"""
468
469 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey,
470 verifierDB, srpUsername=None, password=None, settings=None):
471 """Link Key Exchange options with verifierDB for SRP"""
472 super(SRPKeyExchange, self).__init__(cipherSuite, clientHello,
473 serverHello, privateKey)
474 self.N = None
475 self.v = None
476 self.b = None
477 self.B = None
478 self.verifierDB = verifierDB
479 self.A = None
480 self.srpUsername = srpUsername
481 self.password = password
482 self.settings = settings
483 if srpUsername is not None and not isinstance(srpUsername, bytearray):
484 raise TypeError("srpUsername must be a bytearray object")
485 if password is not None and not isinstance(password, bytearray):
486 raise TypeError("password must be a bytearray object")
487
489 """Create SRP version of Server Key Exchange"""
490 srpUsername = bytes(self.clientHello.srp_username)
491
492 try:
493 entry = self.verifierDB[srpUsername]
494 except KeyError:
495 raise TLSUnknownPSKIdentity("Unknown identity")
496 (self.N, g, s, self.v) = entry
497
498
499 self.b = bytesToNumber(getRandomBytes(32))
500 k = makeK(self.N, g)
501 self.B = (powMod(g, self.b, self.N) + (k * self.v)) % self.N
502
503
504 serverKeyExchange = ServerKeyExchange(self.cipherSuite,
505 self.serverHello.server_version)
506 serverKeyExchange.createSRP(self.N, g, s, self.B)
507 if self.cipherSuite in CipherSuite.srpCertSuites:
508 self.signServerKeyExchange(serverKeyExchange, sigHash)
509 return serverKeyExchange
510
512 """Calculate premaster secret from Client Key Exchange and sent SKE"""
513 A = clientKeyExchange.srp_A
514 if A % self.N == 0:
515 raise TLSIllegalParameterException("Invalid SRP A value")
516
517
518 u = makeU(self.N, A, self.B)
519
520
521 S = powMod((A * powMod(self.v, u, self.N)) % self.N, self.b, self.N)
522 return numberToByteArray(S)
523
525 """Calculate premaster secret from ServerKeyExchange"""
526 del srvPublicKey
527 N = serverKeyExchange.srp_N
528 g = serverKeyExchange.srp_g
529 s = serverKeyExchange.srp_s
530 B = serverKeyExchange.srp_B
531
532 if (g, N) not in goodGroupParameters:
533 raise TLSInsufficientSecurity("Unknown group parameters")
534 if numBits(N) < self.settings.minKeySize:
535 raise TLSInsufficientSecurity("N value is too small: {0}".\
536 format(numBits(N)))
537 if numBits(N) > self.settings.maxKeySize:
538 raise TLSInsufficientSecurity("N value is too large: {0}".\
539 format(numBits(N)))
540 if B % N == 0:
541 raise TLSIllegalParameterException("Suspicious B value")
542
543
544 a = bytesToNumber(getRandomBytes(32))
545 self.A = powMod(g, a, N)
546
547
548 x = makeX(s, self.srpUsername, self.password)
549 v = powMod(g, x, N)
550
551
552 u = makeU(N, self.A, B)
553
554
555 k = makeK(N, g)
556 S = powMod((B - (k*v)) % N, a+(u*x), N)
557 return numberToByteArray(S)
558
564