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, SignatureScheme
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 from .utils import tlshashlib as hashlib
21 import ecdsa
24 """
25 Common API for calculating Premaster secret
26
27 NOT stable, will get moved from this file
28 """
29
30 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey=None):
31 """Initialize KeyExchange. privateKey is the signing private key"""
32 self.cipherSuite = cipherSuite
33 self.clientHello = clientHello
34 self.serverHello = serverHello
35 self.privateKey = privateKey
36
38 """
39 Create a ServerKeyExchange object
40
41 Returns a ServerKeyExchange object for the server's initial leg in the
42 handshake. If the key exchange method does not send ServerKeyExchange
43 (e.g. RSA), it returns None.
44 """
45 raise NotImplementedError()
46
48 """
49 Create a ClientKeyExchange object
50
51 Returns a ClientKeyExchange for the second flight from client in the
52 handshake.
53 """
54 return ClientKeyExchange(self.cipherSuite,
55 self.serverHello.server_version)
56
58 """
59 Process ClientKeyExchange and return premaster secret
60
61 Processes the client's ClientKeyExchange message and returns the
62 premaster secret. Raises TLSLocalAlert on error.
63 """
64 raise NotImplementedError()
65
68 """Process the server KEX and return premaster secret"""
69 raise NotImplementedError()
70
72 """Sign a TLSv1.2 SKE message."""
73 try:
74 serverKeyExchange.hashAlg, serverKeyExchange.signAlg = \
75 getattr(SignatureScheme, sigHash)
76 keyType = SignatureScheme.getKeyType(sigHash)
77 padType = SignatureScheme.getPadding(sigHash)
78 hashName = SignatureScheme.getHash(sigHash)
79 saltLen = getattr(hashlib, hashName)().digest_size
80 except AttributeError:
81 serverKeyExchange.signAlg = SignatureAlgorithm.rsa
82 serverKeyExchange.hashAlg = getattr(HashAlgorithm, sigHash)
83 keyType = 'rsa'
84 padType = 'pkcs1'
85 hashName = sigHash
86 saltLen = 0
87
88 assert keyType == 'rsa'
89
90 hashBytes = serverKeyExchange.hash(self.clientHello.random,
91 self.serverHello.random)
92
93 serverKeyExchange.signature = \
94 self.privateKey.sign(hashBytes,
95 padding=padType,
96 hashAlg=hashName,
97 saltLen=saltLen)
98
99 if not serverKeyExchange.signature:
100 raise TLSInternalError("Empty signature")
101
102 if not self.privateKey.verify(serverKeyExchange.signature,
103 hashBytes,
104 padding=padType,
105 hashAlg=hashName,
106 saltLen=saltLen):
107 raise TLSInternalError("Server Key Exchange signature invalid")
108
110 """
111 Sign a server key exchange using default or specified algorithm
112
113 @type sigHash: str
114 @param sigHash: name of the signature hash to be used for signing
115 """
116 if self.serverHello.server_version < (3, 3):
117 hashBytes = serverKeyExchange.hash(self.clientHello.random,
118 self.serverHello.random)
119
120 serverKeyExchange.signature = self.privateKey.sign(hashBytes)
121
122 if not serverKeyExchange.signature:
123 raise TLSInternalError("Empty signature")
124
125 if not self.privateKey.verify(serverKeyExchange.signature,
126 hashBytes):
127 raise TLSInternalError("Server Key Exchange signature invalid")
128 else:
129 self._tls12_signSKE(serverKeyExchange, sigHash)
130
131 @staticmethod
132 - def _tls12_verify_SKE(serverKeyExchange, publicKey, clientRandom,
133 serverRandom, validSigAlgs):
134 """Verify TLSv1.2 version of SKE."""
135 if (serverKeyExchange.hashAlg, serverKeyExchange.signAlg) not in \
136 validSigAlgs:
137 raise TLSIllegalParameterException("Server selected "
138 "invalid signature "
139 "algorithm")
140 schemeID = (serverKeyExchange.hashAlg,
141 serverKeyExchange.signAlg)
142 scheme = SignatureScheme.toRepr(schemeID)
143 if scheme is not None:
144 keyType = SignatureScheme.getKeyType(scheme)
145 padType = SignatureScheme.getPadding(scheme)
146 hashName = SignatureScheme.getHash(scheme)
147 saltLen = getattr(hashlib, hashName)().digest_size
148 else:
149 if serverKeyExchange.signAlg != SignatureAlgorithm.rsa:
150 raise TLSInternalError("non-RSA sigs are not supported")
151 keyType = 'rsa'
152 padType = 'pkcs1'
153 saltLen = 0
154 hashName = HashAlgorithm.toRepr(serverKeyExchange.hashAlg)
155 if hashName is None:
156 msg = "Unknown hash ID: {0}"\
157 .format(serverKeyExchange.hashAlg)
158 raise TLSIllegalParameterException(msg)
159 assert keyType == 'rsa'
160
161 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom)
162
163 sigBytes = serverKeyExchange.signature
164 if not sigBytes:
165 raise TLSIllegalParameterException("Empty signature")
166
167 if not publicKey.verify(sigBytes, hashBytes,
168 padding=padType,
169 hashAlg=hashName,
170 saltLen=saltLen):
171 raise TLSDecryptionFailed("Server Key Exchange signature "
172 "invalid")
173
174 @staticmethod
177 """Verify signature on the Server Key Exchange message
178
179 the only acceptable signature algorithms are specified by validSigAlgs
180 """
181 if serverKeyExchange.version < (3, 3):
182 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom)
183 sigBytes = serverKeyExchange.signature
184
185 if not sigBytes:
186 raise TLSIllegalParameterException("Empty signature")
187
188 if not publicKey.verify(sigBytes, hashBytes):
189 raise TLSDecryptionFailed("Server Key Exchange signature "
190 "invalid")
191 else:
192 KeyExchange._tls12_verify_SKE(serverKeyExchange, publicKey,
193 clientRandom, serverRandom,
194 validSigAlgs)
195
196 @staticmethod
197 - def calcVerifyBytes(version, handshakeHashes, signatureAlg,
198 premasterSecret, clientRandom, serverRandom):
199 """Calculate signed bytes for Certificate Verify"""
200 if version == (3, 0):
201 masterSecret = calcMasterSecret(version,
202 0,
203 premasterSecret,
204 clientRandom,
205 serverRandom)
206 verifyBytes = handshakeHashes.digestSSL(masterSecret, b"")
207 elif version in ((3, 1), (3, 2)):
208 verifyBytes = handshakeHashes.digest()
209 elif version == (3, 3):
210 scheme = SignatureScheme.toRepr(signatureAlg)
211 if scheme is None:
212 hashName = HashAlgorithm.toRepr(signatureAlg[0])
213 padding = 'pkcs1'
214 else:
215 hashName = SignatureScheme.getHash(scheme)
216 padding = SignatureScheme.getPadding(scheme)
217 verifyBytes = handshakeHashes.digest(hashName)
218 if padding == 'pkcs1':
219 verifyBytes = RSAKey.addPKCS1Prefix(verifyBytes, hashName)
220 return verifyBytes
221
222 @staticmethod
223 - def makeCertificateVerify(version, handshakeHashes, validSigAlgs,
224 privateKey, certificateRequest, premasterSecret,
225 clientRandom, serverRandom):
226 """Create a Certificate Verify message
227
228 @param version: protocol version in use
229 @param handshakeHashes: the running hash of all handshake messages
230 @param validSigAlgs: acceptable signature algorithms for client side,
231 applicable only to TLSv1.2 (or later)
232 @param certificateRequest: the server provided Certificate Request
233 message
234 @param premasterSecret: the premaster secret, needed only for SSLv3
235 @param clientRandom: client provided random value, needed only for SSLv3
236 @param serverRandom: server provided random value, needed only for SSLv3
237 """
238 signatureAlgorithm = None
239
240 if version == (3, 3):
241 serverSigAlgs = certificateRequest.supported_signature_algs
242 signatureAlgorithm = getFirstMatching(validSigAlgs, serverSigAlgs)
243
244 if signatureAlgorithm is None:
245 signatureAlgorithm = validSigAlgs[0]
246 verifyBytes = KeyExchange.calcVerifyBytes(version, handshakeHashes,
247 signatureAlgorithm,
248 premasterSecret,
249 clientRandom,
250 serverRandom)
251 scheme = SignatureScheme.toRepr(signatureAlgorithm)
252
253
254 hashName = None
255 saltLen = 0
256 if scheme is None:
257 padding = 'pkcs1'
258 else:
259 padding = SignatureScheme.getPadding(scheme)
260 if padding == 'pss':
261 hashName = SignatureScheme.getHash(scheme)
262 saltLen = getattr(hashlib, hashName)().digest_size
263
264 signedBytes = privateKey.sign(verifyBytes,
265 padding,
266 hashName,
267 saltLen)
268 if not privateKey.verify(signedBytes, verifyBytes, padding, hashName,
269 saltLen):
270 raise TLSInternalError("Certificate Verify signature invalid")
271 certificateVerify = CertificateVerify(version)
272 certificateVerify.create(signedBytes, signatureAlgorithm)
273
274 return certificateVerify
275
277 """
278 Common methods for key exchanges that authenticate Server Key Exchange
279
280 Methods for signing Server Key Exchange message
281 """
282
288
291 """
292 Handling of RSA key exchange
293
294 NOT stable API, do NOT use
295 """
296
297 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
298 super(RSAKeyExchange, self).__init__(cipherSuite, clientHello,
299 serverHello, privateKey)
300 self.encPremasterSecret = None
301
303 """Don't create a server key exchange for RSA key exchange"""
304 return None
305
307 """Decrypt client key exchange, return premaster secret"""
308 premasterSecret = self.privateKey.decrypt(\
309 clientKeyExchange.encryptedPreMasterSecret)
310
311
312
313 randomPreMasterSecret = getRandomBytes(48)
314 if not premasterSecret:
315 premasterSecret = randomPreMasterSecret
316 elif len(premasterSecret) != 48:
317 premasterSecret = randomPreMasterSecret
318 else:
319 versionCheck = (premasterSecret[0], premasterSecret[1])
320 if versionCheck != self.clientHello.client_version:
321
322 if versionCheck != self.serverHello.server_version:
323 premasterSecret = randomPreMasterSecret
324 return premasterSecret
325
328 """Generate premaster secret for server"""
329 del serverKeyExchange
330 premasterSecret = getRandomBytes(48)
331 premasterSecret[0] = self.clientHello.client_version[0]
332 premasterSecret[1] = self.clientHello.client_version[1]
333
334 self.encPremasterSecret = srvPublicKey.encrypt(premasterSecret)
335 return premasterSecret
336
338 """Return a client key exchange with clients key share"""
339 clientKeyExchange = super(RSAKeyExchange, self).makeClientKeyExchange()
340 clientKeyExchange.createRSA(self.encPremasterSecret)
341 return clientKeyExchange
342
345 """
346 Handling of anonymous Diffie-Hellman Key exchange
347
348 FFDHE without signing serverKeyExchange useful for anonymous DH
349 """
350
351 - def __init__(self, cipherSuite, clientHello, serverHello,
352 dhParams=None, dhGroups=None):
353 super(ADHKeyExchange, self).__init__(cipherSuite, clientHello,
354 serverHello)
355
356 self.dh_Xs = None
357 self.dh_Yc = None
358 if dhParams:
359 self.dh_g, self.dh_p = dhParams
360 else:
361
362 self.dh_g, self.dh_p = goodGroupParameters[2]
363 self.dhGroups = dhGroups
364
366 """
367 Prepare server side of anonymous key exchange with selected parameters
368 """
369
370 ext = self.clientHello.getExtension(ExtensionType.supported_groups)
371 if ext and self.dhGroups:
372 commonGroup = getFirstMatching(ext.groups, self.dhGroups)
373 if commonGroup:
374 self.dh_g, self.dh_p = RFC7919_GROUPS[commonGroup - 256]
375 elif getFirstMatching(ext.groups, range(256, 512)):
376 raise TLSInternalError("DHE key exchange attempted despite no "
377 "overlap between supported groups")
378
379
380
381 randBytesNeeded = divceil(paramStrength(self.dh_p) * 2, 8)
382 self.dh_Xs = bytesToNumber(getRandomBytes(randBytesNeeded))
383 dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p)
384
385 version = self.serverHello.server_version
386 serverKeyExchange = ServerKeyExchange(self.cipherSuite, version)
387 serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys)
388
389 return serverKeyExchange
390
405
432
438
443 """
444 Handling of authenticated ephemeral Diffe-Hellman Key exchange.
445 """
446
447 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey,
448 dhParams=None, dhGroups=None):
449 """
450 Create helper object for Diffie-Hellamn key exchange.
451
452 @param dhParams: Diffie-Hellman parameters that will be used by
453 server. First element of the tuple is the generator, the second
454 is the prime. If not specified it will use a secure set (currently
455 a 2048-bit safe prime).
456 @type dhParams: 2-element tuple of int
457 """
458 super(DHE_RSAKeyExchange, self).__init__(cipherSuite, clientHello,
459 serverHello, dhParams,
460 dhGroups)
461
462 self.privateKey = privateKey
463
466 """
467 Handling of anonymous Eliptic curve Diffie-Hellman Key exchange
468
469 ECDHE without signing serverKeyExchange useful for anonymous ECDH
470 """
473 super(AECDHKeyExchange, self).__init__(cipherSuite, clientHello,
474 serverHello)
475 self.ecdhXs = None
476 self.acceptedCurves = acceptedCurves
477 self.group_id = None
478 self.ecdhYc = None
479 self.defaultCurve = defaultCurve
480
512
526
545
551
557 """Helper class for conducting ECDHE key exchange"""
558
561 super(ECDHE_RSAKeyExchange, self).__init__(cipherSuite, clientHello,
562 serverHello,
563 acceptedCurves,
564 defaultCurve)
565
566 self.privateKey = privateKey
567
570 """Helper class for conducting SRP key exchange"""
571
572 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey,
573 verifierDB, srpUsername=None, password=None, settings=None):
574 """Link Key Exchange options with verifierDB for SRP"""
575 super(SRPKeyExchange, self).__init__(cipherSuite, clientHello,
576 serverHello, privateKey)
577 self.N = None
578 self.v = None
579 self.b = None
580 self.B = None
581 self.verifierDB = verifierDB
582 self.A = None
583 self.srpUsername = srpUsername
584 self.password = password
585 self.settings = settings
586 if srpUsername is not None and not isinstance(srpUsername, bytearray):
587 raise TypeError("srpUsername must be a bytearray object")
588 if password is not None and not isinstance(password, bytearray):
589 raise TypeError("password must be a bytearray object")
590
592 """Create SRP version of Server Key Exchange"""
593 srpUsername = bytes(self.clientHello.srp_username)
594
595 try:
596 entry = self.verifierDB[srpUsername]
597 except KeyError:
598 raise TLSUnknownPSKIdentity("Unknown identity")
599 (self.N, g, s, self.v) = entry
600
601
602 self.b = bytesToNumber(getRandomBytes(32))
603 k = makeK(self.N, g)
604 self.B = (powMod(g, self.b, self.N) + (k * self.v)) % self.N
605
606
607 serverKeyExchange = ServerKeyExchange(self.cipherSuite,
608 self.serverHello.server_version)
609 serverKeyExchange.createSRP(self.N, g, s, self.B)
610 if self.cipherSuite in CipherSuite.srpCertSuites:
611 self.signServerKeyExchange(serverKeyExchange, sigHash)
612 return serverKeyExchange
613
615 """Calculate premaster secret from Client Key Exchange and sent SKE"""
616 A = clientKeyExchange.srp_A
617 if A % self.N == 0:
618 raise TLSIllegalParameterException("Invalid SRP A value")
619
620
621 u = makeU(self.N, A, self.B)
622
623
624 S = powMod((A * powMod(self.v, u, self.N)) % self.N, self.b, self.N)
625 return numberToByteArray(S)
626
628 """Calculate premaster secret from ServerKeyExchange"""
629 del srvPublicKey
630 N = serverKeyExchange.srp_N
631 g = serverKeyExchange.srp_g
632 s = serverKeyExchange.srp_s
633 B = serverKeyExchange.srp_B
634
635 if (g, N) not in goodGroupParameters:
636 raise TLSInsufficientSecurity("Unknown group parameters")
637 if numBits(N) < self.settings.minKeySize:
638 raise TLSInsufficientSecurity("N value is too small: {0}".\
639 format(numBits(N)))
640 if numBits(N) > self.settings.maxKeySize:
641 raise TLSInsufficientSecurity("N value is too large: {0}".\
642 format(numBits(N)))
643 if B % N == 0:
644 raise TLSIllegalParameterException("Suspicious B value")
645
646
647 a = bytesToNumber(getRandomBytes(32))
648 self.A = powMod(g, a, N)
649
650
651 x = makeX(s, self.srpUsername, self.password)
652 v = powMod(g, x, N)
653
654
655 u = makeU(N, self.A, B)
656
657
658 k = makeK(N, g)
659 S = powMod((B - (k*v)) % N, a+(u*x), N)
660 return numberToByteArray(S)
661
667