1
2
3
4
5
6
7
8
9
10 """
11 MAIN CLASS FOR TLS LITE (START HERE!).
12 """
13
14 import socket
15 from .utils.compat import formatExceptionTrace
16 from .tlsrecordlayer import TLSRecordLayer
17 from .session import Session
18 from .constants import *
19 from .utils.cryptomath import getRandomBytes
20 from .errors import *
21 from .messages import *
22 from .mathtls import *
23 from .handshakesettings import HandshakeSettings
24 from .utils.tackwrapper import *
25
26
28 """
29 This class wraps a socket and provides TLS handshaking and data
30 transfer.
31
32 To use this class, create a new instance, passing a connected
33 socket into the constructor. Then call some handshake function.
34 If the handshake completes without raising an exception, then a TLS
35 connection has been negotiated. You can transfer data over this
36 connection as if it were a socket.
37
38 This class provides both synchronous and asynchronous versions of
39 its key functions. The synchronous versions should be used when
40 writing single-or multi-threaded code using blocking sockets. The
41 asynchronous versions should be used when performing asynchronous,
42 event-based I/O with non-blocking sockets.
43
44 Asynchronous I/O is a complicated subject; typically, you should
45 not use the asynchronous functions directly, but should use some
46 framework like asyncore or Twisted which TLS Lite integrates with
47 (see
48 L{tlslite.integration.tlsasyncdispatchermixin.TLSAsyncDispatcherMixIn}).
49 """
50
52 """Create a new TLSConnection instance.
53
54 @param sock: The socket data will be transmitted on. The
55 socket should already be connected. It may be in blocking or
56 non-blocking mode.
57
58 @type sock: L{socket.socket}
59 """
60 TLSRecordLayer.__init__(self, sock)
61
62
63
64
65
69 """Perform an anonymous handshake in the role of client.
70
71 This function performs an SSL or TLS handshake using an
72 anonymous Diffie Hellman ciphersuite.
73
74 Like any handshake function, this can be called on a closed
75 TLS connection, or on a TLS connection that is already open.
76 If called on an open connection it performs a re-handshake.
77
78 If the function completes without raising an exception, the
79 TLS connection will be open and available for data transfer.
80
81 If an exception is raised, the connection will have been
82 automatically closed (if it was ever open).
83
84 @type session: L{tlslite.Session.Session}
85 @param session: A TLS session to attempt to resume. If the
86 resumption does not succeed, a full handshake will be
87 performed.
88
89 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
90 @param settings: Various settings which can be used to control
91 the ciphersuites, certificate types, and SSL/TLS versions
92 offered by the client.
93
94 @type checker: L{tlslite.Checker.Checker}
95 @param checker: A Checker instance. This instance will be
96 invoked to examine the other party's authentication
97 credentials, if the handshake completes succesfully.
98
99 @type serverName: string
100 @param serverName: The ServerNameIndication TLS Extension.
101
102 @type async: bool
103 @param async: If False, this function will block until the
104 handshake is completed. If True, this function will return a
105 generator. Successive invocations of the generator will
106 return 0 if it is waiting to read from the socket, 1 if it is
107 waiting to write to the socket, or will raise StopIteration if
108 the handshake operation is completed.
109
110 @rtype: None or an iterable
111 @return: If 'async' is True, a generator object will be
112 returned.
113
114 @raise socket.error: If a socket error occurs.
115 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
116 without a preceding alert.
117 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
118 @raise tlslite.errors.TLSAuthenticationError: If the checker
119 doesn't like the other party's authentication credentials.
120 """
121 handshaker = self._handshakeClientAsync(anonParams=(True),
122 session=session,
123 settings=settings,
124 checker=checker,
125 serverName=serverName)
126 if async:
127 return handshaker
128 for result in handshaker:
129 pass
130
131 - def handshakeClientSRP(self, username, password, session=None,
132 settings=None, checker=None,
133 reqTack=True, serverName="",
134 async=False):
135 """Perform an SRP handshake in the role of client.
136
137 This function performs a TLS/SRP handshake. SRP mutually
138 authenticates both parties to each other using only a
139 username and password. This function may also perform a
140 combined SRP and server-certificate handshake, if the server
141 chooses to authenticate itself with a certificate chain in
142 addition to doing SRP.
143
144 If the function completes without raising an exception, the
145 TLS connection will be open and available for data transfer.
146
147 If an exception is raised, the connection will have been
148 automatically closed (if it was ever open).
149
150 @type username: str
151 @param username: The SRP username.
152
153 @type password: str
154 @param password: The SRP password.
155
156 @type session: L{tlslite.session.Session}
157 @param session: A TLS session to attempt to resume. This
158 session must be an SRP session performed with the same username
159 and password as were passed in. If the resumption does not
160 succeed, a full SRP handshake will be performed.
161
162 @type settings: L{tlslite.handshakesettings.HandshakeSettings}
163 @param settings: Various settings which can be used to control
164 the ciphersuites, certificate types, and SSL/TLS versions
165 offered by the client.
166
167 @type checker: L{tlslite.checker.Checker}
168 @param checker: A Checker instance. This instance will be
169 invoked to examine the other party's authentication
170 credentials, if the handshake completes succesfully.
171
172 @type reqTack: bool
173 @param reqTack: Whether or not to send a "tack" TLS Extension,
174 requesting the server return a TackExtension if it has one.
175
176 @type serverName: string
177 @param serverName: The ServerNameIndication TLS Extension.
178
179 @type async: bool
180 @param async: If False, this function will block until the
181 handshake is completed. If True, this function will return a
182 generator. Successive invocations of the generator will
183 return 0 if it is waiting to read from the socket, 1 if it is
184 waiting to write to the socket, or will raise StopIteration if
185 the handshake operation is completed.
186
187 @rtype: None or an iterable
188 @return: If 'async' is True, a generator object will be
189 returned.
190
191 @raise socket.error: If a socket error occurs.
192 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
193 without a preceding alert.
194 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
195 @raise tlslite.errors.TLSAuthenticationError: If the checker
196 doesn't like the other party's authentication credentials.
197 """
198 handshaker = self._handshakeClientAsync(srpParams=(username, password),
199 session=session, settings=settings, checker=checker,
200 reqTack=reqTack, serverName=serverName)
201
202
203
204
205
206
207
208 if async:
209 return handshaker
210 for result in handshaker:
211 pass
212
213 - def handshakeClientCert(self, certChain=None, privateKey=None,
214 session=None, settings=None, checker=None,
215 nextProtos=None, reqTack=True, serverName="",
216 async=False):
217 """Perform a certificate-based handshake in the role of client.
218
219 This function performs an SSL or TLS handshake. The server
220 will authenticate itself using an X.509 certificate
221 chain. If the handshake succeeds, the server's certificate
222 chain will be stored in the session's serverCertChain attribute.
223 Unless a checker object is passed in, this function does no
224 validation or checking of the server's certificate chain.
225
226 If the server requests client authentication, the
227 client will send the passed-in certificate chain, and use the
228 passed-in private key to authenticate itself. If no
229 certificate chain and private key were passed in, the client
230 will attempt to proceed without client authentication. The
231 server may or may not allow this.
232
233 If the function completes without raising an exception, the
234 TLS connection will be open and available for data transfer.
235
236 If an exception is raised, the connection will have been
237 automatically closed (if it was ever open).
238
239 @type certChain: L{tlslite.x509certchain.X509CertChain}
240 @param certChain: The certificate chain to be used if the
241 server requests client authentication.
242
243 @type privateKey: L{tlslite.utils.rsakey.RSAKey}
244 @param privateKey: The private key to be used if the server
245 requests client authentication.
246
247 @type session: L{tlslite.session.Session}
248 @param session: A TLS session to attempt to resume. If the
249 resumption does not succeed, a full handshake will be
250 performed.
251
252 @type settings: L{tlslite.handshakesettings.HandshakeSettings}
253 @param settings: Various settings which can be used to control
254 the ciphersuites, certificate types, and SSL/TLS versions
255 offered by the client.
256
257 @type checker: L{tlslite.checker.Checker}
258 @param checker: A Checker instance. This instance will be
259 invoked to examine the other party's authentication
260 credentials, if the handshake completes succesfully.
261
262 @type nextProtos: list of strings.
263 @param nextProtos: A list of upper layer protocols ordered by
264 preference, to use in the Next-Protocol Negotiation Extension.
265
266 @type reqTack: bool
267 @param reqTack: Whether or not to send a "tack" TLS Extension,
268 requesting the server return a TackExtension if it has one.
269
270 @type serverName: string
271 @param serverName: The ServerNameIndication TLS Extension.
272
273 @type async: bool
274 @param async: If False, this function will block until the
275 handshake is completed. If True, this function will return a
276 generator. Successive invocations of the generator will
277 return 0 if it is waiting to read from the socket, 1 if it is
278 waiting to write to the socket, or will raise StopIteration if
279 the handshake operation is completed.
280
281 @rtype: None or an iterable
282 @return: If 'async' is True, a generator object will be
283 returned.
284
285 @raise socket.error: If a socket error occurs.
286 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
287 without a preceding alert.
288 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
289 @raise tlslite.errors.TLSAuthenticationError: If the checker
290 doesn't like the other party's authentication credentials.
291 """
292 handshaker = self._handshakeClientAsync(certParams=(certChain,
293 privateKey), session=session, settings=settings,
294 checker=checker, serverName=serverName,
295 nextProtos=nextProtos, reqTack=reqTack)
296
297
298
299
300
301
302
303 if async:
304 return handshaker
305 for result in handshaker:
306 pass
307
308
309 - def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
310 session=None, settings=None, checker=None,
311 nextProtos=None, serverName="", reqTack=True):
323
324
327
328 self._handshakeStart(client=True)
329
330
331 srpUsername = None
332 password = None
333 clientCertChain = None
334 privateKey = None
335
336
337 if srpParams:
338 assert(not certParams)
339 assert(not anonParams)
340 srpUsername, password = srpParams
341 if certParams:
342 assert(not srpParams)
343 assert(not anonParams)
344 clientCertChain, privateKey = certParams
345 if anonParams:
346 assert(not srpParams)
347 assert(not certParams)
348
349
350 if srpUsername and not password:
351 raise ValueError("Caller passed a username but no password")
352 if password and not srpUsername:
353 raise ValueError("Caller passed a password but no username")
354 if clientCertChain and not privateKey:
355 raise ValueError("Caller passed a certChain but no privateKey")
356 if privateKey and not clientCertChain:
357 raise ValueError("Caller passed a privateKey but no certChain")
358 if reqTack:
359 if not tackpyLoaded:
360 reqTack = False
361 if not settings or not settings.useExperimentalTackExtension:
362 reqTack = False
363 if nextProtos is not None:
364 if len(nextProtos) == 0:
365 raise ValueError("Caller passed no nextProtos")
366
367
368
369 if not settings:
370 settings = HandshakeSettings()
371 settings = settings._filter()
372
373 if clientCertChain:
374 if not isinstance(clientCertChain, X509CertChain):
375 raise ValueError("Unrecognized certificate type")
376 if "x509" not in settings.certificateTypes:
377 raise ValueError("Client certificate doesn't match "\
378 "Handshake Settings")
379
380 if session:
381
382
383 if not session.valid():
384 session = None
385 elif session.resumable:
386 if session.srpUsername != srpUsername:
387 raise ValueError("Session username doesn't match")
388 if session.serverName != serverName:
389 raise ValueError("Session servername doesn't match")
390
391
392 if srpUsername and self.fault == Fault.badUsername:
393 srpUsername += "GARBAGE"
394 if password and self.fault == Fault.badPassword:
395 password += "GARBAGE"
396
397
398
399
400 self.version = settings.maxVersion
401
402
403
404
405
406 for result in self._clientSendClientHello(settings, session,
407 srpUsername, srpParams, certParams,
408 anonParams, serverName, nextProtos,
409 reqTack):
410 if result in (0,1): yield result
411 else: break
412 clientHello = result
413
414
415 for result in self._clientGetServerHello(settings, clientHello):
416 if result in (0,1): yield result
417 else: break
418 serverHello = result
419 cipherSuite = serverHello.cipher_suite
420
421
422
423 nextProto = self._clientSelectNextProto(nextProtos, serverHello)
424
425
426 for result in self._clientResume(session, serverHello,
427 clientHello.random,
428 settings.cipherImplementations,
429 nextProto):
430 if result in (0,1): yield result
431 else: break
432 if result == "resumed_and_finished":
433 self._handshakeDone(resumed=True)
434 return
435
436
437
438
439 if cipherSuite in CipherSuite.srpAllSuites:
440 for result in self._clientSRPKeyExchange(\
441 settings, cipherSuite, serverHello.certificate_type,
442 srpUsername, password,
443 clientHello.random, serverHello.random,
444 serverHello.tackExt):
445 if result in (0,1): yield result
446 else: break
447 (premasterSecret, serverCertChain, tackExt) = result
448
449
450
451 elif cipherSuite in CipherSuite.anonSuites:
452 for result in self._clientAnonKeyExchange(settings, cipherSuite,
453 clientHello.random, serverHello.random):
454 if result in (0,1): yield result
455 else: break
456 (premasterSecret, serverCertChain, tackExt) = result
457
458
459
460
461
462
463
464 else:
465 for result in self._clientRSAKeyExchange(settings, cipherSuite,
466 clientCertChain, privateKey,
467 serverHello.certificate_type,
468 clientHello.random, serverHello.random,
469 serverHello.tackExt):
470 if result in (0,1): yield result
471 else: break
472 (premasterSecret, serverCertChain, clientCertChain,
473 tackExt) = result
474
475
476
477 for result in self._clientFinished(premasterSecret,
478 clientHello.random,
479 serverHello.random,
480 cipherSuite, settings.cipherImplementations,
481 nextProto):
482 if result in (0,1): yield result
483 else: break
484 masterSecret = result
485
486
487 self.session = Session()
488 self.session.create(masterSecret, serverHello.session_id, cipherSuite,
489 srpUsername, clientCertChain, serverCertChain,
490 tackExt, serverHello.tackExt!=None, serverName)
491 self._handshakeDone(resumed=False)
492
493
494 - def _clientSendClientHello(self, settings, session, srpUsername,
495 srpParams, certParams, anonParams,
496 serverName, nextProtos, reqTack):
497
498 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
499 if srpParams:
500 cipherSuites += CipherSuite.getSrpAllSuites(settings.cipherNames)
501 elif certParams:
502 cipherSuites += CipherSuite.getCertSuites(settings.cipherNames)
503 elif anonParams:
504 cipherSuites += CipherSuite.getAnonSuites(settings.cipherNames)
505 else:
506 assert(False)
507
508
509 certificateTypes = settings._getCertificateTypes()
510
511
512 if session and session.sessionID:
513
514
515 if session.cipherSuite not in cipherSuites:
516 raise ValueError("Session's cipher suite not consistent "\
517 "with parameters")
518 else:
519 clientHello = ClientHello()
520 clientHello.create(settings.maxVersion, getRandomBytes(32),
521 session.sessionID, cipherSuites,
522 certificateTypes,
523 session.srpUsername,
524 reqTack, nextProtos is not None,
525 session.serverName)
526
527
528 else:
529 clientHello = ClientHello()
530 clientHello.create(settings.maxVersion, getRandomBytes(32),
531 bytearray(0), cipherSuites,
532 certificateTypes,
533 srpUsername,
534 reqTack, nextProtos is not None,
535 serverName)
536 for result in self._sendMsg(clientHello):
537 yield result
538 yield clientHello
539
540
542 for result in self._getMsg(ContentType.handshake,
543 HandshakeType.server_hello):
544 if result in (0,1): yield result
545 else: break
546 serverHello = result
547
548
549
550 self.version = serverHello.server_version
551
552
553 self._versionCheck = True
554
555
556 if serverHello.server_version < settings.minVersion:
557 for result in self._sendError(\
558 AlertDescription.protocol_version,
559 "Too old version: %s" % str(serverHello.server_version)):
560 yield result
561 if serverHello.server_version > settings.maxVersion:
562 for result in self._sendError(\
563 AlertDescription.protocol_version,
564 "Too new version: %s" % str(serverHello.server_version)):
565 yield result
566 if serverHello.cipher_suite not in clientHello.cipher_suites:
567 for result in self._sendError(\
568 AlertDescription.illegal_parameter,
569 "Server responded with incorrect ciphersuite"):
570 yield result
571 if serverHello.certificate_type not in clientHello.certificate_types:
572 for result in self._sendError(\
573 AlertDescription.illegal_parameter,
574 "Server responded with incorrect certificate type"):
575 yield result
576 if serverHello.compression_method != 0:
577 for result in self._sendError(\
578 AlertDescription.illegal_parameter,
579 "Server responded with incorrect compression method"):
580 yield result
581 if serverHello.tackExt:
582 if not clientHello.tack:
583 for result in self._sendError(\
584 AlertDescription.illegal_parameter,
585 "Server responded with unrequested Tack Extension"):
586 yield result
587 if serverHello.next_protos and not clientHello.supports_npn:
588 for result in self._sendError(\
589 AlertDescription.illegal_parameter,
590 "Server responded with unrequested NPN Extension"):
591 yield result
592 if not serverHello.tackExt.verifySignatures():
593 for result in self._sendError(\
594 AlertDescription.decrypt_error,
595 "TackExtension contains an invalid signature"):
596 yield result
597 yield serverHello
598
600
601
602
603
604
605
606
607 if nextProtos is not None and serverHello.next_protos is not None:
608 for p in nextProtos:
609 if bytearray(p) in serverHello.next_protos:
610 return bytearray(p)
611 else:
612
613
614
615 return bytearray(nextProtos[0])
616 return None
617
618 - def _clientResume(self, session, serverHello, clientRandom,
619 cipherImplementations, nextProto):
645
646 - def _clientSRPKeyExchange(self, settings, cipherSuite, certificateType,
647 srpUsername, password,
648 clientRandom, serverRandom, tackExt):
649
650
651 if cipherSuite in CipherSuite.srpCertSuites:
652
653 for result in self._getMsg(ContentType.handshake,
654 HandshakeType.certificate, certificateType):
655 if result in (0,1): yield result
656 else: break
657 serverCertificate = result
658 else:
659 serverCertificate = None
660
661 for result in self._getMsg(ContentType.handshake,
662 HandshakeType.server_key_exchange, cipherSuite):
663 if result in (0,1): yield result
664 else: break
665 serverKeyExchange = result
666
667 for result in self._getMsg(ContentType.handshake,
668 HandshakeType.server_hello_done):
669 if result in (0,1): yield result
670 else: break
671 serverHelloDone = result
672
673
674
675 N = serverKeyExchange.srp_N
676 g = serverKeyExchange.srp_g
677 s = serverKeyExchange.srp_s
678 B = serverKeyExchange.srp_B
679
680 if (g,N) not in goodGroupParameters:
681 for result in self._sendError(\
682 AlertDescription.insufficient_security,
683 "Unknown group parameters"):
684 yield result
685 if numBits(N) < settings.minKeySize:
686 for result in self._sendError(\
687 AlertDescription.insufficient_security,
688 "N value is too small: %d" % numBits(N)):
689 yield result
690 if numBits(N) > settings.maxKeySize:
691 for result in self._sendError(\
692 AlertDescription.insufficient_security,
693 "N value is too large: %d" % numBits(N)):
694 yield result
695 if B % N == 0:
696 for result in self._sendError(\
697 AlertDescription.illegal_parameter,
698 "Suspicious B value"):
699 yield result
700
701
702
703 serverCertChain = None
704 if cipherSuite in CipherSuite.srpCertSuites:
705
706 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom)
707
708
709 sigBytes = serverKeyExchange.signature
710 if len(sigBytes) == 0:
711 for result in self._sendError(\
712 AlertDescription.illegal_parameter,
713 "Server sent an SRP ServerKeyExchange "\
714 "message without a signature"):
715 yield result
716
717
718
719
720 for result in self._clientGetKeyFromChain(serverCertificate,
721 settings, tackExt):
722 if result in (0,1): yield result
723 else: break
724 publicKey, serverCertChain, tackExt = result
725
726
727 if not publicKey.verify(sigBytes, hashBytes):
728 for result in self._sendError(\
729 AlertDescription.decrypt_error,
730 "Signature failed to verify"):
731 yield result
732
733
734 a = bytesToNumber(getRandomBytes(32))
735 A = powMod(g, a, N)
736
737
738 x = makeX(s, bytearray(srpUsername, "utf-8"),
739 bytearray(password, "utf-8"))
740 v = powMod(g, x, N)
741
742
743 u = makeU(N, A, B)
744
745
746 k = makeK(N, g)
747 S = powMod((B - (k*v)) % N, a+(u*x), N)
748
749 if self.fault == Fault.badA:
750 A = N
751 S = 0
752
753 premasterSecret = numberToByteArray(S)
754
755
756 for result in self._sendMsg(\
757 ClientKeyExchange(cipherSuite).createSRP(A)):
758 yield result
759 yield (premasterSecret, serverCertChain, tackExt)
760
761
762 - def _clientRSAKeyExchange(self, settings, cipherSuite,
763 clientCertChain, privateKey,
764 certificateType,
765 clientRandom, serverRandom,
766 tackExt):
767
768
769 for result in self._getMsg(ContentType.handshake,
770 HandshakeType.certificate, certificateType):
771 if result in (0,1): yield result
772 else: break
773 serverCertificate = result
774
775
776 for result in self._getMsg(ContentType.handshake,
777 (HandshakeType.server_hello_done,
778 HandshakeType.certificate_request)):
779 if result in (0,1): yield result
780 else: break
781 msg = result
782 certificateRequest = None
783 if isinstance(msg, CertificateRequest):
784 certificateRequest = msg
785
786 for result in self._getMsg(ContentType.handshake,
787 HandshakeType.server_hello_done):
788 if result in (0,1): yield result
789 else: break
790 serverHelloDone = result
791 elif isinstance(msg, ServerHelloDone):
792 serverHelloDone = msg
793
794
795
796
797 for result in self._clientGetKeyFromChain(serverCertificate,
798 settings, tackExt):
799 if result in (0,1): yield result
800 else: break
801 publicKey, serverCertChain, tackExt = result
802
803
804 premasterSecret = getRandomBytes(48)
805 premasterSecret[0] = settings.maxVersion[0]
806 premasterSecret[1] = settings.maxVersion[1]
807
808 if self.fault == Fault.badPremasterPadding:
809 premasterSecret[0] = 5
810 if self.fault == Fault.shortPremasterSecret:
811 premasterSecret = premasterSecret[:-1]
812
813
814 encryptedPreMasterSecret = publicKey.encrypt(premasterSecret)
815
816
817
818 if certificateRequest:
819 clientCertificate = Certificate(certificateType)
820
821 if clientCertChain:
822
823
824 wrongType = False
825 if certificateType == CertificateType.x509:
826 if not isinstance(clientCertChain, X509CertChain):
827 wrongType = True
828 if wrongType:
829 for result in self._sendError(\
830 AlertDescription.handshake_failure,
831 "Client certificate is of wrong type"):
832 yield result
833
834 clientCertificate.create(clientCertChain)
835 for result in self._sendMsg(clientCertificate):
836 yield result
837 else:
838
839
840
841 privateKey = None
842 clientCertChain = None
843
844
845 clientKeyExchange = ClientKeyExchange(cipherSuite,
846 self.version)
847 clientKeyExchange.createRSA(encryptedPreMasterSecret)
848 for result in self._sendMsg(clientKeyExchange):
849 yield result
850
851
852
853 if certificateRequest and privateKey:
854 if self.version == (3,0):
855 masterSecret = calcMasterSecret(self.version,
856 premasterSecret,
857 clientRandom,
858 serverRandom)
859 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
860 elif self.version in ((3,1), (3,2)):
861 verifyBytes = self._handshake_md5.digest() + \
862 self._handshake_sha.digest()
863 if self.fault == Fault.badVerifyMessage:
864 verifyBytes[0] = ((verifyBytes[0]+1) % 256)
865 signedBytes = privateKey.sign(verifyBytes)
866 certificateVerify = CertificateVerify()
867 certificateVerify.create(signedBytes)
868 for result in self._sendMsg(certificateVerify):
869 yield result
870 yield (premasterSecret, serverCertChain, clientCertChain, tackExt)
871
874 for result in self._getMsg(ContentType.handshake,
875 HandshakeType.server_key_exchange, cipherSuite):
876 if result in (0,1): yield result
877 else: break
878 serverKeyExchange = result
879
880 for result in self._getMsg(ContentType.handshake,
881 HandshakeType.server_hello_done):
882 if result in (0,1): yield result
883 else: break
884 serverHelloDone = result
885
886
887 dh_p = serverKeyExchange.dh_p
888 dh_g = serverKeyExchange.dh_g
889 dh_Xc = bytesToNumber(getRandomBytes(32))
890 dh_Ys = serverKeyExchange.dh_Ys
891 dh_Yc = powMod(dh_g, dh_Xc, dh_p)
892
893
894 for result in self._sendMsg(\
895 ClientKeyExchange(cipherSuite, self.version).createDH(dh_Yc)):
896 yield result
897
898
899 S = powMod(dh_Ys, dh_Xc, dh_p)
900 premasterSecret = numberToByteArray(S)
901
902 yield (premasterSecret, None, None)
903
904 - def _clientFinished(self, premasterSecret, clientRandom, serverRandom,
905 cipherSuite, cipherImplementations, nextProto):
906
907 masterSecret = calcMasterSecret(self.version, premasterSecret,
908 clientRandom, serverRandom)
909 self._calcPendingStates(cipherSuite, masterSecret,
910 clientRandom, serverRandom,
911 cipherImplementations)
912
913
914 for result in self._sendFinished(masterSecret, nextProto):
915 yield result
916 for result in self._getFinished(masterSecret, nextProto=nextProto):
917 yield result
918 yield masterSecret
919
956
957
958
959
960
961
962
963 - def handshakeServer(self, verifierDB=None,
964 certChain=None, privateKey=None, reqCert=False,
965 sessionCache=None, settings=None, checker=None,
966 reqCAs = None,
967 tacks=None, activationFlags=0,
968 nextProtos=None, anon=False):
969 """Perform a handshake in the role of server.
970
971 This function performs an SSL or TLS handshake. Depending on
972 the arguments and the behavior of the client, this function can
973 perform an SRP, or certificate-based handshake. It
974 can also perform a combined SRP and server-certificate
975 handshake.
976
977 Like any handshake function, this can be called on a closed
978 TLS connection, or on a TLS connection that is already open.
979 If called on an open connection it performs a re-handshake.
980 This function does not send a Hello Request message before
981 performing the handshake, so if re-handshaking is required,
982 the server must signal the client to begin the re-handshake
983 through some other means.
984
985 If the function completes without raising an exception, the
986 TLS connection will be open and available for data transfer.
987
988 If an exception is raised, the connection will have been
989 automatically closed (if it was ever open).
990
991 @type verifierDB: L{tlslite.verifierdb.VerifierDB}
992 @param verifierDB: A database of SRP password verifiers
993 associated with usernames. If the client performs an SRP
994 handshake, the session's srpUsername attribute will be set.
995
996 @type certChain: L{tlslite.x509certchain.X509CertChain}
997 @param certChain: The certificate chain to be used if the
998 client requests server certificate authentication.
999
1000 @type privateKey: L{tlslite.utils.rsakey.RSAKey}
1001 @param privateKey: The private key to be used if the client
1002 requests server certificate authentication.
1003
1004 @type reqCert: bool
1005 @param reqCert: Whether to request client certificate
1006 authentication. This only applies if the client chooses server
1007 certificate authentication; if the client chooses SRP
1008 authentication, this will be ignored. If the client
1009 performs a client certificate authentication, the sessions's
1010 clientCertChain attribute will be set.
1011
1012 @type sessionCache: L{tlslite.sessioncache.SessionCache}
1013 @param sessionCache: An in-memory cache of resumable sessions.
1014 The client can resume sessions from this cache. Alternatively,
1015 if the client performs a full handshake, a new session will be
1016 added to the cache.
1017
1018 @type settings: L{tlslite.handshakesettings.HandshakeSettings}
1019 @param settings: Various settings which can be used to control
1020 the ciphersuites and SSL/TLS version chosen by the server.
1021
1022 @type checker: L{tlslite.checker.Checker}
1023 @param checker: A Checker instance. This instance will be
1024 invoked to examine the other party's authentication
1025 credentials, if the handshake completes succesfully.
1026
1027 @type reqCAs: list of L{bytearray} of unsigned bytes
1028 @param reqCAs: A collection of DER-encoded DistinguishedNames that
1029 will be sent along with a certificate request. This does not affect
1030 verification.
1031
1032 @type nextProtos: list of strings.
1033 @param nextProtos: A list of upper layer protocols to expose to the
1034 clients through the Next-Protocol Negotiation Extension,
1035 if they support it.
1036
1037 @raise socket.error: If a socket error occurs.
1038 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
1039 without a preceding alert.
1040 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
1041 @raise tlslite.errors.TLSAuthenticationError: If the checker
1042 doesn't like the other party's authentication credentials.
1043 """
1044 for result in self.handshakeServerAsync(verifierDB,
1045 certChain, privateKey, reqCert, sessionCache, settings,
1046 checker, reqCAs,
1047 tacks=tacks, activationFlags=activationFlags,
1048 nextProtos=nextProtos, anon=anon):
1049 pass
1050
1051
1052 - def handshakeServerAsync(self, verifierDB=None,
1053 certChain=None, privateKey=None, reqCert=False,
1054 sessionCache=None, settings=None, checker=None,
1055 reqCAs=None,
1056 tacks=None, activationFlags=0,
1057 nextProtos=None, anon=False
1058 ):
1059 """Start a server handshake operation on the TLS connection.
1060
1061 This function returns a generator which behaves similarly to
1062 handshakeServer(). Successive invocations of the generator
1063 will return 0 if it is waiting to read from the socket, 1 if it is
1064 waiting to write to the socket, or it will raise StopIteration
1065 if the handshake operation is complete.
1066
1067 @rtype: iterable
1068 @return: A generator; see above for details.
1069 """
1070 handshaker = self._handshakeServerAsyncHelper(\
1071 verifierDB=verifierDB, certChain=certChain,
1072 privateKey=privateKey, reqCert=reqCert,
1073 sessionCache=sessionCache, settings=settings,
1074 reqCAs=reqCAs,
1075 tacks=tacks, activationFlags=activationFlags,
1076 nextProtos=nextProtos, anon=anon)
1077 for result in self._handshakeWrapperAsync(handshaker, checker):
1078 yield result
1079
1080
1081 - def _handshakeServerAsyncHelper(self, verifierDB,
1082 certChain, privateKey, reqCert, sessionCache,
1083 settings, reqCAs,
1084 tacks, activationFlags,
1085 nextProtos, anon):
1086
1087 self._handshakeStart(client=False)
1088
1089 if (not verifierDB) and (not certChain) and not anon:
1090 raise ValueError("Caller passed no authentication credentials")
1091 if certChain and not privateKey:
1092 raise ValueError("Caller passed a certChain but no privateKey")
1093 if privateKey and not certChain:
1094 raise ValueError("Caller passed a privateKey but no certChain")
1095 if reqCAs and not reqCert:
1096 raise ValueError("Caller passed reqCAs but not reqCert")
1097 if certChain and not isinstance(certChain, X509CertChain):
1098 raise ValueError("Unrecognized certificate type")
1099 if activationFlags and not tacks:
1100 raise ValueError("Nonzero activationFlags requires tacks")
1101 if tacks:
1102 if not tackpyLoaded:
1103 raise ValueError("tackpy is not loaded")
1104 if not settings or not settings.useExperimentalTackExtension:
1105 raise ValueError("useExperimentalTackExtension not enabled")
1106
1107 if not settings:
1108 settings = HandshakeSettings()
1109 settings = settings._filter()
1110
1111
1112
1113
1114
1115 for result in self._serverGetClientHello(settings, certChain,\
1116 verifierDB, sessionCache,
1117 anon):
1118 if result in (0,1): yield result
1119 elif result == None:
1120 self._handshakeDone(resumed=True)
1121 return
1122 else: break
1123 (clientHello, cipherSuite) = result
1124
1125
1126
1127
1128 if sessionCache:
1129 sessionID = getRandomBytes(32)
1130 else:
1131 sessionID = bytearray(0)
1132
1133 if not clientHello.supports_npn:
1134 nextProtos = None
1135
1136
1137 if not cipherSuite in CipherSuite.certAllSuites:
1138 tacks = None
1139
1140
1141 if clientHello.tack:
1142 tackExt = TackExtension.create(tacks, activationFlags)
1143 else:
1144 tackExt = None
1145 serverHello = ServerHello()
1146 serverHello.create(self.version, getRandomBytes(32), sessionID, \
1147 cipherSuite, CertificateType.x509, tackExt,
1148 nextProtos)
1149
1150
1151 clientCertChain = None
1152 if cipherSuite in CipherSuite.srpAllSuites:
1153 for result in self._serverSRPKeyExchange(clientHello, serverHello,
1154 verifierDB, cipherSuite,
1155 privateKey, certChain):
1156 if result in (0,1): yield result
1157 else: break
1158 premasterSecret = result
1159
1160
1161 elif cipherSuite in CipherSuite.certSuites:
1162 for result in self._serverCertKeyExchange(clientHello, serverHello,
1163 certChain, privateKey,
1164 reqCert, reqCAs, cipherSuite,
1165 settings):
1166 if result in (0,1): yield result
1167 else: break
1168 (premasterSecret, clientCertChain) = result
1169
1170
1171 elif cipherSuite in CipherSuite.anonSuites:
1172 for result in self._serverAnonKeyExchange(clientHello, serverHello,
1173 cipherSuite, settings):
1174 if result in (0,1): yield result
1175 else: break
1176 premasterSecret = result
1177
1178 else:
1179 assert(False)
1180
1181
1182 for result in self._serverFinished(premasterSecret,
1183 clientHello.random, serverHello.random,
1184 cipherSuite, settings.cipherImplementations,
1185 nextProtos):
1186 if result in (0,1): yield result
1187 else: break
1188 masterSecret = result
1189
1190
1191 self.session = Session()
1192 if cipherSuite in CipherSuite.certAllSuites:
1193 serverCertChain = certChain
1194 else:
1195 serverCertChain = None
1196 srpUsername = None
1197 serverName = None
1198 if clientHello.srp_username:
1199 srpUsername = clientHello.srp_username.decode("utf-8")
1200 if clientHello.server_name:
1201 serverName = clientHello.server_name.decode("utf-8")
1202 self.session.create(masterSecret, serverHello.session_id, cipherSuite,
1203 srpUsername, clientCertChain, serverCertChain,
1204 tackExt, serverHello.tackExt!=None, serverName)
1205
1206
1207 if sessionCache and sessionID:
1208 sessionCache[sessionID] = self.session
1209
1210 self._handshakeDone(resumed=False)
1211
1212
1215
1216 cipherSuites = []
1217 if verifierDB:
1218 if certChain:
1219 cipherSuites += \
1220 CipherSuite.getSrpCertSuites(settings.cipherNames)
1221 cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
1222 elif certChain:
1223 cipherSuites += CipherSuite.getCertSuites(settings.cipherNames)
1224 elif anon:
1225 cipherSuites += CipherSuite.getAnonSuites(settings.cipherNames)
1226 else:
1227 assert(False)
1228
1229
1230
1231
1232 self.version = settings.maxVersion
1233
1234
1235 for result in self._getMsg(ContentType.handshake,
1236 HandshakeType.client_hello):
1237 if result in (0,1): yield result
1238 else: break
1239 clientHello = result
1240
1241
1242 if clientHello.client_version < settings.minVersion:
1243 self.version = settings.minVersion
1244 for result in self._sendError(\
1245 AlertDescription.protocol_version,
1246 "Too old version: %s" % str(clientHello.client_version)):
1247 yield result
1248
1249
1250 elif clientHello.client_version > settings.maxVersion:
1251 self.version = settings.maxVersion
1252
1253 else:
1254
1255 self.version = clientHello.client_version
1256
1257
1258 if clientHello.session_id and sessionCache:
1259 session = None
1260
1261
1262 if sessionCache and not session:
1263 try:
1264 session = sessionCache[clientHello.session_id]
1265 if not session.resumable:
1266 raise AssertionError()
1267
1268 if session.cipherSuite not in cipherSuites:
1269 for result in self._sendError(\
1270 AlertDescription.handshake_failure):
1271 yield result
1272 if session.cipherSuite not in clientHello.cipher_suites:
1273 for result in self._sendError(\
1274 AlertDescription.handshake_failure):
1275 yield result
1276 if clientHello.srp_username:
1277 if not session.srpUsername or \
1278 clientHello.srp_username != bytearray(session.srpUsername, "utf-8"):
1279 for result in self._sendError(\
1280 AlertDescription.handshake_failure):
1281 yield result
1282 if clientHello.server_name:
1283 if not session.serverName or \
1284 clientHello.server_name != bytearray(session.serverName, "utf-8"):
1285 for result in self._sendError(\
1286 AlertDescription.handshake_failure):
1287 yield result
1288 except KeyError:
1289 pass
1290
1291
1292 if session:
1293
1294 serverHello = ServerHello()
1295 serverHello.create(self.version, getRandomBytes(32),
1296 session.sessionID, session.cipherSuite,
1297 CertificateType.x509, None, None)
1298 for result in self._sendMsg(serverHello):
1299 yield result
1300
1301
1302 self._versionCheck = True
1303
1304
1305 self._calcPendingStates(session.cipherSuite,
1306 session.masterSecret,
1307 clientHello.random,
1308 serverHello.random,
1309 settings.cipherImplementations)
1310
1311
1312 for result in self._sendFinished(session.masterSecret):
1313 yield result
1314 for result in self._getFinished(session.masterSecret):
1315 yield result
1316
1317
1318 self.session = session
1319
1320 yield None
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330 for cipherSuite in cipherSuites:
1331 if cipherSuite in clientHello.cipher_suites:
1332 break
1333 else:
1334 for result in self._sendError(\
1335 AlertDescription.handshake_failure,
1336 "No mutual ciphersuite"):
1337 yield result
1338 if cipherSuite in CipherSuite.srpAllSuites and \
1339 not clientHello.srp_username:
1340 for result in self._sendError(\
1341 AlertDescription.unknown_psk_identity,
1342 "Client sent a hello, but without the SRP username"):
1343 yield result
1344
1345
1346 if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \
1347 not in clientHello.certificate_types:
1348 for result in self._sendError(\
1349 AlertDescription.handshake_failure,
1350 "the client doesn't support my certificate type"):
1351 yield result
1352
1353
1354
1355
1356 yield (clientHello, cipherSuite)
1357
1358 - def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB,
1359 cipherSuite, privateKey, serverCertChain):
1360
1361 srpUsername = clientHello.srp_username.decode("utf-8")
1362 self.allegedSrpUsername = srpUsername
1363
1364 try:
1365 entry = verifierDB[srpUsername]
1366 except KeyError:
1367 for result in self._sendError(\
1368 AlertDescription.unknown_psk_identity):
1369 yield result
1370 (N, g, s, v) = entry
1371
1372
1373 b = bytesToNumber(getRandomBytes(32))
1374 k = makeK(N, g)
1375 B = (powMod(g, b, N) + (k*v)) % N
1376
1377
1378 serverKeyExchange = ServerKeyExchange(cipherSuite)
1379 serverKeyExchange.createSRP(N, g, s, B)
1380 if cipherSuite in CipherSuite.srpCertSuites:
1381 hashBytes = serverKeyExchange.hash(clientHello.random,
1382 serverHello.random)
1383 serverKeyExchange.signature = privateKey.sign(hashBytes)
1384
1385
1386
1387 msgs = []
1388 msgs.append(serverHello)
1389 if cipherSuite in CipherSuite.srpCertSuites:
1390 certificateMsg = Certificate(CertificateType.x509)
1391 certificateMsg.create(serverCertChain)
1392 msgs.append(certificateMsg)
1393 msgs.append(serverKeyExchange)
1394 msgs.append(ServerHelloDone())
1395 for result in self._sendMsgs(msgs):
1396 yield result
1397
1398
1399 self._versionCheck = True
1400
1401
1402 for result in self._getMsg(ContentType.handshake,
1403 HandshakeType.client_key_exchange,
1404 cipherSuite):
1405 if result in (0,1): yield result
1406 else: break
1407 clientKeyExchange = result
1408 A = clientKeyExchange.srp_A
1409 if A % N == 0:
1410 for result in self._sendError(AlertDescription.illegal_parameter,
1411 "Suspicious A value"):
1412 yield result
1413 assert(False)
1414
1415
1416 u = makeU(N, A, B)
1417
1418
1419 S = powMod((A * powMod(v,u,N)) % N, b, N)
1420 premasterSecret = numberToByteArray(S)
1421
1422 yield premasterSecret
1423
1424
1425 - def _serverCertKeyExchange(self, clientHello, serverHello,
1426 serverCertChain, privateKey,
1427 reqCert, reqCAs, cipherSuite,
1428 settings):
1429
1430
1431 msgs = []
1432
1433
1434 clientCertChain = None
1435
1436 msgs.append(serverHello)
1437 msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
1438 if reqCert and reqCAs:
1439 msgs.append(CertificateRequest().create(\
1440 [ClientCertificateType.rsa_sign], reqCAs))
1441 elif reqCert:
1442 msgs.append(CertificateRequest())
1443 msgs.append(ServerHelloDone())
1444 for result in self._sendMsgs(msgs):
1445 yield result
1446
1447
1448 self._versionCheck = True
1449
1450
1451 if reqCert:
1452 if self.version == (3,0):
1453 for result in self._getMsg((ContentType.handshake,
1454 ContentType.alert),
1455 HandshakeType.certificate,
1456 CertificateType.x509):
1457 if result in (0,1): yield result
1458 else: break
1459 msg = result
1460
1461 if isinstance(msg, Alert):
1462
1463 alert = msg
1464 if alert.description != \
1465 AlertDescription.no_certificate:
1466 self._shutdown(False)
1467 raise TLSRemoteAlert(alert)
1468 elif isinstance(msg, Certificate):
1469 clientCertificate = msg
1470 if clientCertificate.certChain and \
1471 clientCertificate.certChain.getNumCerts()!=0:
1472 clientCertChain = clientCertificate.certChain
1473 else:
1474 raise AssertionError()
1475 elif self.version in ((3,1), (3,2)):
1476 for result in self._getMsg(ContentType.handshake,
1477 HandshakeType.certificate,
1478 CertificateType.x509):
1479 if result in (0,1): yield result
1480 else: break
1481 clientCertificate = result
1482 if clientCertificate.certChain and \
1483 clientCertificate.certChain.getNumCerts()!=0:
1484 clientCertChain = clientCertificate.certChain
1485 else:
1486 raise AssertionError()
1487
1488
1489 for result in self._getMsg(ContentType.handshake,
1490 HandshakeType.client_key_exchange,
1491 cipherSuite):
1492 if result in (0,1): yield result
1493 else: break
1494 clientKeyExchange = result
1495
1496
1497 premasterSecret = privateKey.decrypt(\
1498 clientKeyExchange.encryptedPreMasterSecret)
1499
1500
1501
1502 randomPreMasterSecret = getRandomBytes(48)
1503 versionCheck = (premasterSecret[0], premasterSecret[1])
1504 if not premasterSecret:
1505 premasterSecret = randomPreMasterSecret
1506 elif len(premasterSecret)!=48:
1507 premasterSecret = randomPreMasterSecret
1508 elif versionCheck != clientHello.client_version:
1509 if versionCheck != self.version:
1510 premasterSecret = randomPreMasterSecret
1511
1512
1513 if clientCertChain:
1514 if self.version == (3,0):
1515 masterSecret = calcMasterSecret(self.version, premasterSecret,
1516 clientHello.random, serverHello.random)
1517 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
1518 elif self.version in ((3,1), (3,2)):
1519 verifyBytes = self._handshake_md5.digest() + \
1520 self._handshake_sha.digest()
1521 for result in self._getMsg(ContentType.handshake,
1522 HandshakeType.certificate_verify):
1523 if result in (0,1): yield result
1524 else: break
1525 certificateVerify = result
1526 publicKey = clientCertChain.getEndEntityPublicKey()
1527 if len(publicKey) < settings.minKeySize:
1528 for result in self._sendError(\
1529 AlertDescription.handshake_failure,
1530 "Client's public key too small: %d" % len(publicKey)):
1531 yield result
1532
1533 if len(publicKey) > settings.maxKeySize:
1534 for result in self._sendError(\
1535 AlertDescription.handshake_failure,
1536 "Client's public key too large: %d" % len(publicKey)):
1537 yield result
1538
1539 if not publicKey.verify(certificateVerify.signature, verifyBytes):
1540 for result in self._sendError(\
1541 AlertDescription.decrypt_error,
1542 "Signature failed to verify"):
1543 yield result
1544 yield (premasterSecret, clientCertChain)
1545
1546
1549
1550 dh_p = getRandomSafePrime(32, False)
1551 dh_g = getRandomNumber(2, dh_p)
1552 dh_Xs = bytesToNumber(getRandomBytes(32))
1553 dh_Ys = powMod(dh_g, dh_Xs, dh_p)
1554
1555
1556 serverKeyExchange = ServerKeyExchange(cipherSuite)
1557 serverKeyExchange.createDH(dh_p, dh_g, dh_Ys)
1558
1559
1560
1561 msgs = []
1562 msgs.append(serverHello)
1563 msgs.append(serverKeyExchange)
1564 msgs.append(ServerHelloDone())
1565 for result in self._sendMsgs(msgs):
1566 yield result
1567
1568
1569 self._versionCheck = True
1570
1571
1572 for result in self._getMsg(ContentType.handshake,
1573 HandshakeType.client_key_exchange,
1574 cipherSuite):
1575 if result in (0,1):
1576 yield result
1577 else:
1578 break
1579 clientKeyExchange = result
1580 dh_Yc = clientKeyExchange.dh_Yc
1581
1582 if dh_Yc % dh_p == 0:
1583 for result in self._sendError(AlertDescription.illegal_parameter,
1584 "Suspicious dh_Yc value"):
1585 yield result
1586 assert(False)
1587
1588
1589 S = powMod(dh_Yc,dh_Xs,dh_p)
1590 premasterSecret = numberToByteArray(S)
1591
1592 yield premasterSecret
1593
1594
1595 - def _serverFinished(self, premasterSecret, clientRandom, serverRandom,
1596 cipherSuite, cipherImplementations, nextProtos):
1597 masterSecret = calcMasterSecret(self.version, premasterSecret,
1598 clientRandom, serverRandom)
1599
1600
1601 self._calcPendingStates(cipherSuite, masterSecret,
1602 clientRandom, serverRandom,
1603 cipherImplementations)
1604
1605
1606 for result in self._getFinished(masterSecret,
1607 expect_next_protocol=nextProtos is not None):
1608 yield result
1609
1610 for result in self._sendFinished(masterSecret):
1611 yield result
1612
1613 yield masterSecret
1614
1615
1616
1617
1618
1619
1620
1643
1644 - def _getFinished(self, masterSecret, expect_next_protocol=False, nextProto=None):
1690
1692 if self.version == (3,0):
1693 if (self._client and send) or (not self._client and not send):
1694 senderStr = b"\x43\x4C\x4E\x54"
1695 else:
1696 senderStr = b"\x53\x52\x56\x52"
1697
1698 verifyData = self._calcSSLHandshakeHash(masterSecret, senderStr)
1699 return verifyData
1700
1701 elif self.version in ((3,1), (3,2)):
1702 if (self._client and send) or (not self._client and not send):
1703 label = b"client finished"
1704 else:
1705 label = b"server finished"
1706
1707 handshakeHashes = self._handshake_md5.digest() + \
1708 self._handshake_sha.digest()
1709 verifyData = PRF(masterSecret, label, handshakeHashes, 12)
1710 return verifyData
1711 else:
1712 raise AssertionError()
1713
1714
1741