- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / tlslite / tlslite / TLSConnection.py
1 """
2 MAIN CLASS FOR TLS LITE (START HERE!).
3 """
4 from __future__ import generators
5
6 import socket
7 from utils.compat import formatExceptionTrace
8 from TLSRecordLayer import TLSRecordLayer
9 from Session import Session
10 from constants import *
11 from utils.cryptomath import getRandomBytes
12 from errors import *
13 from messages import *
14 from mathtls import *
15 from HandshakeSettings import HandshakeSettings
16
17
18 class TLSConnection(TLSRecordLayer):
19     """
20     This class wraps a socket and provides TLS handshaking and data
21     transfer.
22
23     To use this class, create a new instance, passing a connected
24     socket into the constructor.  Then call some handshake function.
25     If the handshake completes without raising an exception, then a TLS
26     connection has been negotiated.  You can transfer data over this
27     connection as if it were a socket.
28
29     This class provides both synchronous and asynchronous versions of
30     its key functions.  The synchronous versions should be used when
31     writing single-or multi-threaded code using blocking sockets.  The
32     asynchronous versions should be used when performing asynchronous,
33     event-based I/O with non-blocking sockets.
34
35     Asynchronous I/O is a complicated subject; typically, you should
36     not use the asynchronous functions directly, but should use some
37     framework like asyncore or Twisted which TLS Lite integrates with
38     (see
39     L{tlslite.integration.TLSAsyncDispatcherMixIn.TLSAsyncDispatcherMixIn} or
40     L{tlslite.integration.TLSTwistedProtocolWrapper.TLSTwistedProtocolWrapper}).
41     """
42
43
44     def __init__(self, sock):
45         """Create a new TLSConnection instance.
46
47         @param sock: The socket data will be transmitted on.  The
48         socket should already be connected.  It may be in blocking or
49         non-blocking mode.
50
51         @type sock: L{socket.socket}
52         """
53         TLSRecordLayer.__init__(self, sock)
54
55     def handshakeClientSRP(self, username, password, session=None,
56                            settings=None, checker=None, async=False):
57         """Perform an SRP handshake in the role of client.
58
59         This function performs a TLS/SRP handshake.  SRP mutually
60         authenticates both parties to each other using only a
61         username and password.  This function may also perform a
62         combined SRP and server-certificate handshake, if the server
63         chooses to authenticate itself with a certificate chain in
64         addition to doing SRP.
65
66         TLS/SRP is non-standard.  Most TLS implementations don't
67         support it.  See
68         U{http://www.ietf.org/html.charters/tls-charter.html} or
69         U{http://trevp.net/tlssrp/} for the latest information on
70         TLS/SRP.
71
72         Like any handshake function, this can be called on a closed
73         TLS connection, or on a TLS connection that is already open.
74         If called on an open connection it performs a re-handshake.
75
76         If the function completes without raising an exception, the
77         TLS connection will be open and available for data transfer.
78
79         If an exception is raised, the connection will have been
80         automatically closed (if it was ever open).
81
82         @type username: str
83         @param username: The SRP username.
84
85         @type password: str
86         @param password: The SRP password.
87
88         @type session: L{tlslite.Session.Session}
89         @param session: A TLS session to attempt to resume.  This
90         session must be an SRP session performed with the same username
91         and password as were passed in.  If the resumption does not
92         succeed, a full SRP handshake will be performed.
93
94         @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
95         @param settings: Various settings which can be used to control
96         the ciphersuites, certificate types, and SSL/TLS versions
97         offered by the client.
98
99         @type checker: L{tlslite.Checker.Checker}
100         @param checker: A Checker instance.  This instance will be
101         invoked to examine the other party's authentication
102         credentials, if the handshake completes succesfully.
103
104         @type async: bool
105         @param async: If False, this function will block until the
106         handshake is completed.  If True, this function will return a
107         generator.  Successive invocations of the generator will
108         return 0 if it is waiting to read from the socket, 1 if it is
109         waiting to write to the socket, or will raise StopIteration if
110         the handshake operation is completed.
111
112         @rtype: None or an iterable
113         @return: If 'async' is True, a generator object will be
114         returned.
115
116         @raise socket.error: If a socket error occurs.
117         @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
118         without a preceding alert.
119         @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
120         @raise tlslite.errors.TLSAuthenticationError: If the checker
121         doesn't like the other party's authentication credentials.
122         """
123         handshaker = self._handshakeClientAsync(srpParams=(username, password),
124                         session=session, settings=settings, checker=checker)
125         if async:
126             return handshaker
127         for result in handshaker:
128             pass
129
130     def handshakeClientCert(self, certChain=None, privateKey=None,
131                             session=None, settings=None, checker=None,
132                             async=False):
133         """Perform a certificate-based handshake in the role of client.
134
135         This function performs an SSL or TLS handshake.  The server
136         will authenticate itself using an X.509 or cryptoID certificate
137         chain.  If the handshake succeeds, the server's certificate
138         chain will be stored in the session's serverCertChain attribute.
139         Unless a checker object is passed in, this function does no
140         validation or checking of the server's certificate chain.
141
142         If the server requests client authentication, the
143         client will send the passed-in certificate chain, and use the
144         passed-in private key to authenticate itself.  If no
145         certificate chain and private key were passed in, the client
146         will attempt to proceed without client authentication.  The
147         server may or may not allow this.
148
149         Like any handshake function, this can be called on a closed
150         TLS connection, or on a TLS connection that is already open.
151         If called on an open connection it performs a re-handshake.
152
153         If the function completes without raising an exception, the
154         TLS connection will be open and available for data transfer.
155
156         If an exception is raised, the connection will have been
157         automatically closed (if it was ever open).
158
159         @type certChain: L{tlslite.X509CertChain.X509CertChain} or
160         L{cryptoIDlib.CertChain.CertChain}
161         @param certChain: The certificate chain to be used if the
162         server requests client authentication.
163
164         @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
165         @param privateKey: The private key to be used if the server
166         requests client authentication.
167
168         @type session: L{tlslite.Session.Session}
169         @param session: A TLS session to attempt to resume.  If the
170         resumption does not succeed, a full handshake will be
171         performed.
172
173         @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
174         @param settings: Various settings which can be used to control
175         the ciphersuites, certificate types, and SSL/TLS versions
176         offered by the client.
177
178         @type checker: L{tlslite.Checker.Checker}
179         @param checker: A Checker instance.  This instance will be
180         invoked to examine the other party's authentication
181         credentials, if the handshake completes succesfully.
182
183         @type async: bool
184         @param async: If False, this function will block until the
185         handshake is completed.  If True, this function will return a
186         generator.  Successive invocations of the generator will
187         return 0 if it is waiting to read from the socket, 1 if it is
188         waiting to write to the socket, or will raise StopIteration if
189         the handshake operation is completed.
190
191         @rtype: None or an iterable
192         @return: If 'async' is True, a generator object will be
193         returned.
194
195         @raise socket.error: If a socket error occurs.
196         @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
197         without a preceding alert.
198         @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
199         @raise tlslite.errors.TLSAuthenticationError: If the checker
200         doesn't like the other party's authentication credentials.
201         """
202         handshaker = self._handshakeClientAsync(certParams=(certChain,
203                         privateKey), session=session, settings=settings,
204                         checker=checker)
205         if async:
206             return handshaker
207         for result in handshaker:
208             pass
209
210     def handshakeClientUnknown(self, srpCallback=None, certCallback=None,
211                                session=None, settings=None, checker=None,
212                                async=False):
213         """Perform a to-be-determined type of handshake in the role of client.
214
215         This function performs an SSL or TLS handshake.  If the server
216         requests client certificate authentication, the
217         certCallback will be invoked and should return a (certChain,
218         privateKey) pair.  If the callback returns None, the library
219         will attempt to proceed without client authentication.  The
220         server may or may not allow this.
221
222         If the server requests SRP authentication, the srpCallback
223         will be invoked and should return a (username, password) pair.
224         If the callback returns None, the local implementation will
225         signal a user_canceled error alert.
226
227         After the handshake completes, the client can inspect the
228         connection's session attribute to determine what type of
229         authentication was performed.
230
231         Like any handshake function, this can be called on a closed
232         TLS connection, or on a TLS connection that is already open.
233         If called on an open connection it performs a re-handshake.
234
235         If the function completes without raising an exception, the
236         TLS connection will be open and available for data transfer.
237
238         If an exception is raised, the connection will have been
239         automatically closed (if it was ever open).
240
241         @type srpCallback: callable
242         @param srpCallback: The callback to be used if the server
243         requests SRP authentication.  If None, the client will not
244         offer support for SRP ciphersuites.
245
246         @type certCallback: callable
247         @param certCallback: The callback to be used if the server
248         requests client certificate authentication.
249
250         @type session: L{tlslite.Session.Session}
251         @param session: A TLS session to attempt to resume.  If the
252         resumption does not succeed, a full handshake will be
253         performed.
254
255         @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
256         @param settings: Various settings which can be used to control
257         the ciphersuites, certificate types, and SSL/TLS versions
258         offered by the client.
259
260         @type checker: L{tlslite.Checker.Checker}
261         @param checker: A Checker instance.  This instance will be
262         invoked to examine the other party's authentication
263         credentials, if the handshake completes succesfully.
264
265         @type async: bool
266         @param async: If False, this function will block until the
267         handshake is completed.  If True, this function will return a
268         generator.  Successive invocations of the generator will
269         return 0 if it is waiting to read from the socket, 1 if it is
270         waiting to write to the socket, or will raise StopIteration if
271         the handshake operation is completed.
272
273         @rtype: None or an iterable
274         @return: If 'async' is True, a generator object will be
275         returned.
276
277         @raise socket.error: If a socket error occurs.
278         @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
279         without a preceding alert.
280         @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
281         @raise tlslite.errors.TLSAuthenticationError: If the checker
282         doesn't like the other party's authentication credentials.
283         """
284         handshaker = self._handshakeClientAsync(unknownParams=(srpCallback,
285                         certCallback), session=session, settings=settings,
286                         checker=checker)
287         if async:
288             return handshaker
289         for result in handshaker:
290             pass
291
292     def handshakeClientSharedKey(self, username, sharedKey, settings=None,
293                                  checker=None, async=False):
294         """Perform a shared-key handshake in the role of client.
295
296         This function performs a shared-key handshake.  Using shared
297         symmetric keys of high entropy (128 bits or greater) mutually
298         authenticates both parties to each other.
299
300         TLS with shared-keys is non-standard.  Most TLS
301         implementations don't support it.  See
302         U{http://www.ietf.org/html.charters/tls-charter.html} for the
303         latest information on TLS with shared-keys.  If the shared-keys
304         Internet-Draft changes or is superceded, TLS Lite will track
305         those changes, so the shared-key support in later versions of
306         TLS Lite may become incompatible with this version.
307
308         Like any handshake function, this can be called on a closed
309         TLS connection, or on a TLS connection that is already open.
310         If called on an open connection it performs a re-handshake.
311
312         If the function completes without raising an exception, the
313         TLS connection will be open and available for data transfer.
314
315         If an exception is raised, the connection will have been
316         automatically closed (if it was ever open).
317
318         @type username: str
319         @param username: The shared-key username.
320
321         @type sharedKey: str
322         @param sharedKey: The shared key.
323
324         @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
325         @param settings: Various settings which can be used to control
326         the ciphersuites, certificate types, and SSL/TLS versions
327         offered by the client.
328
329         @type checker: L{tlslite.Checker.Checker}
330         @param checker: A Checker instance.  This instance will be
331         invoked to examine the other party's authentication
332         credentials, if the handshake completes succesfully.
333
334         @type async: bool
335         @param async: If False, this function will block until the
336         handshake is completed.  If True, this function will return a
337         generator.  Successive invocations of the generator will
338         return 0 if it is waiting to read from the socket, 1 if it is
339         waiting to write to the socket, or will raise StopIteration if
340         the handshake operation is completed.
341
342         @rtype: None or an iterable
343         @return: If 'async' is True, a generator object will be
344         returned.
345
346         @raise socket.error: If a socket error occurs.
347         @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
348         without a preceding alert.
349         @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
350         @raise tlslite.errors.TLSAuthenticationError: If the checker
351         doesn't like the other party's authentication credentials.
352         """
353         handshaker = self._handshakeClientAsync(sharedKeyParams=(username,
354                         sharedKey), settings=settings, checker=checker)
355         if async:
356             return handshaker
357         for result in handshaker:
358             pass
359
360     def _handshakeClientAsync(self, srpParams=(), certParams=(),
361                              unknownParams=(), sharedKeyParams=(),
362                              session=None, settings=None, checker=None,
363                              recursive=False):
364
365         handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams,
366                 certParams=certParams, unknownParams=unknownParams,
367                 sharedKeyParams=sharedKeyParams, session=session,
368                 settings=settings, recursive=recursive)
369         for result in self._handshakeWrapperAsync(handshaker, checker):
370             yield result
371
372
373     def _handshakeClientAsyncHelper(self, srpParams, certParams, unknownParams,
374                                sharedKeyParams, session, settings, recursive):
375         if not recursive:
376             self._handshakeStart(client=True)
377
378         #Unpack parameters
379         srpUsername = None      # srpParams
380         password = None         # srpParams
381         clientCertChain = None  # certParams
382         privateKey = None       # certParams
383         srpCallback = None      # unknownParams
384         certCallback = None     # unknownParams
385         #session                # sharedKeyParams (or session)
386         #settings               # settings
387
388         if srpParams:
389             srpUsername, password = srpParams
390         elif certParams:
391             clientCertChain, privateKey = certParams
392         elif unknownParams:
393             srpCallback, certCallback = unknownParams
394         elif sharedKeyParams:
395             session = Session()._createSharedKey(*sharedKeyParams)
396
397         if not settings:
398             settings = HandshakeSettings()
399         settings = settings._filter()
400
401         #Validate parameters
402         if srpUsername and not password:
403             raise ValueError("Caller passed a username but no password")
404         if password and not srpUsername:
405             raise ValueError("Caller passed a password but no username")
406
407         if clientCertChain and not privateKey:
408             raise ValueError("Caller passed a certChain but no privateKey")
409         if privateKey and not clientCertChain:
410             raise ValueError("Caller passed a privateKey but no certChain")
411
412         if clientCertChain:
413             foundType = False
414             try:
415                 import cryptoIDlib.CertChain
416                 if isinstance(clientCertChain, cryptoIDlib.CertChain.CertChain):
417                     if "cryptoID" not in settings.certificateTypes:
418                         raise ValueError("Client certificate doesn't "\
419                                          "match Handshake Settings")
420                     settings.certificateTypes = ["cryptoID"]
421                     foundType = True
422             except ImportError:
423                 pass
424             if not foundType and isinstance(clientCertChain,
425                                             X509CertChain):
426                 if "x509" not in settings.certificateTypes:
427                     raise ValueError("Client certificate doesn't match "\
428                                      "Handshake Settings")
429                 settings.certificateTypes = ["x509"]
430                 foundType = True
431             if not foundType:
432                 raise ValueError("Unrecognized certificate type")
433
434
435         if session:
436             if not session.valid():
437                 session = None #ignore non-resumable sessions...
438             elif session.resumable and \
439                     (session.srpUsername != srpUsername):
440                 raise ValueError("Session username doesn't match")
441
442         #Add Faults to parameters
443         if srpUsername and self.fault == Fault.badUsername:
444             srpUsername += "GARBAGE"
445         if password and self.fault == Fault.badPassword:
446             password += "GARBAGE"
447         if sharedKeyParams:
448             identifier = sharedKeyParams[0]
449             sharedKey = sharedKeyParams[1]
450             if self.fault == Fault.badIdentifier:
451                 identifier += "GARBAGE"
452                 session = Session()._createSharedKey(identifier, sharedKey)
453             elif self.fault == Fault.badSharedKey:
454                 sharedKey += "GARBAGE"
455                 session = Session()._createSharedKey(identifier, sharedKey)
456
457
458         #Initialize locals
459         serverCertChain = None
460         cipherSuite = 0
461         certificateType = CertificateType.x509
462         premasterSecret = None
463
464         #Get client nonce
465         clientRandom = getRandomBytes(32)
466
467         #Initialize acceptable ciphersuites
468         cipherSuites = []
469         if srpParams:
470             cipherSuites += CipherSuite.getSrpRsaSuites(settings.cipherNames)
471             cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
472         elif certParams:
473             cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
474         elif unknownParams:
475             if srpCallback:
476                 cipherSuites += \
477                     CipherSuite.getSrpRsaSuites(settings.cipherNames)
478                 cipherSuites += \
479                     CipherSuite.getSrpSuites(settings.cipherNames)
480             cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
481         elif sharedKeyParams:
482             cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
483         else:
484             cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
485
486         #Initialize acceptable certificate types
487         certificateTypes = settings._getCertificateTypes()
488
489         #Tentatively set the version to the client's minimum version.
490         #We'll use this for the ClientHello, and if an error occurs
491         #parsing the Server Hello, we'll use this version for the response
492         self.version = settings.maxVersion
493
494         #Either send ClientHello (with a resumable session)...
495         if session:
496             #If it's a resumable (i.e. not a shared-key session), then its
497             #ciphersuite must be one of the acceptable ciphersuites
498             if (not sharedKeyParams) and \
499                 session.cipherSuite not in cipherSuites:
500                 raise ValueError("Session's cipher suite not consistent "\
501                                  "with parameters")
502             else:
503                 clientHello = ClientHello()
504                 clientHello.create(settings.maxVersion, clientRandom,
505                                    session.sessionID, cipherSuites,
506                                    certificateTypes, session.srpUsername)
507
508         #Or send ClientHello (without)
509         else:
510             clientHello = ClientHello()
511             clientHello.create(settings.maxVersion, clientRandom,
512                                createByteArraySequence([]), cipherSuites,
513                                certificateTypes, srpUsername)
514         for result in self._sendMsg(clientHello):
515             yield result
516
517         #Get ServerHello (or missing_srp_username)
518         for result in self._getMsg((ContentType.handshake,
519                                   ContentType.alert),
520                                   HandshakeType.server_hello):
521             if result in (0,1):
522                 yield result
523             else:
524                 break
525         msg = result
526
527         if isinstance(msg, ServerHello):
528             serverHello = msg
529         elif isinstance(msg, Alert):
530             alert = msg
531
532             #If it's not a missing_srp_username, re-raise
533             if alert.description != AlertDescription.missing_srp_username:
534                 self._shutdown(False)
535                 raise TLSRemoteAlert(alert)
536
537             #If we're not in SRP callback mode, we won't have offered SRP
538             #without a username, so we shouldn't get this alert
539             if not srpCallback:
540                 for result in self._sendError(\
541                                 AlertDescription.unexpected_message):
542                     yield result
543             srpParams = srpCallback()
544             #If the callback returns None, cancel the handshake
545             if srpParams == None:
546                 for result in self._sendError(AlertDescription.user_canceled):
547                     yield result
548
549             #Recursively perform handshake
550             for result in self._handshakeClientAsyncHelper(srpParams,
551                             None, None, None, None, settings, True):
552                 yield result
553             return
554
555         #Get the server version.  Do this before anything else, so any
556         #error alerts will use the server's version
557         self.version = serverHello.server_version
558
559         #Future responses from server must use this version
560         self._versionCheck = True
561
562         #Check ServerHello
563         if serverHello.server_version < settings.minVersion:
564             for result in self._sendError(\
565                 AlertDescription.protocol_version,
566                 "Too old version: %s" % str(serverHello.server_version)):
567                 yield result
568         if serverHello.server_version > settings.maxVersion:
569             for result in self._sendError(\
570                 AlertDescription.protocol_version,
571                 "Too new version: %s" % str(serverHello.server_version)):
572                 yield result
573         if serverHello.cipher_suite not in cipherSuites:
574             for result in self._sendError(\
575                 AlertDescription.illegal_parameter,
576                 "Server responded with incorrect ciphersuite"):
577                 yield result
578         if serverHello.certificate_type not in certificateTypes:
579             for result in self._sendError(\
580                 AlertDescription.illegal_parameter,
581                 "Server responded with incorrect certificate type"):
582                 yield result
583         if serverHello.compression_method != 0:
584             for result in self._sendError(\
585                 AlertDescription.illegal_parameter,
586                 "Server responded with incorrect compression method"):
587                 yield result
588
589         #Get the server nonce
590         serverRandom = serverHello.random
591
592         #If the server agrees to resume
593         if session and session.sessionID and \
594                        serverHello.session_id == session.sessionID:
595
596             #If a shared-key, we're flexible about suites; otherwise the
597             #server-chosen suite has to match the session's suite
598             if sharedKeyParams:
599                 session.cipherSuite = serverHello.cipher_suite
600             elif serverHello.cipher_suite != session.cipherSuite:
601                 for result in self._sendError(\
602                     AlertDescription.illegal_parameter,\
603                     "Server's ciphersuite doesn't match session"):
604                     yield result
605
606             #Set the session for this connection
607             self.session = session
608
609             #Calculate pending connection states
610             self._calcPendingStates(clientRandom, serverRandom,
611                                    settings.cipherImplementations)
612
613             #Exchange ChangeCipherSpec and Finished messages
614             for result in self._getChangeCipherSpec():
615                 yield result
616             for result in self._getFinished():
617                 yield result
618             for result in self._sendFinished():
619                 yield result
620
621             #Mark the connection as open
622             self._handshakeDone(resumed=True)
623
624         #If server DOES NOT agree to resume
625         else:
626
627             if sharedKeyParams:
628                 for result in self._sendError(\
629                         AlertDescription.user_canceled,
630                         "Was expecting a shared-key resumption"):
631                     yield result
632
633             #We've already validated these
634             cipherSuite = serverHello.cipher_suite
635             certificateType = serverHello.certificate_type
636
637             #If the server chose an SRP suite...
638             if cipherSuite in CipherSuite.srpSuites:
639                 #Get ServerKeyExchange, ServerHelloDone
640                 for result in self._getMsg(ContentType.handshake,
641                         HandshakeType.server_key_exchange, cipherSuite):
642                     if result in (0,1):
643                         yield result
644                     else:
645                         break
646                 serverKeyExchange = result
647
648                 for result in self._getMsg(ContentType.handshake,
649                         HandshakeType.server_hello_done):
650                     if result in (0,1):
651                         yield result
652                     else:
653                         break
654                 serverHelloDone = result
655
656             #If the server chose an SRP+RSA suite...
657             elif cipherSuite in CipherSuite.srpRsaSuites:
658                 #Get Certificate, ServerKeyExchange, ServerHelloDone
659                 for result in self._getMsg(ContentType.handshake,
660                         HandshakeType.certificate, certificateType):
661                     if result in (0,1):
662                         yield result
663                     else:
664                         break
665                 serverCertificate = result
666
667                 for result in self._getMsg(ContentType.handshake,
668                         HandshakeType.server_key_exchange, cipherSuite):
669                     if result in (0,1):
670                         yield result
671                     else:
672                         break
673                 serverKeyExchange = result
674
675                 for result in self._getMsg(ContentType.handshake,
676                         HandshakeType.server_hello_done):
677                     if result in (0,1):
678                         yield result
679                     else:
680                         break
681                 serverHelloDone = result
682
683             #If the server chose an RSA suite...
684             elif cipherSuite in CipherSuite.rsaSuites:
685                 #Get Certificate[, CertificateRequest], ServerHelloDone
686                 for result in self._getMsg(ContentType.handshake,
687                         HandshakeType.certificate, certificateType):
688                     if result in (0,1):
689                         yield result
690                     else:
691                         break
692                 serverCertificate = result
693
694                 for result in self._getMsg(ContentType.handshake,
695                         (HandshakeType.server_hello_done,
696                         HandshakeType.certificate_request)):
697                     if result in (0,1):
698                         yield result
699                     else:
700                         break
701                 msg = result
702
703                 certificateRequest = None
704                 if isinstance(msg, CertificateRequest):
705                     certificateRequest = msg
706                     for result in self._getMsg(ContentType.handshake,
707                             HandshakeType.server_hello_done):
708                         if result in (0,1):
709                             yield result
710                         else:
711                             break
712                     serverHelloDone = result
713                 elif isinstance(msg, ServerHelloDone):
714                     serverHelloDone = msg
715             else:
716                 raise AssertionError()
717
718
719             #Calculate SRP premaster secret, if server chose an SRP or
720             #SRP+RSA suite
721             if cipherSuite in CipherSuite.srpSuites + \
722                               CipherSuite.srpRsaSuites:
723                 #Get and check the server's group parameters and B value
724                 N = serverKeyExchange.srp_N
725                 g = serverKeyExchange.srp_g
726                 s = serverKeyExchange.srp_s
727                 B = serverKeyExchange.srp_B
728
729                 if (g,N) not in goodGroupParameters:
730                     for result in self._sendError(\
731                             AlertDescription.untrusted_srp_parameters,
732                             "Unknown group parameters"):
733                         yield result
734                 if numBits(N) < settings.minKeySize:
735                     for result in self._sendError(\
736                             AlertDescription.untrusted_srp_parameters,
737                             "N value is too small: %d" % numBits(N)):
738                         yield result
739                 if numBits(N) > settings.maxKeySize:
740                     for result in self._sendError(\
741                             AlertDescription.untrusted_srp_parameters,
742                             "N value is too large: %d" % numBits(N)):
743                         yield result
744                 if B % N == 0:
745                     for result in self._sendError(\
746                             AlertDescription.illegal_parameter,
747                             "Suspicious B value"):
748                         yield result
749
750                 #Check the server's signature, if server chose an
751                 #SRP+RSA suite
752                 if cipherSuite in CipherSuite.srpRsaSuites:
753                     #Hash ServerKeyExchange/ServerSRPParams
754                     hashBytes = serverKeyExchange.hash(clientRandom,
755                                                        serverRandom)
756
757                     #Extract signature bytes from ServerKeyExchange
758                     sigBytes = serverKeyExchange.signature
759                     if len(sigBytes) == 0:
760                         for result in self._sendError(\
761                                 AlertDescription.illegal_parameter,
762                                 "Server sent an SRP ServerKeyExchange "\
763                                 "message without a signature"):
764                             yield result
765
766                     #Get server's public key from the Certificate message
767                     for result in self._getKeyFromChain(serverCertificate,
768                                                        settings):
769                         if result in (0,1):
770                             yield result
771                         else:
772                             break
773                     publicKey, serverCertChain = result
774
775                     #Verify signature
776                     if not publicKey.verify(sigBytes, hashBytes):
777                         for result in self._sendError(\
778                                 AlertDescription.decrypt_error,
779                                 "Signature failed to verify"):
780                             yield result
781
782
783                 #Calculate client's ephemeral DH values (a, A)
784                 a = bytesToNumber(getRandomBytes(32))
785                 A = powMod(g, a, N)
786
787                 #Calculate client's static DH values (x, v)
788                 x = makeX(bytesToString(s), srpUsername, password)
789                 v = powMod(g, x, N)
790
791                 #Calculate u
792                 u = makeU(N, A, B)
793
794                 #Calculate premaster secret
795                 k = makeK(N, g)
796                 S = powMod((B - (k*v)) % N, a+(u*x), N)
797
798                 if self.fault == Fault.badA:
799                     A = N
800                     S = 0
801                 premasterSecret = numberToBytes(S)
802
803                 #Send ClientKeyExchange
804                 for result in self._sendMsg(\
805                         ClientKeyExchange(cipherSuite).createSRP(A)):
806                     yield result
807
808
809             #Calculate RSA premaster secret, if server chose an RSA suite
810             elif cipherSuite in CipherSuite.rsaSuites:
811
812                 #Handle the presence of a CertificateRequest
813                 if certificateRequest:
814                     if unknownParams and certCallback:
815                         certParamsNew = certCallback()
816                         if certParamsNew:
817                             clientCertChain, privateKey = certParamsNew
818
819                 #Get server's public key from the Certificate message
820                 for result in self._getKeyFromChain(serverCertificate,
821                                                    settings):
822                     if result in (0,1):
823                         yield result
824                     else:
825                         break
826                 publicKey, serverCertChain = result
827
828
829                 #Calculate premaster secret
830                 premasterSecret = getRandomBytes(48)
831                 premasterSecret[0] = settings.maxVersion[0]
832                 premasterSecret[1] = settings.maxVersion[1]
833
834                 if self.fault == Fault.badPremasterPadding:
835                     premasterSecret[0] = 5
836                 if self.fault == Fault.shortPremasterSecret:
837                     premasterSecret = premasterSecret[:-1]
838
839                 #Encrypt premaster secret to server's public key
840                 encryptedPreMasterSecret = publicKey.encrypt(premasterSecret)
841
842                 #If client authentication was requested, send Certificate
843                 #message, either with certificates or empty
844                 if certificateRequest:
845                     clientCertificate = Certificate(certificateType)
846
847                     if clientCertChain:
848                         #Check to make sure we have the same type of
849                         #certificates the server requested
850                         wrongType = False
851                         if certificateType == CertificateType.x509:
852                             if not isinstance(clientCertChain, X509CertChain):
853                                 wrongType = True
854                         elif certificateType == CertificateType.cryptoID:
855                             if not isinstance(clientCertChain,
856                                               cryptoIDlib.CertChain.CertChain):
857                                 wrongType = True
858                         if wrongType:
859                             for result in self._sendError(\
860                                     AlertDescription.handshake_failure,
861                                     "Client certificate is of wrong type"):
862                                 yield result
863
864                         clientCertificate.create(clientCertChain)
865
866                     for result in self._sendMsg(clientCertificate):
867                         yield result
868                 else:
869                     #The server didn't request client auth, so we
870                     #zeroize these so the clientCertChain won't be
871                     #stored in the session.
872                     privateKey = None
873                     clientCertChain = None
874
875                 #Send ClientKeyExchange
876                 clientKeyExchange = ClientKeyExchange(cipherSuite,
877                                                       self.version)
878                 clientKeyExchange.createRSA(encryptedPreMasterSecret)
879                 for result in self._sendMsg(clientKeyExchange):
880                     yield result
881
882                 #If client authentication was requested and we have a
883                 #private key, send CertificateVerify
884                 if certificateRequest and privateKey:
885                     if self.version == (3,0):
886                         #Create a temporary session object, just for the
887                         #purpose of creating the CertificateVerify
888                         session = Session()
889                         session._calcMasterSecret(self.version,
890                                                  premasterSecret,
891                                                  clientRandom,
892                                                  serverRandom)
893                         verifyBytes = self._calcSSLHandshakeHash(\
894                                           session.masterSecret, "")
895                     elif self.version in ((3,1), (3,2)):
896                         verifyBytes = stringToBytes(\
897                             self._handshake_md5.digest() + \
898                             self._handshake_sha.digest())
899                     if self.fault == Fault.badVerifyMessage:
900                         verifyBytes[0] = ((verifyBytes[0]+1) % 256)
901                     signedBytes = privateKey.sign(verifyBytes)
902                     certificateVerify = CertificateVerify()
903                     certificateVerify.create(signedBytes)
904                     for result in self._sendMsg(certificateVerify):
905                         yield result
906
907
908             #Create the session object
909             self.session = Session()
910             self.session._calcMasterSecret(self.version, premasterSecret,
911                                           clientRandom, serverRandom)
912             self.session.sessionID = serverHello.session_id
913             self.session.cipherSuite = cipherSuite
914             self.session.srpUsername = srpUsername
915             self.session.clientCertChain = clientCertChain
916             self.session.serverCertChain = serverCertChain
917
918             #Calculate pending connection states
919             self._calcPendingStates(clientRandom, serverRandom,
920                                    settings.cipherImplementations)
921
922             #Exchange ChangeCipherSpec and Finished messages
923             for result in self._sendFinished():
924                 yield result
925             for result in self._getChangeCipherSpec():
926                 yield result
927             for result in self._getFinished():
928                 yield result
929
930             #Mark the connection as open
931             self.session._setResumable(True)
932             self._handshakeDone(resumed=False)
933
934
935
936     def handshakeServer(self, sharedKeyDB=None, verifierDB=None,
937                         certChain=None, privateKey=None, reqCert=False,
938                         sessionCache=None, settings=None, checker=None,
939                         reqCAs=None, tlsIntolerant=0):
940         """Perform a handshake in the role of server.
941
942         This function performs an SSL or TLS handshake.  Depending on
943         the arguments and the behavior of the client, this function can
944         perform a shared-key, SRP, or certificate-based handshake.  It
945         can also perform a combined SRP and server-certificate
946         handshake.
947
948         Like any handshake function, this can be called on a closed
949         TLS connection, or on a TLS connection that is already open.
950         If called on an open connection it performs a re-handshake.
951         This function does not send a Hello Request message before
952         performing the handshake, so if re-handshaking is required,
953         the server must signal the client to begin the re-handshake
954         through some other means.
955
956         If the function completes without raising an exception, the
957         TLS connection will be open and available for data transfer.
958
959         If an exception is raised, the connection will have been
960         automatically closed (if it was ever open).
961
962         @type sharedKeyDB: L{tlslite.SharedKeyDB.SharedKeyDB}
963         @param sharedKeyDB: A database of shared symmetric keys
964         associated with usernames.  If the client performs a
965         shared-key handshake, the session's sharedKeyUsername
966         attribute will be set.
967
968         @type verifierDB: L{tlslite.VerifierDB.VerifierDB}
969         @param verifierDB: A database of SRP password verifiers
970         associated with usernames.  If the client performs an SRP
971         handshake, the session's srpUsername attribute will be set.
972
973         @type certChain: L{tlslite.X509CertChain.X509CertChain} or
974         L{cryptoIDlib.CertChain.CertChain}
975         @param certChain: The certificate chain to be used if the
976         client requests server certificate authentication.
977
978         @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
979         @param privateKey: The private key to be used if the client
980         requests server certificate authentication.
981
982         @type reqCert: bool
983         @param reqCert: Whether to request client certificate
984         authentication.  This only applies if the client chooses server
985         certificate authentication; if the client chooses SRP or
986         shared-key authentication, this will be ignored.  If the client
987         performs a client certificate authentication, the sessions's
988         clientCertChain attribute will be set.
989
990         @type sessionCache: L{tlslite.SessionCache.SessionCache}
991         @param sessionCache: An in-memory cache of resumable sessions.
992         The client can resume sessions from this cache.  Alternatively,
993         if the client performs a full handshake, a new session will be
994         added to the cache.
995
996         @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
997         @param settings: Various settings which can be used to control
998         the ciphersuites and SSL/TLS version chosen by the server.
999
1000         @type checker: L{tlslite.Checker.Checker}
1001         @param checker: A Checker instance.  This instance will be
1002         invoked to examine the other party's authentication
1003         credentials, if the handshake completes succesfully.
1004
1005         @type reqCAs: list of L{array.array} of unsigned bytes
1006         @param reqCAs: A collection of DER-encoded DistinguishedNames that
1007         will be sent along with a certificate request. This does not affect
1008         verification.
1009
1010         @raise socket.error: If a socket error occurs.
1011         @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
1012         without a preceding alert.
1013         @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
1014         @raise tlslite.errors.TLSAuthenticationError: If the checker
1015         doesn't like the other party's authentication credentials.
1016         """
1017         for result in self.handshakeServerAsync(sharedKeyDB, verifierDB,
1018                 certChain, privateKey, reqCert, sessionCache, settings,
1019                 checker, reqCAs, tlsIntolerant):
1020             pass
1021
1022
1023     def handshakeServerAsync(self, sharedKeyDB=None, verifierDB=None,
1024                              certChain=None, privateKey=None, reqCert=False,
1025                              sessionCache=None, settings=None, checker=None,
1026                              reqCAs=None, tlsIntolerant=0):
1027         """Start a server handshake operation on the TLS connection.
1028
1029         This function returns a generator which behaves similarly to
1030         handshakeServer().  Successive invocations of the generator
1031         will return 0 if it is waiting to read from the socket, 1 if it is
1032         waiting to write to the socket, or it will raise StopIteration
1033         if the handshake operation is complete.
1034
1035         @rtype: iterable
1036         @return: A generator; see above for details.
1037         """
1038         handshaker = self._handshakeServerAsyncHelper(\
1039             sharedKeyDB=sharedKeyDB,
1040             verifierDB=verifierDB, certChain=certChain,
1041             privateKey=privateKey, reqCert=reqCert,
1042             sessionCache=sessionCache, settings=settings,
1043             reqCAs=reqCAs,
1044             tlsIntolerant=tlsIntolerant)
1045         for result in self._handshakeWrapperAsync(handshaker, checker):
1046             yield result
1047
1048
1049     def _handshakeServerAsyncHelper(self, sharedKeyDB, verifierDB,
1050                              certChain, privateKey, reqCert, sessionCache,
1051                              settings, reqCAs, tlsIntolerant):
1052
1053         self._handshakeStart(client=False)
1054
1055         if (not sharedKeyDB) and (not verifierDB) and (not certChain):
1056             raise ValueError("Caller passed no authentication credentials")
1057         if certChain and not privateKey:
1058             raise ValueError("Caller passed a certChain but no privateKey")
1059         if privateKey and not certChain:
1060             raise ValueError("Caller passed a privateKey but no certChain")
1061         if reqCAs and not reqCert:
1062             raise ValueError("Caller passed reqCAs but not reqCert")
1063
1064         if not settings:
1065             settings = HandshakeSettings()
1066         settings = settings._filter()
1067
1068         #Initialize acceptable cipher suites
1069         cipherSuites = []
1070         if verifierDB:
1071             if certChain:
1072                 cipherSuites += \
1073                     CipherSuite.getSrpRsaSuites(settings.cipherNames)
1074             cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
1075         if sharedKeyDB or certChain:
1076             cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
1077
1078         #Initialize acceptable certificate type
1079         certificateType = None
1080         if certChain:
1081             try:
1082                 import cryptoIDlib.CertChain
1083                 if isinstance(certChain, cryptoIDlib.CertChain.CertChain):
1084                     certificateType = CertificateType.cryptoID
1085             except ImportError:
1086                 pass
1087             if isinstance(certChain, X509CertChain):
1088                 certificateType = CertificateType.x509
1089             if certificateType == None:
1090                 raise ValueError("Unrecognized certificate type")
1091
1092         #Initialize locals
1093         clientCertChain = None
1094         serverCertChain = None #We may set certChain to this later
1095         postFinishedError = None
1096         doingChannelID = False
1097
1098         #Tentatively set version to most-desirable version, so if an error
1099         #occurs parsing the ClientHello, this is what we'll use for the
1100         #error alert
1101         self.version = settings.maxVersion
1102
1103         #Get ClientHello
1104         for result in self._getMsg(ContentType.handshake,
1105                                    HandshakeType.client_hello):
1106             if result in (0,1):
1107                 yield result
1108             else:
1109                 break
1110         clientHello = result
1111
1112         #If client's version is too low, reject it
1113         if clientHello.client_version < settings.minVersion:
1114             self.version = settings.minVersion
1115             for result in self._sendError(\
1116                   AlertDescription.protocol_version,
1117                   "Too old version: %s" % str(clientHello.client_version)):
1118                 yield result
1119
1120         #If tlsIntolerant is nonzero, reject certain TLS versions.
1121         #1: reject all TLS versions.
1122         #2: reject TLS 1.1 or higher.
1123         #3: reject TLS 1.2 or higher.
1124         if (tlsIntolerant == 1 and clientHello.client_version > (3, 0) or
1125             tlsIntolerant == 2 and clientHello.client_version > (3, 1) or
1126             tlsIntolerant == 3 and clientHello.client_version > (3, 2)):
1127             for result in self._sendError(\
1128                     AlertDescription.handshake_failure):
1129                 yield result
1130
1131         #If client's version is too high, propose my highest version
1132         elif clientHello.client_version > settings.maxVersion:
1133             self.version = settings.maxVersion
1134
1135         else:
1136             #Set the version to the client's version
1137             self.version = clientHello.client_version
1138
1139         #Get the client nonce; create server nonce
1140         clientRandom = clientHello.random
1141         serverRandom = getRandomBytes(32)
1142
1143         #Calculate the first cipher suite intersection.
1144         #This is the 'privileged' ciphersuite.  We'll use it if we're
1145         #doing a shared-key resumption or a new negotiation.  In fact,
1146         #the only time we won't use it is if we're resuming a non-sharedkey
1147         #session, in which case we use the ciphersuite from the session.
1148         #
1149         #Given the current ciphersuite ordering, this means we prefer SRP
1150         #over non-SRP.
1151         for cipherSuite in cipherSuites:
1152             if cipherSuite in clientHello.cipher_suites:
1153                 break
1154         else:
1155             for result in self._sendError(\
1156                     AlertDescription.handshake_failure):
1157                 yield result
1158
1159         #If resumption was requested...
1160         if clientHello.session_id and (sharedKeyDB or sessionCache):
1161             session = None
1162
1163             #Check in the sharedKeys container
1164             if sharedKeyDB and len(clientHello.session_id)==16:
1165                 try:
1166                     #Trim off zero padding, if any
1167                     for x in range(16):
1168                         if clientHello.session_id[x]==0:
1169                             break
1170                     self.allegedSharedKeyUsername = bytesToString(\
1171                                             clientHello.session_id[:x])
1172                     session = sharedKeyDB[self.allegedSharedKeyUsername]
1173                     if not session.sharedKey:
1174                         raise AssertionError()
1175                     #use privileged ciphersuite
1176                     session.cipherSuite = cipherSuite
1177                 except KeyError:
1178                     pass
1179
1180             #Then check in the session cache
1181             if sessionCache and not session:
1182                 try:
1183                     session = sessionCache[bytesToString(\
1184                                                clientHello.session_id)]
1185                     if session.sharedKey:
1186                         raise AssertionError()
1187                     if not session.resumable:
1188                         raise AssertionError()
1189                     #Check for consistency with ClientHello
1190                     if session.cipherSuite not in cipherSuites:
1191                         for result in self._sendError(\
1192                                 AlertDescription.handshake_failure):
1193                             yield result
1194                     if session.cipherSuite not in clientHello.cipher_suites:
1195                         for result in self._sendError(\
1196                                 AlertDescription.handshake_failure):
1197                             yield result
1198                     if clientHello.srp_username:
1199                         if clientHello.srp_username != session.srpUsername:
1200                             for result in self._sendError(\
1201                                     AlertDescription.handshake_failure):
1202                                 yield result
1203                 except KeyError:
1204                     pass
1205
1206             #If a session is found..
1207             if session:
1208                 #Set the session
1209                 self.session = session
1210
1211                 #Send ServerHello
1212                 serverHello = ServerHello()
1213                 serverHello.create(self.version, serverRandom,
1214                                    session.sessionID, session.cipherSuite,
1215                                    certificateType)
1216                 serverHello.channel_id = clientHello.channel_id
1217                 doingChannelID = clientHello.channel_id
1218                 for result in self._sendMsg(serverHello):
1219                     yield result
1220
1221                 #From here on, the client's messages must have the right version
1222                 self._versionCheck = True
1223
1224                 #Calculate pending connection states
1225                 self._calcPendingStates(clientRandom, serverRandom,
1226                                        settings.cipherImplementations)
1227
1228                 #Exchange ChangeCipherSpec and Finished messages
1229                 for result in self._sendFinished():
1230                     yield result
1231                 for result in self._getChangeCipherSpec():
1232                     yield result
1233                 if doingChannelID:
1234                     for result in self._getEncryptedExtensions():
1235                         yield result
1236                 for result in self._getFinished():
1237                     yield result
1238
1239                 #Mark the connection as open
1240                 self._handshakeDone(resumed=True)
1241                 return
1242
1243
1244         #If not a resumption...
1245
1246         #TRICKY: we might have chosen an RSA suite that was only deemed
1247         #acceptable because of the shared-key resumption.  If the shared-
1248         #key resumption failed, because the identifier wasn't recognized,
1249         #we might fall through to here, where we have an RSA suite
1250         #chosen, but no certificate.
1251         if cipherSuite in CipherSuite.rsaSuites and not certChain:
1252             for result in self._sendError(\
1253                     AlertDescription.handshake_failure):
1254                 yield result
1255
1256         #If an RSA suite is chosen, check for certificate type intersection
1257         #(We do this check down here because if the mismatch occurs but the
1258         # client is using a shared-key session, it's okay)
1259         if cipherSuite in CipherSuite.rsaSuites + \
1260                           CipherSuite.srpRsaSuites:
1261             if certificateType not in clientHello.certificate_types:
1262                 for result in self._sendError(\
1263                         AlertDescription.handshake_failure,
1264                         "the client doesn't support my certificate type"):
1265                     yield result
1266
1267             #Move certChain -> serverCertChain, now that we're using it
1268             serverCertChain = certChain
1269
1270
1271         #Create sessionID
1272         if sessionCache:
1273             sessionID = getRandomBytes(32)
1274         else:
1275             sessionID = createByteArraySequence([])
1276
1277         #If we've selected an SRP suite, exchange keys and calculate
1278         #premaster secret:
1279         if cipherSuite in CipherSuite.srpSuites + CipherSuite.srpRsaSuites:
1280
1281             #If there's no SRP username...
1282             if not clientHello.srp_username:
1283
1284                 #Ask the client to re-send ClientHello with one
1285                 for result in self._sendMsg(Alert().create(\
1286                         AlertDescription.missing_srp_username,
1287                         AlertLevel.warning)):
1288                     yield result
1289
1290                 #Get ClientHello
1291                 for result in self._getMsg(ContentType.handshake,
1292                         HandshakeType.client_hello):
1293                     if result in (0,1):
1294                         yield result
1295                     else:
1296                         break
1297                 clientHello = result
1298
1299                 #Check ClientHello
1300                 #If client's version is too low, reject it (COPIED CODE; BAD!)
1301                 if clientHello.client_version < settings.minVersion:
1302                     self.version = settings.minVersion
1303                     for result in self._sendError(\
1304                           AlertDescription.protocol_version,
1305                           "Too old version: %s" % str(clientHello.client_version)):
1306                         yield result
1307
1308                 #If client's version is too high, propose my highest version
1309                 elif clientHello.client_version > settings.maxVersion:
1310                     self.version = settings.maxVersion
1311
1312                 else:
1313                     #Set the version to the client's version
1314                     self.version = clientHello.client_version
1315
1316                 #Recalculate the privileged cipher suite, making sure to
1317                 #pick an SRP suite
1318                 cipherSuites = [c for c in cipherSuites if c in \
1319                                 CipherSuite.srpSuites + \
1320                                 CipherSuite.srpRsaSuites]
1321                 for cipherSuite in cipherSuites:
1322                     if cipherSuite in clientHello.cipher_suites:
1323                         break
1324                 else:
1325                     for result in self._sendError(\
1326                             AlertDescription.handshake_failure):
1327                         yield result
1328
1329                 #Get the client nonce; create server nonce
1330                 clientRandom = clientHello.random
1331                 serverRandom = getRandomBytes(32)
1332
1333                 #The username better be there, this time
1334                 if not clientHello.srp_username:
1335                     for result in self._sendError(\
1336                             AlertDescription.illegal_parameter,
1337                             "Client resent a hello, but without the SRP"\
1338                             " username"):
1339                         yield result
1340
1341
1342             #Get username
1343             self.allegedSrpUsername = clientHello.srp_username
1344
1345             #Get parameters from username
1346             try:
1347                 entry = verifierDB[self.allegedSrpUsername]
1348             except KeyError:
1349                 for result in self._sendError(\
1350                         AlertDescription.unknown_srp_username):
1351                     yield result
1352             (N, g, s, v) = entry
1353
1354             #Calculate server's ephemeral DH values (b, B)
1355             b = bytesToNumber(getRandomBytes(32))
1356             k = makeK(N, g)
1357             B = (powMod(g, b, N) + (k*v)) % N
1358
1359             #Create ServerKeyExchange, signing it if necessary
1360             serverKeyExchange = ServerKeyExchange(cipherSuite)
1361             serverKeyExchange.createSRP(N, g, stringToBytes(s), B)
1362             if cipherSuite in CipherSuite.srpRsaSuites:
1363                 hashBytes = serverKeyExchange.hash(clientRandom,
1364                                                    serverRandom)
1365                 serverKeyExchange.signature = privateKey.sign(hashBytes)
1366
1367             #Send ServerHello[, Certificate], ServerKeyExchange,
1368             #ServerHelloDone
1369             msgs = []
1370             serverHello = ServerHello()
1371             serverHello.create(self.version, serverRandom, sessionID,
1372                                cipherSuite, certificateType)
1373             msgs.append(serverHello)
1374             if cipherSuite in CipherSuite.srpRsaSuites:
1375                 certificateMsg = Certificate(certificateType)
1376                 certificateMsg.create(serverCertChain)
1377                 msgs.append(certificateMsg)
1378             msgs.append(serverKeyExchange)
1379             msgs.append(ServerHelloDone())
1380             for result in self._sendMsgs(msgs):
1381                 yield result
1382
1383             #From here on, the client's messages must have the right version
1384             self._versionCheck = True
1385
1386             #Get and check ClientKeyExchange
1387             for result in self._getMsg(ContentType.handshake,
1388                                       HandshakeType.client_key_exchange,
1389                                       cipherSuite):
1390                 if result in (0,1):
1391                     yield result
1392                 else:
1393                     break
1394             clientKeyExchange = result
1395             A = clientKeyExchange.srp_A
1396             if A % N == 0:
1397                 postFinishedError = (AlertDescription.illegal_parameter,
1398                                      "Suspicious A value")
1399             #Calculate u
1400             u = makeU(N, A, B)
1401
1402             #Calculate premaster secret
1403             S = powMod((A * powMod(v,u,N)) % N, b, N)
1404             premasterSecret = numberToBytes(S)
1405
1406
1407         #If we've selected an RSA suite, exchange keys and calculate
1408         #premaster secret:
1409         elif cipherSuite in CipherSuite.rsaSuites:
1410
1411             #Send ServerHello, Certificate[, CertificateRequest],
1412             #ServerHelloDone
1413             msgs = []
1414             serverHello = ServerHello().create(
1415                     self.version, serverRandom,
1416                     sessionID, cipherSuite, certificateType)
1417             serverHello.channel_id = clientHello.channel_id
1418             doingChannelID = clientHello.channel_id
1419             msgs.append(serverHello)
1420             msgs.append(Certificate(certificateType).create(serverCertChain))
1421             if reqCert and reqCAs:
1422                 msgs.append(CertificateRequest().create([], reqCAs))
1423             elif reqCert:
1424                 msgs.append(CertificateRequest())
1425             msgs.append(ServerHelloDone())
1426             for result in self._sendMsgs(msgs):
1427                 yield result
1428
1429             #From here on, the client's messages must have the right version
1430             self._versionCheck = True
1431
1432             #Get [Certificate,] (if was requested)
1433             if reqCert:
1434                 if self.version == (3,0):
1435                     for result in self._getMsg((ContentType.handshake,
1436                                                ContentType.alert),
1437                                                HandshakeType.certificate,
1438                                                certificateType):
1439                         if result in (0,1):
1440                             yield result
1441                         else:
1442                             break
1443                     msg = result
1444
1445                     if isinstance(msg, Alert):
1446                         #If it's not a no_certificate alert, re-raise
1447                         alert = msg
1448                         if alert.description != \
1449                                 AlertDescription.no_certificate:
1450                             self._shutdown(False)
1451                             raise TLSRemoteAlert(alert)
1452                     elif isinstance(msg, Certificate):
1453                         clientCertificate = msg
1454                         if clientCertificate.certChain and \
1455                                 clientCertificate.certChain.getNumCerts()!=0:
1456                             clientCertChain = clientCertificate.certChain
1457                     else:
1458                         raise AssertionError()
1459                 elif self.version in ((3,1), (3,2)):
1460                     for result in self._getMsg(ContentType.handshake,
1461                                               HandshakeType.certificate,
1462                                               certificateType):
1463                         if result in (0,1):
1464                             yield result
1465                         else:
1466                             break
1467                     clientCertificate = result
1468                     if clientCertificate.certChain and \
1469                             clientCertificate.certChain.getNumCerts()!=0:
1470                         clientCertChain = clientCertificate.certChain
1471                 else:
1472                     raise AssertionError()
1473
1474             #Get ClientKeyExchange
1475             for result in self._getMsg(ContentType.handshake,
1476                                       HandshakeType.client_key_exchange,
1477                                       cipherSuite):
1478                 if result in (0,1):
1479                     yield result
1480                 else:
1481                     break
1482             clientKeyExchange = result
1483
1484             #Decrypt ClientKeyExchange
1485             premasterSecret = privateKey.decrypt(\
1486                 clientKeyExchange.encryptedPreMasterSecret)
1487
1488             randomPreMasterSecret = getRandomBytes(48)
1489             versionCheck = (premasterSecret[0], premasterSecret[1])
1490             if not premasterSecret:
1491                 premasterSecret = randomPreMasterSecret
1492             elif len(premasterSecret)!=48:
1493                 premasterSecret = randomPreMasterSecret
1494             elif versionCheck != clientHello.client_version:
1495                 if versionCheck != self.version: #Tolerate buggy IE clients
1496                     premasterSecret = randomPreMasterSecret
1497
1498             #Get and check CertificateVerify, if relevant
1499             if clientCertChain:
1500                 if self.version == (3,0):
1501                     #Create a temporary session object, just for the purpose
1502                     #of checking the CertificateVerify
1503                     session = Session()
1504                     session._calcMasterSecret(self.version, premasterSecret,
1505                                              clientRandom, serverRandom)
1506                     verifyBytes = self._calcSSLHandshakeHash(\
1507                                     session.masterSecret, "")
1508                 elif self.version in ((3,1), (3,2)):
1509                     verifyBytes = stringToBytes(self._handshake_md5.digest() +\
1510                                                 self._handshake_sha.digest())
1511                 for result in self._getMsg(ContentType.handshake,
1512                                           HandshakeType.certificate_verify):
1513                     if result in (0,1):
1514                         yield result
1515                     else:
1516                         break
1517                 certificateVerify = result
1518                 publicKey = clientCertChain.getEndEntityPublicKey()
1519                 if len(publicKey) < settings.minKeySize:
1520                     postFinishedError = (AlertDescription.handshake_failure,
1521                         "Client's public key too small: %d" % len(publicKey))
1522                 if len(publicKey) > settings.maxKeySize:
1523                     postFinishedError = (AlertDescription.handshake_failure,
1524                         "Client's public key too large: %d" % len(publicKey))
1525
1526                 if not publicKey.verify(certificateVerify.signature,
1527                                         verifyBytes):
1528                     postFinishedError = (AlertDescription.decrypt_error,
1529                                          "Signature failed to verify")
1530
1531
1532         #Create the session object
1533         self.session = Session()
1534         self.session._calcMasterSecret(self.version, premasterSecret,
1535                                       clientRandom, serverRandom)
1536         self.session.sessionID = sessionID
1537         self.session.cipherSuite = cipherSuite
1538         self.session.srpUsername = self.allegedSrpUsername
1539         self.session.clientCertChain = clientCertChain
1540         self.session.serverCertChain = serverCertChain
1541
1542         #Calculate pending connection states
1543         self._calcPendingStates(clientRandom, serverRandom,
1544                                settings.cipherImplementations)
1545
1546         #Exchange ChangeCipherSpec and Finished messages
1547         for result in self._getChangeCipherSpec():
1548             yield result
1549         if doingChannelID:
1550             for result in self._getEncryptedExtensions():
1551                 yield result
1552         for result in self._getFinished():
1553             yield result
1554
1555         #If we were holding a post-finished error until receiving the client
1556         #finished message, send it now.  We delay the call until this point
1557         #because calling sendError() throws an exception, and our caller might
1558         #shut down the socket upon receiving the exception.  If he did, and the
1559         #client was still sending its ChangeCipherSpec or Finished messages, it
1560         #would cause a socket error on the client side.  This is a lot of
1561         #consideration to show to misbehaving clients, but this would also
1562         #cause problems with fault-testing.
1563         if postFinishedError:
1564             for result in self._sendError(*postFinishedError):
1565                 yield result
1566
1567         for result in self._sendFinished():
1568             yield result
1569
1570         #Add the session object to the session cache
1571         if sessionCache and sessionID:
1572             sessionCache[bytesToString(sessionID)] = self.session
1573
1574         #Mark the connection as open
1575         self.session._setResumable(True)
1576         self._handshakeDone(resumed=False)
1577
1578
1579     def _handshakeWrapperAsync(self, handshaker, checker):
1580         if not self.fault:
1581             try:
1582                 for result in handshaker:
1583                     yield result
1584                 if checker:
1585                     try:
1586                         checker(self)
1587                     except TLSAuthenticationError:
1588                         alert = Alert().create(AlertDescription.close_notify,
1589                                                AlertLevel.fatal)
1590                         for result in self._sendMsg(alert):
1591                             yield result
1592                         raise
1593             except:
1594                     self._shutdown(False)
1595                     raise
1596         else:
1597             try:
1598                 for result in handshaker:
1599                     yield result
1600                 if checker:
1601                     try:
1602                         checker(self)
1603                     except TLSAuthenticationError:
1604                         alert = Alert().create(AlertDescription.close_notify,
1605                                                AlertLevel.fatal)
1606                         for result in self._sendMsg(alert):
1607                             yield result
1608                         raise
1609             except socket.error, e:
1610                 raise TLSFaultError("socket error!")
1611             except TLSAbruptCloseError, e:
1612                 raise TLSFaultError("abrupt close error!")
1613             except TLSAlert, alert:
1614                 if alert.description not in Fault.faultAlerts[self.fault]:
1615                     raise TLSFaultError(str(alert))
1616                 else:
1617                     pass
1618             except:
1619                 self._shutdown(False)
1620                 raise
1621             else:
1622                 raise TLSFaultError("No error!")
1623
1624
1625     def _getKeyFromChain(self, certificate, settings):
1626         #Get and check cert chain from the Certificate message
1627         certChain = certificate.certChain
1628         if not certChain or certChain.getNumCerts() == 0:
1629             for result in self._sendError(AlertDescription.illegal_parameter,
1630                     "Other party sent a Certificate message without "\
1631                     "certificates"):
1632                 yield result
1633
1634         #Get and check public key from the cert chain
1635         publicKey = certChain.getEndEntityPublicKey()
1636         if len(publicKey) < settings.minKeySize:
1637             for result in self._sendError(AlertDescription.handshake_failure,
1638                     "Other party's public key too small: %d" % len(publicKey)):
1639                 yield result
1640         if len(publicKey) > settings.maxKeySize:
1641             for result in self._sendError(AlertDescription.handshake_failure,
1642                     "Other party's public key too large: %d" % len(publicKey)):
1643                 yield result
1644
1645         yield publicKey, certChain