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