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 """
471 - def __init__(self, cipherSuite, clientHello, serverHello, acceptedCurves):
472 super(AECDHKeyExchange, self).__init__(cipherSuite, clientHello,
473 serverHello)
474 self.ecdhXs = None
475 self.acceptedCurves = acceptedCurves
476 self.group_id = None
477 self.ecdhYc = None
478
509
523
542
548
554 """Helper class for conducting ECDHE key exchange"""
555
556 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey,
557 acceptedCurves):
558 super(ECDHE_RSAKeyExchange, self).__init__(cipherSuite, clientHello,
559 serverHello,
560 acceptedCurves)
561
562 self.privateKey = privateKey
563
566 """Helper class for conducting SRP key exchange"""
567
568 - def __init__(self, cipherSuite, clientHello, serverHello, privateKey,
569 verifierDB, srpUsername=None, password=None, settings=None):
570 """Link Key Exchange options with verifierDB for SRP"""
571 super(SRPKeyExchange, self).__init__(cipherSuite, clientHello,
572 serverHello, privateKey)
573 self.N = None
574 self.v = None
575 self.b = None
576 self.B = None
577 self.verifierDB = verifierDB
578 self.A = None
579 self.srpUsername = srpUsername
580 self.password = password
581 self.settings = settings
582 if srpUsername is not None and not isinstance(srpUsername, bytearray):
583 raise TypeError("srpUsername must be a bytearray object")
584 if password is not None and not isinstance(password, bytearray):
585 raise TypeError("password must be a bytearray object")
586
588 """Create SRP version of Server Key Exchange"""
589 srpUsername = bytes(self.clientHello.srp_username)
590
591 try:
592 entry = self.verifierDB[srpUsername]
593 except KeyError:
594 raise TLSUnknownPSKIdentity("Unknown identity")
595 (self.N, g, s, self.v) = entry
596
597
598 self.b = bytesToNumber(getRandomBytes(32))
599 k = makeK(self.N, g)
600 self.B = (powMod(g, self.b, self.N) + (k * self.v)) % self.N
601
602
603 serverKeyExchange = ServerKeyExchange(self.cipherSuite,
604 self.serverHello.server_version)
605 serverKeyExchange.createSRP(self.N, g, s, self.B)
606 if self.cipherSuite in CipherSuite.srpCertSuites:
607 self.signServerKeyExchange(serverKeyExchange, sigHash)
608 return serverKeyExchange
609
611 """Calculate premaster secret from Client Key Exchange and sent SKE"""
612 A = clientKeyExchange.srp_A
613 if A % self.N == 0:
614 raise TLSIllegalParameterException("Invalid SRP A value")
615
616
617 u = makeU(self.N, A, self.B)
618
619
620 S = powMod((A * powMod(self.v, u, self.N)) % self.N, self.b, self.N)
621 return numberToByteArray(S)
622
624 """Calculate premaster secret from ServerKeyExchange"""
625 del srvPublicKey
626 N = serverKeyExchange.srp_N
627 g = serverKeyExchange.srp_g
628 s = serverKeyExchange.srp_s
629 B = serverKeyExchange.srp_B
630
631 if (g, N) not in goodGroupParameters:
632 raise TLSInsufficientSecurity("Unknown group parameters")
633 if numBits(N) < self.settings.minKeySize:
634 raise TLSInsufficientSecurity("N value is too small: {0}".\
635 format(numBits(N)))
636 if numBits(N) > self.settings.maxKeySize:
637 raise TLSInsufficientSecurity("N value is too large: {0}".\
638 format(numBits(N)))
639 if B % N == 0:
640 raise TLSIllegalParameterException("Suspicious B value")
641
642
643 a = bytesToNumber(getRandomBytes(32))
644 self.A = powMod(g, a, N)
645
646
647 x = makeX(s, self.srpUsername, self.password)
648 v = powMod(g, x, N)
649
650
651 u = makeU(N, self.A, B)
652
653
654 k = makeK(N, g)
655 S = powMod((B - (k*v)) % N, a+(u*x), N)
656 return numberToByteArray(S)
657
663