• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""
2MAIN CLASS FOR TLS LITE (START HERE!).
3"""
4from __future__ import generators
5
6import socket
7from utils.compat import formatExceptionTrace
8from TLSRecordLayer import TLSRecordLayer
9from Session import Session
10from constants import *
11from utils.cryptomath import getRandomBytes
12from errors import *
13from messages import *
14from mathtls import *
15from HandshakeSettings import HandshakeSettings
16
17
18class 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                        signedCertTimestamps=None, fallbackSCSV=False,
941                        ocspResponse=None):
942        """Perform a handshake in the role of server.
943
944        This function performs an SSL or TLS handshake.  Depending on
945        the arguments and the behavior of the client, this function can
946        perform a shared-key, SRP, or certificate-based handshake.  It
947        can also perform a combined SRP and server-certificate
948        handshake.
949
950        Like any handshake function, this can be called on a closed
951        TLS connection, or on a TLS connection that is already open.
952        If called on an open connection it performs a re-handshake.
953        This function does not send a Hello Request message before
954        performing the handshake, so if re-handshaking is required,
955        the server must signal the client to begin the re-handshake
956        through some other means.
957
958        If the function completes without raising an exception, the
959        TLS connection will be open and available for data transfer.
960
961        If an exception is raised, the connection will have been
962        automatically closed (if it was ever open).
963
964        @type sharedKeyDB: L{tlslite.SharedKeyDB.SharedKeyDB}
965        @param sharedKeyDB: A database of shared symmetric keys
966        associated with usernames.  If the client performs a
967        shared-key handshake, the session's sharedKeyUsername
968        attribute will be set.
969
970        @type verifierDB: L{tlslite.VerifierDB.VerifierDB}
971        @param verifierDB: A database of SRP password verifiers
972        associated with usernames.  If the client performs an SRP
973        handshake, the session's srpUsername attribute will be set.
974
975        @type certChain: L{tlslite.X509CertChain.X509CertChain} or
976        L{cryptoIDlib.CertChain.CertChain}
977        @param certChain: The certificate chain to be used if the
978        client requests server certificate authentication.
979
980        @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
981        @param privateKey: The private key to be used if the client
982        requests server certificate authentication.
983
984        @type reqCert: bool
985        @param reqCert: Whether to request client certificate
986        authentication.  This only applies if the client chooses server
987        certificate authentication; if the client chooses SRP or
988        shared-key authentication, this will be ignored.  If the client
989        performs a client certificate authentication, the sessions's
990        clientCertChain attribute will be set.
991
992        @type sessionCache: L{tlslite.SessionCache.SessionCache}
993        @param sessionCache: An in-memory cache of resumable sessions.
994        The client can resume sessions from this cache.  Alternatively,
995        if the client performs a full handshake, a new session will be
996        added to the cache.
997
998        @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
999        @param settings: Various settings which can be used to control
1000        the ciphersuites and SSL/TLS version chosen by the server.
1001
1002        @type checker: L{tlslite.Checker.Checker}
1003        @param checker: A Checker instance.  This instance will be
1004        invoked to examine the other party's authentication
1005        credentials, if the handshake completes succesfully.
1006
1007        @type reqCAs: list of L{array.array} of unsigned bytes
1008        @param reqCAs: A collection of DER-encoded DistinguishedNames that
1009        will be sent along with a certificate request. This does not affect
1010        verification.
1011
1012        @type signedCertTimestamps: str
1013        @param signedCertTimestamps: A SignedCertificateTimestampList (as a
1014        binary 8-bit string) that will be sent as a TLS extension whenever
1015        the client announces support for the extension.
1016
1017        @type tlsIntolerant: int
1018        @param tlsIntolerant: if non-zero, the server will simulate TLS
1019        version intolerance by returning a fatal, handshake_failure alert.
1020        The versions to which it's intolerant vary depending on the value:
1021        1: reject all TLS versions.
1022        2: reject TLS 1.1 or higher.
1023        3: reject TLS 1.2 or higher.
1024
1025        @type fallbackSCSV: bool
1026        @param fallbackSCSV: if true, the server will implement
1027        TLS_FALLBACK_SCSV and thus reject connections using less than the
1028        server's maximum TLS version that include this cipher suite.
1029
1030        @type ocspResponse: str
1031        @param ocspResponse: An OCSP response (as a binary 8-bit string) that
1032        will be sent stapled in the handshake whenever the client announces
1033        support for the status_request extension.
1034        Note that the response is sent independent of the ClientHello
1035        status_request extension contents, and is thus only meant for testing
1036        environments. Real OCSP stapling is more complicated as it requires
1037        choosing a suitable response based on the ClientHello status_request
1038        extension contents.
1039
1040        @raise socket.error: If a socket error occurs.
1041        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
1042        without a preceding alert.
1043        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
1044        @raise tlslite.errors.TLSAuthenticationError: If the checker
1045        doesn't like the other party's authentication credentials.
1046        """
1047        for result in self.handshakeServerAsync(sharedKeyDB, verifierDB,
1048                certChain, privateKey, reqCert, sessionCache, settings,
1049                checker, reqCAs, tlsIntolerant, signedCertTimestamps,
1050                fallbackSCSV, ocspResponse):
1051            pass
1052
1053
1054    def handshakeServerAsync(self, sharedKeyDB=None, verifierDB=None,
1055                             certChain=None, privateKey=None, reqCert=False,
1056                             sessionCache=None, settings=None, checker=None,
1057                             reqCAs=None, tlsIntolerant=0,
1058                             signedCertTimestamps=None,
1059                             fallbackSCSV=False, ocspResponse=None):
1060        """Start a server handshake operation on the TLS connection.
1061
1062        This function returns a generator which behaves similarly to
1063        handshakeServer().  Successive invocations of the generator
1064        will return 0 if it is waiting to read from the socket, 1 if it is
1065        waiting to write to the socket, or it will raise StopIteration
1066        if the handshake operation is complete.
1067
1068        @rtype: iterable
1069        @return: A generator; see above for details.
1070        """
1071        handshaker = self._handshakeServerAsyncHelper(\
1072            sharedKeyDB=sharedKeyDB,
1073            verifierDB=verifierDB, certChain=certChain,
1074            privateKey=privateKey, reqCert=reqCert,
1075            sessionCache=sessionCache, settings=settings,
1076            reqCAs=reqCAs,
1077            tlsIntolerant=tlsIntolerant,
1078            signedCertTimestamps=signedCertTimestamps,
1079            fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse)
1080
1081        for result in self._handshakeWrapperAsync(handshaker, checker):
1082            yield result
1083
1084
1085    def _handshakeServerAsyncHelper(self, sharedKeyDB, verifierDB,
1086                                    certChain, privateKey, reqCert,
1087                                    sessionCache, settings, reqCAs,
1088                                    tlsIntolerant, signedCertTimestamps,
1089                                    fallbackSCSV, ocspResponse):
1090
1091        self._handshakeStart(client=False)
1092
1093        if (not sharedKeyDB) and (not verifierDB) and (not certChain):
1094            raise ValueError("Caller passed no authentication credentials")
1095        if certChain and not privateKey:
1096            raise ValueError("Caller passed a certChain but no privateKey")
1097        if privateKey and not certChain:
1098            raise ValueError("Caller passed a privateKey but no certChain")
1099        if reqCAs and not reqCert:
1100            raise ValueError("Caller passed reqCAs but not reqCert")
1101        if signedCertTimestamps and not certChain:
1102            raise ValueError("Caller passed signedCertTimestamps but no "
1103                             "certChain")
1104
1105        if not settings:
1106            settings = HandshakeSettings()
1107        settings = settings._filter()
1108
1109        #Initialize acceptable cipher suites
1110        cipherSuites = []
1111        if verifierDB:
1112            if certChain:
1113                cipherSuites += \
1114                    CipherSuite.getSrpRsaSuites(settings.cipherNames)
1115            cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
1116        if sharedKeyDB or certChain:
1117            cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
1118
1119        #Initialize acceptable certificate type
1120        certificateType = None
1121        if certChain:
1122            try:
1123                import cryptoIDlib.CertChain
1124                if isinstance(certChain, cryptoIDlib.CertChain.CertChain):
1125                    certificateType = CertificateType.cryptoID
1126            except ImportError:
1127                pass
1128            if isinstance(certChain, X509CertChain):
1129                certificateType = CertificateType.x509
1130            if certificateType == None:
1131                raise ValueError("Unrecognized certificate type")
1132
1133        #Initialize locals
1134        clientCertChain = None
1135        serverCertChain = None #We may set certChain to this later
1136        postFinishedError = None
1137        doingChannelID = False
1138
1139        #Tentatively set version to most-desirable version, so if an error
1140        #occurs parsing the ClientHello, this is what we'll use for the
1141        #error alert
1142        self.version = settings.maxVersion
1143
1144        #Get ClientHello
1145        for result in self._getMsg(ContentType.handshake,
1146                                   HandshakeType.client_hello):
1147            if result in (0,1):
1148                yield result
1149            else:
1150                break
1151        clientHello = result
1152
1153        #If client's version is too low, reject it
1154        if clientHello.client_version < settings.minVersion:
1155            self.version = settings.minVersion
1156            for result in self._sendError(\
1157                  AlertDescription.protocol_version,
1158                  "Too old version: %s" % str(clientHello.client_version)):
1159                yield result
1160
1161        #If tlsIntolerant is nonzero, reject certain TLS versions.
1162        #1: reject all TLS versions.
1163        #2: reject TLS 1.1 or higher.
1164        #3: reject TLS 1.2 or higher.
1165        if (tlsIntolerant == 1 and clientHello.client_version > (3, 0) or
1166            tlsIntolerant == 2 and clientHello.client_version > (3, 1) or
1167            tlsIntolerant == 3 and clientHello.client_version > (3, 2)):
1168            for result in self._sendError(\
1169                    AlertDescription.handshake_failure):
1170                yield result
1171
1172        #If client's version is too high, propose my highest version
1173        if clientHello.client_version > settings.maxVersion:
1174            self.version = settings.maxVersion
1175        else:
1176            #Set the version to the client's version
1177            self.version = clientHello.client_version
1178            if (fallbackSCSV and
1179                clientHello.client_version < settings.maxVersion):
1180                for cipherSuite in clientHello.cipher_suites:
1181                    if cipherSuite == 0x5600:
1182                        for result in self._sendError(\
1183                                AlertDescription.inappropriate_fallback):
1184                            yield result
1185
1186        #Get the client nonce; create server nonce
1187        clientRandom = clientHello.random
1188        serverRandom = getRandomBytes(32)
1189
1190        #Calculate the first cipher suite intersection.
1191        #This is the 'privileged' ciphersuite.  We'll use it if we're
1192        #doing a shared-key resumption or a new negotiation.  In fact,
1193        #the only time we won't use it is if we're resuming a non-sharedkey
1194        #session, in which case we use the ciphersuite from the session.
1195        #
1196        #Given the current ciphersuite ordering, this means we prefer SRP
1197        #over non-SRP.
1198        for cipherSuite in cipherSuites:
1199            if cipherSuite in clientHello.cipher_suites:
1200                break
1201        else:
1202            for result in self._sendError(\
1203                    AlertDescription.handshake_failure):
1204                yield result
1205
1206        #If resumption was requested...
1207        if clientHello.session_id and (sharedKeyDB or sessionCache):
1208            session = None
1209
1210            #Check in the sharedKeys container
1211            if sharedKeyDB and len(clientHello.session_id)==16:
1212                try:
1213                    #Trim off zero padding, if any
1214                    for x in range(16):
1215                        if clientHello.session_id[x]==0:
1216                            break
1217                    self.allegedSharedKeyUsername = bytesToString(\
1218                                            clientHello.session_id[:x])
1219                    session = sharedKeyDB[self.allegedSharedKeyUsername]
1220                    if not session.sharedKey:
1221                        raise AssertionError()
1222                    #use privileged ciphersuite
1223                    session.cipherSuite = cipherSuite
1224                except KeyError:
1225                    pass
1226
1227            #Then check in the session cache
1228            if sessionCache and not session:
1229                try:
1230                    session = sessionCache[bytesToString(\
1231                                               clientHello.session_id)]
1232                    if session.sharedKey:
1233                        raise AssertionError()
1234                    if not session.resumable:
1235                        raise AssertionError()
1236                    #Check for consistency with ClientHello
1237                    if session.cipherSuite not in cipherSuites:
1238                        for result in self._sendError(\
1239                                AlertDescription.handshake_failure):
1240                            yield result
1241                    if session.cipherSuite not in clientHello.cipher_suites:
1242                        for result in self._sendError(\
1243                                AlertDescription.handshake_failure):
1244                            yield result
1245                    if clientHello.srp_username:
1246                        if clientHello.srp_username != session.srpUsername:
1247                            for result in self._sendError(\
1248                                    AlertDescription.handshake_failure):
1249                                yield result
1250                except KeyError:
1251                    pass
1252
1253            #If a session is found..
1254            if session:
1255                #Set the session
1256                self.session = session
1257
1258                #Send ServerHello
1259                serverHello = ServerHello()
1260                serverHello.create(self.version, serverRandom,
1261                                   session.sessionID, session.cipherSuite,
1262                                   certificateType)
1263                serverHello.channel_id = clientHello.channel_id
1264                doingChannelID = clientHello.channel_id
1265                for result in self._sendMsg(serverHello):
1266                    yield result
1267
1268                #From here on, the client's messages must have the right version
1269                self._versionCheck = True
1270
1271                #Calculate pending connection states
1272                self._calcPendingStates(clientRandom, serverRandom,
1273                                       settings.cipherImplementations)
1274
1275                #Exchange ChangeCipherSpec and Finished messages
1276                for result in self._sendFinished():
1277                    yield result
1278                for result in self._getChangeCipherSpec():
1279                    yield result
1280                if doingChannelID:
1281                    for result in self._getEncryptedExtensions():
1282                        yield result
1283                for result in self._getFinished():
1284                    yield result
1285
1286                #Mark the connection as open
1287                self._handshakeDone(resumed=True)
1288                return
1289
1290
1291        #If not a resumption...
1292
1293        #TRICKY: we might have chosen an RSA suite that was only deemed
1294        #acceptable because of the shared-key resumption.  If the shared-
1295        #key resumption failed, because the identifier wasn't recognized,
1296        #we might fall through to here, where we have an RSA suite
1297        #chosen, but no certificate.
1298        if cipherSuite in CipherSuite.rsaSuites and not certChain:
1299            for result in self._sendError(\
1300                    AlertDescription.handshake_failure):
1301                yield result
1302
1303        #If an RSA suite is chosen, check for certificate type intersection
1304        #(We do this check down here because if the mismatch occurs but the
1305        # client is using a shared-key session, it's okay)
1306        if cipherSuite in CipherSuite.rsaSuites + \
1307                          CipherSuite.srpRsaSuites:
1308            if certificateType not in clientHello.certificate_types:
1309                for result in self._sendError(\
1310                        AlertDescription.handshake_failure,
1311                        "the client doesn't support my certificate type"):
1312                    yield result
1313
1314            #Move certChain -> serverCertChain, now that we're using it
1315            serverCertChain = certChain
1316
1317
1318        #Create sessionID
1319        if sessionCache:
1320            sessionID = getRandomBytes(32)
1321        else:
1322            sessionID = createByteArraySequence([])
1323
1324        #If we've selected an SRP suite, exchange keys and calculate
1325        #premaster secret:
1326        if cipherSuite in CipherSuite.srpSuites + CipherSuite.srpRsaSuites:
1327
1328            #If there's no SRP username...
1329            if not clientHello.srp_username:
1330
1331                #Ask the client to re-send ClientHello with one
1332                for result in self._sendMsg(Alert().create(\
1333                        AlertDescription.missing_srp_username,
1334                        AlertLevel.warning)):
1335                    yield result
1336
1337                #Get ClientHello
1338                for result in self._getMsg(ContentType.handshake,
1339                        HandshakeType.client_hello):
1340                    if result in (0,1):
1341                        yield result
1342                    else:
1343                        break
1344                clientHello = result
1345
1346                #Check ClientHello
1347                #If client's version is too low, reject it (COPIED CODE; BAD!)
1348                if clientHello.client_version < settings.minVersion:
1349                    self.version = settings.minVersion
1350                    for result in self._sendError(\
1351                          AlertDescription.protocol_version,
1352                          "Too old version: %s" % str(clientHello.client_version)):
1353                        yield result
1354
1355                #If client's version is too high, propose my highest version
1356                elif clientHello.client_version > settings.maxVersion:
1357                    self.version = settings.maxVersion
1358
1359                else:
1360                    #Set the version to the client's version
1361                    self.version = clientHello.client_version
1362
1363                #Recalculate the privileged cipher suite, making sure to
1364                #pick an SRP suite
1365                cipherSuites = [c for c in cipherSuites if c in \
1366                                CipherSuite.srpSuites + \
1367                                CipherSuite.srpRsaSuites]
1368                for cipherSuite in cipherSuites:
1369                    if cipherSuite in clientHello.cipher_suites:
1370                        break
1371                else:
1372                    for result in self._sendError(\
1373                            AlertDescription.handshake_failure):
1374                        yield result
1375
1376                #Get the client nonce; create server nonce
1377                clientRandom = clientHello.random
1378                serverRandom = getRandomBytes(32)
1379
1380                #The username better be there, this time
1381                if not clientHello.srp_username:
1382                    for result in self._sendError(\
1383                            AlertDescription.illegal_parameter,
1384                            "Client resent a hello, but without the SRP"\
1385                            " username"):
1386                        yield result
1387
1388
1389            #Get username
1390            self.allegedSrpUsername = clientHello.srp_username
1391
1392            #Get parameters from username
1393            try:
1394                entry = verifierDB[self.allegedSrpUsername]
1395            except KeyError:
1396                for result in self._sendError(\
1397                        AlertDescription.unknown_srp_username):
1398                    yield result
1399            (N, g, s, v) = entry
1400
1401            #Calculate server's ephemeral DH values (b, B)
1402            b = bytesToNumber(getRandomBytes(32))
1403            k = makeK(N, g)
1404            B = (powMod(g, b, N) + (k*v)) % N
1405
1406            #Create ServerKeyExchange, signing it if necessary
1407            serverKeyExchange = ServerKeyExchange(cipherSuite)
1408            serverKeyExchange.createSRP(N, g, stringToBytes(s), B)
1409            if cipherSuite in CipherSuite.srpRsaSuites:
1410                hashBytes = serverKeyExchange.hash(clientRandom,
1411                                                   serverRandom)
1412                serverKeyExchange.signature = privateKey.sign(hashBytes)
1413
1414            #Send ServerHello[, Certificate], ServerKeyExchange,
1415            #ServerHelloDone
1416            msgs = []
1417            serverHello = ServerHello()
1418            serverHello.create(self.version, serverRandom, sessionID,
1419                               cipherSuite, certificateType)
1420            msgs.append(serverHello)
1421            if cipherSuite in CipherSuite.srpRsaSuites:
1422                certificateMsg = Certificate(certificateType)
1423                certificateMsg.create(serverCertChain)
1424                msgs.append(certificateMsg)
1425            msgs.append(serverKeyExchange)
1426            msgs.append(ServerHelloDone())
1427            for result in self._sendMsgs(msgs):
1428                yield result
1429
1430            #From here on, the client's messages must have the right version
1431            self._versionCheck = True
1432
1433            #Get and check ClientKeyExchange
1434            for result in self._getMsg(ContentType.handshake,
1435                                      HandshakeType.client_key_exchange,
1436                                      cipherSuite):
1437                if result in (0,1):
1438                    yield result
1439                else:
1440                    break
1441            clientKeyExchange = result
1442            A = clientKeyExchange.srp_A
1443            if A % N == 0:
1444                postFinishedError = (AlertDescription.illegal_parameter,
1445                                     "Suspicious A value")
1446            #Calculate u
1447            u = makeU(N, A, B)
1448
1449            #Calculate premaster secret
1450            S = powMod((A * powMod(v,u,N)) % N, b, N)
1451            premasterSecret = numberToBytes(S)
1452
1453
1454        #If we've selected an RSA suite, exchange keys and calculate
1455        #premaster secret:
1456        elif cipherSuite in CipherSuite.rsaSuites:
1457
1458            #Send ServerHello, Certificate[, CertificateRequest],
1459            #ServerHelloDone
1460            msgs = []
1461            serverHello = ServerHello().create(
1462                    self.version, serverRandom,
1463                    sessionID, cipherSuite, certificateType)
1464            serverHello.channel_id = clientHello.channel_id
1465            if clientHello.support_signed_cert_timestamps:
1466              serverHello.signed_cert_timestamps = signedCertTimestamps
1467            serverHello.status_request = (clientHello.status_request and
1468                                          ocspResponse)
1469            doingChannelID = clientHello.channel_id
1470            msgs.append(serverHello)
1471            msgs.append(Certificate(certificateType).create(serverCertChain))
1472            if serverHello.status_request:
1473                msgs.append(CertificateStatus().create(ocspResponse))
1474            if reqCert and reqCAs:
1475                msgs.append(CertificateRequest().create([], reqCAs))
1476            elif reqCert:
1477                msgs.append(CertificateRequest())
1478            msgs.append(ServerHelloDone())
1479            for result in self._sendMsgs(msgs):
1480                yield result
1481
1482            #From here on, the client's messages must have the right version
1483            self._versionCheck = True
1484
1485            #Get [Certificate,] (if was requested)
1486            if reqCert:
1487                if self.version == (3,0):
1488                    for result in self._getMsg((ContentType.handshake,
1489                                               ContentType.alert),
1490                                               HandshakeType.certificate,
1491                                               certificateType):
1492                        if result in (0,1):
1493                            yield result
1494                        else:
1495                            break
1496                    msg = result
1497
1498                    if isinstance(msg, Alert):
1499                        #If it's not a no_certificate alert, re-raise
1500                        alert = msg
1501                        if alert.description != \
1502                                AlertDescription.no_certificate:
1503                            self._shutdown(False)
1504                            raise TLSRemoteAlert(alert)
1505                    elif isinstance(msg, Certificate):
1506                        clientCertificate = msg
1507                        if clientCertificate.certChain and \
1508                                clientCertificate.certChain.getNumCerts()!=0:
1509                            clientCertChain = clientCertificate.certChain
1510                    else:
1511                        raise AssertionError()
1512                elif self.version in ((3,1), (3,2)):
1513                    for result in self._getMsg(ContentType.handshake,
1514                                              HandshakeType.certificate,
1515                                              certificateType):
1516                        if result in (0,1):
1517                            yield result
1518                        else:
1519                            break
1520                    clientCertificate = result
1521                    if clientCertificate.certChain and \
1522                            clientCertificate.certChain.getNumCerts()!=0:
1523                        clientCertChain = clientCertificate.certChain
1524                else:
1525                    raise AssertionError()
1526
1527            #Get ClientKeyExchange
1528            for result in self._getMsg(ContentType.handshake,
1529                                      HandshakeType.client_key_exchange,
1530                                      cipherSuite):
1531                if result in (0,1):
1532                    yield result
1533                else:
1534                    break
1535            clientKeyExchange = result
1536
1537            #Decrypt ClientKeyExchange
1538            premasterSecret = privateKey.decrypt(\
1539                clientKeyExchange.encryptedPreMasterSecret)
1540
1541            randomPreMasterSecret = getRandomBytes(48)
1542            versionCheck = (premasterSecret[0], premasterSecret[1])
1543            if not premasterSecret:
1544                premasterSecret = randomPreMasterSecret
1545            elif len(premasterSecret)!=48:
1546                premasterSecret = randomPreMasterSecret
1547            elif versionCheck != clientHello.client_version:
1548                if versionCheck != self.version: #Tolerate buggy IE clients
1549                    premasterSecret = randomPreMasterSecret
1550
1551            #Get and check CertificateVerify, if relevant
1552            if clientCertChain:
1553                if self.version == (3,0):
1554                    #Create a temporary session object, just for the purpose
1555                    #of checking the CertificateVerify
1556                    session = Session()
1557                    session._calcMasterSecret(self.version, premasterSecret,
1558                                             clientRandom, serverRandom)
1559                    verifyBytes = self._calcSSLHandshakeHash(\
1560                                    session.masterSecret, "")
1561                elif self.version in ((3,1), (3,2)):
1562                    verifyBytes = stringToBytes(self._handshake_md5.digest() +\
1563                                                self._handshake_sha.digest())
1564                for result in self._getMsg(ContentType.handshake,
1565                                          HandshakeType.certificate_verify):
1566                    if result in (0,1):
1567                        yield result
1568                    else:
1569                        break
1570                certificateVerify = result
1571                publicKey = clientCertChain.getEndEntityPublicKey()
1572                if len(publicKey) < settings.minKeySize:
1573                    postFinishedError = (AlertDescription.handshake_failure,
1574                        "Client's public key too small: %d" % len(publicKey))
1575                if len(publicKey) > settings.maxKeySize:
1576                    postFinishedError = (AlertDescription.handshake_failure,
1577                        "Client's public key too large: %d" % len(publicKey))
1578
1579                if not publicKey.verify(certificateVerify.signature,
1580                                        verifyBytes):
1581                    postFinishedError = (AlertDescription.decrypt_error,
1582                                         "Signature failed to verify")
1583
1584
1585        #Create the session object
1586        self.session = Session()
1587        self.session._calcMasterSecret(self.version, premasterSecret,
1588                                      clientRandom, serverRandom)
1589        self.session.sessionID = sessionID
1590        self.session.cipherSuite = cipherSuite
1591        self.session.srpUsername = self.allegedSrpUsername
1592        self.session.clientCertChain = clientCertChain
1593        self.session.serverCertChain = serverCertChain
1594
1595        #Calculate pending connection states
1596        self._calcPendingStates(clientRandom, serverRandom,
1597                               settings.cipherImplementations)
1598
1599        #Exchange ChangeCipherSpec and Finished messages
1600        for result in self._getChangeCipherSpec():
1601            yield result
1602        if doingChannelID:
1603            for result in self._getEncryptedExtensions():
1604                yield result
1605        for result in self._getFinished():
1606            yield result
1607
1608        #If we were holding a post-finished error until receiving the client
1609        #finished message, send it now.  We delay the call until this point
1610        #because calling sendError() throws an exception, and our caller might
1611        #shut down the socket upon receiving the exception.  If he did, and the
1612        #client was still sending its ChangeCipherSpec or Finished messages, it
1613        #would cause a socket error on the client side.  This is a lot of
1614        #consideration to show to misbehaving clients, but this would also
1615        #cause problems with fault-testing.
1616        if postFinishedError:
1617            for result in self._sendError(*postFinishedError):
1618                yield result
1619
1620        for result in self._sendFinished():
1621            yield result
1622
1623        #Add the session object to the session cache
1624        if sessionCache and sessionID:
1625            sessionCache[bytesToString(sessionID)] = self.session
1626
1627        #Mark the connection as open
1628        self.session._setResumable(True)
1629        self._handshakeDone(resumed=False)
1630
1631
1632    def _handshakeWrapperAsync(self, handshaker, checker):
1633        if not self.fault:
1634            try:
1635                for result in handshaker:
1636                    yield result
1637                if checker:
1638                    try:
1639                        checker(self)
1640                    except TLSAuthenticationError:
1641                        alert = Alert().create(AlertDescription.close_notify,
1642                                               AlertLevel.fatal)
1643                        for result in self._sendMsg(alert):
1644                            yield result
1645                        raise
1646            except:
1647                    self._shutdown(False)
1648                    raise
1649        else:
1650            try:
1651                for result in handshaker:
1652                    yield result
1653                if checker:
1654                    try:
1655                        checker(self)
1656                    except TLSAuthenticationError:
1657                        alert = Alert().create(AlertDescription.close_notify,
1658                                               AlertLevel.fatal)
1659                        for result in self._sendMsg(alert):
1660                            yield result
1661                        raise
1662            except socket.error, e:
1663                raise TLSFaultError("socket error!")
1664            except TLSAbruptCloseError, e:
1665                raise TLSFaultError("abrupt close error!")
1666            except TLSAlert, alert:
1667                if alert.description not in Fault.faultAlerts[self.fault]:
1668                    raise TLSFaultError(str(alert))
1669                else:
1670                    pass
1671            except:
1672                self._shutdown(False)
1673                raise
1674            else:
1675                raise TLSFaultError("No error!")
1676
1677
1678    def _getKeyFromChain(self, certificate, settings):
1679        #Get and check cert chain from the Certificate message
1680        certChain = certificate.certChain
1681        if not certChain or certChain.getNumCerts() == 0:
1682            for result in self._sendError(AlertDescription.illegal_parameter,
1683                    "Other party sent a Certificate message without "\
1684                    "certificates"):
1685                yield result
1686
1687        #Get and check public key from the cert chain
1688        publicKey = certChain.getEndEntityPublicKey()
1689        if len(publicKey) < settings.minKeySize:
1690            for result in self._sendError(AlertDescription.handshake_failure,
1691                    "Other party's public key too small: %d" % len(publicKey)):
1692                yield result
1693        if len(publicKey) > settings.maxKeySize:
1694            for result in self._sendError(AlertDescription.handshake_failure,
1695                    "Other party's public key too large: %d" % len(publicKey)):
1696                yield result
1697
1698        yield publicKey, certChain
1699