• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Authors:
2#   Trevor Perrin
3#   Google - added reqCAs parameter
4#   Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support
5#   Dimitris Moraitis - Anon ciphersuites
6#   Martin von Loewis - python 3 port
7#
8# See the LICENSE file for legal information regarding use of this file.
9
10"""
11MAIN CLASS FOR TLS LITE (START HERE!).
12"""
13
14import socket
15from .utils.compat import formatExceptionTrace
16from .tlsrecordlayer import TLSRecordLayer
17from .session import Session
18from .constants import *
19from .utils.cryptomath import getRandomBytes
20from .errors import *
21from .messages import *
22from .mathtls import *
23from .handshakesettings import HandshakeSettings
24from .utils.tackwrapper import *
25
26class KeyExchange(object):
27    def __init__(self, cipherSuite, clientHello, serverHello, privateKey):
28        """
29        Initializes the KeyExchange. privateKey is the signing private key.
30        """
31        self.cipherSuite = cipherSuite
32        self.clientHello = clientHello
33        self.serverHello = serverHello
34        self.privateKey = privateKey
35
36    def makeServerKeyExchange():
37        """
38        Returns a ServerKeyExchange object for the server's initial leg in the
39        handshake. If the key exchange method does not send ServerKeyExchange
40        (e.g. RSA), it returns None.
41        """
42        raise NotImplementedError()
43
44    def processClientKeyExchange(clientKeyExchange):
45        """
46        Processes the client's ClientKeyExchange message and returns the
47        premaster secret. Raises TLSLocalAlert on error.
48        """
49        raise NotImplementedError()
50
51class RSAKeyExchange(KeyExchange):
52    def makeServerKeyExchange(self):
53        return None
54
55    def processClientKeyExchange(self, clientKeyExchange):
56        premasterSecret = self.privateKey.decrypt(\
57            clientKeyExchange.encryptedPreMasterSecret)
58
59        # On decryption failure randomize premaster secret to avoid
60        # Bleichenbacher's "million message" attack
61        randomPreMasterSecret = getRandomBytes(48)
62        if not premasterSecret:
63            premasterSecret = randomPreMasterSecret
64        elif len(premasterSecret)!=48:
65            premasterSecret = randomPreMasterSecret
66        else:
67            versionCheck = (premasterSecret[0], premasterSecret[1])
68            if versionCheck != self.clientHello.client_version:
69                #Tolerate buggy IE clients
70                if versionCheck != self.serverHello.server_version:
71                    premasterSecret = randomPreMasterSecret
72        return premasterSecret
73
74def _hexStringToNumber(s):
75    s = s.replace(" ", "").replace("\n", "")
76    if len(s) % 2 != 0:
77        raise ValueError("Length is not even")
78    return bytesToNumber(bytearray(s.decode("hex")))
79
80class DHE_RSAKeyExchange(KeyExchange):
81    # 2048-bit MODP Group (RFC 3526, Section 3)
82    dh_p = _hexStringToNumber("""
83FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
8429024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
85EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
86E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
87EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
88C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
8983655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
90670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
91E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
92DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
9315728E5A 8AACAA68 FFFFFFFF FFFFFFFF""")
94    dh_g = 2
95
96    # RFC 3526, Section 8.
97    strength = 160
98
99    def makeServerKeyExchange(self):
100        # Per RFC 3526, Section 1, the exponent should have double the entropy
101        # of the strength of the curve.
102        self.dh_Xs = bytesToNumber(getRandomBytes(self.strength * 2 / 8))
103        dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p)
104
105        serverKeyExchange = ServerKeyExchange(self.cipherSuite)
106        serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys)
107        serverKeyExchange.signature = self.privateKey.sign(
108            serverKeyExchange.hash(self.clientHello.random,
109                                   self.serverHello.random))
110        return serverKeyExchange
111
112    def processClientKeyExchange(self, clientKeyExchange):
113        dh_Yc = clientKeyExchange.dh_Yc
114
115        # First half of RFC 2631, Section 2.1.5. Validate the client's public
116        # key.
117        if not 2 <= dh_Yc <= self.dh_p - 1:
118            raise TLSLocalAlert(AlertDescription.illegal_parameter,
119                                "Invalid dh_Yc value")
120
121        S = powMod(dh_Yc, self.dh_Xs, self.dh_p)
122        return numberToByteArray(S)
123
124class TLSConnection(TLSRecordLayer):
125    """
126    This class wraps a socket and provides TLS handshaking and data
127    transfer.
128
129    To use this class, create a new instance, passing a connected
130    socket into the constructor.  Then call some handshake function.
131    If the handshake completes without raising an exception, then a TLS
132    connection has been negotiated.  You can transfer data over this
133    connection as if it were a socket.
134
135    This class provides both synchronous and asynchronous versions of
136    its key functions.  The synchronous versions should be used when
137    writing single-or multi-threaded code using blocking sockets.  The
138    asynchronous versions should be used when performing asynchronous,
139    event-based I/O with non-blocking sockets.
140
141    Asynchronous I/O is a complicated subject; typically, you should
142    not use the asynchronous functions directly, but should use some
143    framework like asyncore or Twisted which TLS Lite integrates with
144    (see
145    L{tlslite.integration.tlsasyncdispatchermixin.TLSAsyncDispatcherMixIn}).
146    """
147
148    def __init__(self, sock):
149        """Create a new TLSConnection instance.
150
151        @param sock: The socket data will be transmitted on.  The
152        socket should already be connected.  It may be in blocking or
153        non-blocking mode.
154
155        @type sock: L{socket.socket}
156        """
157        TLSRecordLayer.__init__(self, sock)
158
159    #*********************************************************
160    # Client Handshake Functions
161    #*********************************************************
162
163    def handshakeClientAnonymous(self, session=None, settings=None,
164                                checker=None, serverName="",
165                                async=False):
166        """Perform an anonymous handshake in the role of client.
167
168        This function performs an SSL or TLS handshake using an
169        anonymous Diffie Hellman ciphersuite.
170
171        Like any handshake function, this can be called on a closed
172        TLS connection, or on a TLS connection that is already open.
173        If called on an open connection it performs a re-handshake.
174
175        If the function completes without raising an exception, the
176        TLS connection will be open and available for data transfer.
177
178        If an exception is raised, the connection will have been
179        automatically closed (if it was ever open).
180
181        @type session: L{tlslite.Session.Session}
182        @param session: A TLS session to attempt to resume.  If the
183        resumption does not succeed, a full handshake will be
184        performed.
185
186        @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
187        @param settings: Various settings which can be used to control
188        the ciphersuites, certificate types, and SSL/TLS versions
189        offered by the client.
190
191        @type checker: L{tlslite.Checker.Checker}
192        @param checker: A Checker instance.  This instance will be
193        invoked to examine the other party's authentication
194        credentials, if the handshake completes succesfully.
195
196        @type serverName: string
197        @param serverName: The ServerNameIndication TLS Extension.
198
199        @type async: bool
200        @param async: If False, this function will block until the
201        handshake is completed.  If True, this function will return a
202        generator.  Successive invocations of the generator will
203        return 0 if it is waiting to read from the socket, 1 if it is
204        waiting to write to the socket, or will raise StopIteration if
205        the handshake operation is completed.
206
207        @rtype: None or an iterable
208        @return: If 'async' is True, a generator object will be
209        returned.
210
211        @raise socket.error: If a socket error occurs.
212        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
213        without a preceding alert.
214        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
215        @raise tlslite.errors.TLSAuthenticationError: If the checker
216        doesn't like the other party's authentication credentials.
217        """
218        handshaker = self._handshakeClientAsync(anonParams=(True),
219                                                session=session,
220                                                settings=settings,
221                                                checker=checker,
222                                                serverName=serverName)
223        if async:
224            return handshaker
225        for result in handshaker:
226            pass
227
228    def handshakeClientSRP(self, username, password, session=None,
229                           settings=None, checker=None,
230                           reqTack=True, serverName="",
231                           async=False):
232        """Perform an SRP handshake in the role of client.
233
234        This function performs a TLS/SRP handshake.  SRP mutually
235        authenticates both parties to each other using only a
236        username and password.  This function may also perform a
237        combined SRP and server-certificate handshake, if the server
238        chooses to authenticate itself with a certificate chain in
239        addition to doing SRP.
240
241        If the function completes without raising an exception, the
242        TLS connection will be open and available for data transfer.
243
244        If an exception is raised, the connection will have been
245        automatically closed (if it was ever open).
246
247        @type username: str
248        @param username: The SRP username.
249
250        @type password: str
251        @param password: The SRP password.
252
253        @type session: L{tlslite.session.Session}
254        @param session: A TLS session to attempt to resume.  This
255        session must be an SRP session performed with the same username
256        and password as were passed in.  If the resumption does not
257        succeed, a full SRP handshake will be performed.
258
259        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
260        @param settings: Various settings which can be used to control
261        the ciphersuites, certificate types, and SSL/TLS versions
262        offered by the client.
263
264        @type checker: L{tlslite.checker.Checker}
265        @param checker: A Checker instance.  This instance will be
266        invoked to examine the other party's authentication
267        credentials, if the handshake completes succesfully.
268
269        @type reqTack: bool
270        @param reqTack: Whether or not to send a "tack" TLS Extension,
271        requesting the server return a TackExtension if it has one.
272
273        @type serverName: string
274        @param serverName: The ServerNameIndication TLS Extension.
275
276        @type async: bool
277        @param async: If False, this function will block until the
278        handshake is completed.  If True, this function will return a
279        generator.  Successive invocations of the generator will
280        return 0 if it is waiting to read from the socket, 1 if it is
281        waiting to write to the socket, or will raise StopIteration if
282        the handshake operation is completed.
283
284        @rtype: None or an iterable
285        @return: If 'async' is True, a generator object will be
286        returned.
287
288        @raise socket.error: If a socket error occurs.
289        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
290        without a preceding alert.
291        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
292        @raise tlslite.errors.TLSAuthenticationError: If the checker
293        doesn't like the other party's authentication credentials.
294        """
295        handshaker = self._handshakeClientAsync(srpParams=(username, password),
296                        session=session, settings=settings, checker=checker,
297                        reqTack=reqTack, serverName=serverName)
298        # The handshaker is a Python Generator which executes the handshake.
299        # It allows the handshake to be run in a "piecewise", asynchronous
300        # fashion, returning 1 when it is waiting to able to write, 0 when
301        # it is waiting to read.
302        #
303        # If 'async' is True, the generator is returned to the caller,
304        # otherwise it is executed to completion here.
305        if async:
306            return handshaker
307        for result in handshaker:
308            pass
309
310    def handshakeClientCert(self, certChain=None, privateKey=None,
311                            session=None, settings=None, checker=None,
312                            nextProtos=None, reqTack=True, serverName="",
313                            async=False):
314        """Perform a certificate-based handshake in the role of client.
315
316        This function performs an SSL or TLS handshake.  The server
317        will authenticate itself using an X.509 certificate
318        chain.  If the handshake succeeds, the server's certificate
319        chain will be stored in the session's serverCertChain attribute.
320        Unless a checker object is passed in, this function does no
321        validation or checking of the server's certificate chain.
322
323        If the server requests client authentication, the
324        client will send the passed-in certificate chain, and use the
325        passed-in private key to authenticate itself.  If no
326        certificate chain and private key were passed in, the client
327        will attempt to proceed without client authentication.  The
328        server may or may not allow this.
329
330        If the function completes without raising an exception, the
331        TLS connection will be open and available for data transfer.
332
333        If an exception is raised, the connection will have been
334        automatically closed (if it was ever open).
335
336        @type certChain: L{tlslite.x509certchain.X509CertChain}
337        @param certChain: The certificate chain to be used if the
338        server requests client authentication.
339
340        @type privateKey: L{tlslite.utils.rsakey.RSAKey}
341        @param privateKey: The private key to be used if the server
342        requests client authentication.
343
344        @type session: L{tlslite.session.Session}
345        @param session: A TLS session to attempt to resume.  If the
346        resumption does not succeed, a full handshake will be
347        performed.
348
349        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
350        @param settings: Various settings which can be used to control
351        the ciphersuites, certificate types, and SSL/TLS versions
352        offered by the client.
353
354        @type checker: L{tlslite.checker.Checker}
355        @param checker: A Checker instance.  This instance will be
356        invoked to examine the other party's authentication
357        credentials, if the handshake completes succesfully.
358
359        @type nextProtos: list of strings.
360        @param nextProtos: A list of upper layer protocols ordered by
361        preference, to use in the Next-Protocol Negotiation Extension.
362
363        @type reqTack: bool
364        @param reqTack: Whether or not to send a "tack" TLS Extension,
365        requesting the server return a TackExtension if it has one.
366
367        @type serverName: string
368        @param serverName: The ServerNameIndication TLS Extension.
369
370        @type async: bool
371        @param async: If False, this function will block until the
372        handshake is completed.  If True, this function will return a
373        generator.  Successive invocations of the generator will
374        return 0 if it is waiting to read from the socket, 1 if it is
375        waiting to write to the socket, or will raise StopIteration if
376        the handshake operation is completed.
377
378        @rtype: None or an iterable
379        @return: If 'async' is True, a generator object will be
380        returned.
381
382        @raise socket.error: If a socket error occurs.
383        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
384        without a preceding alert.
385        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
386        @raise tlslite.errors.TLSAuthenticationError: If the checker
387        doesn't like the other party's authentication credentials.
388        """
389        handshaker = self._handshakeClientAsync(certParams=(certChain,
390                        privateKey), session=session, settings=settings,
391                        checker=checker, serverName=serverName,
392                        nextProtos=nextProtos, reqTack=reqTack)
393        # The handshaker is a Python Generator which executes the handshake.
394        # It allows the handshake to be run in a "piecewise", asynchronous
395        # fashion, returning 1 when it is waiting to able to write, 0 when
396        # it is waiting to read.
397        #
398        # If 'async' is True, the generator is returned to the caller,
399        # otherwise it is executed to completion here.
400        if async:
401            return handshaker
402        for result in handshaker:
403            pass
404
405
406    def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(),
407                             session=None, settings=None, checker=None,
408                             nextProtos=None, serverName="", reqTack=True):
409
410        handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams,
411                certParams=certParams,
412                anonParams=anonParams,
413                session=session,
414                settings=settings,
415                serverName=serverName,
416                nextProtos=nextProtos,
417                reqTack=reqTack)
418        for result in self._handshakeWrapperAsync(handshaker, checker):
419            yield result
420
421
422    def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams,
423                               session, settings, serverName, nextProtos, reqTack):
424
425        self._handshakeStart(client=True)
426
427        #Unpack parameters
428        srpUsername = None      # srpParams[0]
429        password = None         # srpParams[1]
430        clientCertChain = None  # certParams[0]
431        privateKey = None       # certParams[1]
432
433        # Allow only one of (srpParams, certParams, anonParams)
434        if srpParams:
435            assert(not certParams)
436            assert(not anonParams)
437            srpUsername, password = srpParams
438        if certParams:
439            assert(not srpParams)
440            assert(not anonParams)
441            clientCertChain, privateKey = certParams
442        if anonParams:
443            assert(not srpParams)
444            assert(not certParams)
445
446        #Validate parameters
447        if srpUsername and not password:
448            raise ValueError("Caller passed a username but no password")
449        if password and not srpUsername:
450            raise ValueError("Caller passed a password but no username")
451        if clientCertChain and not privateKey:
452            raise ValueError("Caller passed a certChain but no privateKey")
453        if privateKey and not clientCertChain:
454            raise ValueError("Caller passed a privateKey but no certChain")
455        if reqTack:
456            if not tackpyLoaded:
457                reqTack = False
458            if not settings or not settings.useExperimentalTackExtension:
459                reqTack = False
460        if nextProtos is not None:
461            if len(nextProtos) == 0:
462                raise ValueError("Caller passed no nextProtos")
463
464        # Validates the settings and filters out any unsupported ciphers
465        # or crypto libraries that were requested
466        if not settings:
467            settings = HandshakeSettings()
468        settings = settings._filter()
469
470        if clientCertChain:
471            if not isinstance(clientCertChain, X509CertChain):
472                raise ValueError("Unrecognized certificate type")
473            if "x509" not in settings.certificateTypes:
474                raise ValueError("Client certificate doesn't match "\
475                                 "Handshake Settings")
476
477        if session:
478            # session.valid() ensures session is resumable and has
479            # non-empty sessionID
480            if not session.valid():
481                session = None #ignore non-resumable sessions...
482            elif session.resumable:
483                if session.srpUsername != srpUsername:
484                    raise ValueError("Session username doesn't match")
485                if session.serverName != serverName:
486                    raise ValueError("Session servername doesn't match")
487
488        #Add Faults to parameters
489        if srpUsername and self.fault == Fault.badUsername:
490            srpUsername += "GARBAGE"
491        if password and self.fault == Fault.badPassword:
492            password += "GARBAGE"
493
494        #Tentatively set the version to the client's minimum version.
495        #We'll use this for the ClientHello, and if an error occurs
496        #parsing the Server Hello, we'll use this version for the response
497        self.version = settings.maxVersion
498
499        # OK Start sending messages!
500        # *****************************
501
502        # Send the ClientHello.
503        for result in self._clientSendClientHello(settings, session,
504                                        srpUsername, srpParams, certParams,
505                                        anonParams, serverName, nextProtos,
506                                        reqTack):
507            if result in (0,1): yield result
508            else: break
509        clientHello = result
510
511        #Get the ServerHello.
512        for result in self._clientGetServerHello(settings, clientHello):
513            if result in (0,1): yield result
514            else: break
515        serverHello = result
516        cipherSuite = serverHello.cipher_suite
517
518        # Choose a matching Next Protocol from server list against ours
519        # (string or None)
520        nextProto = self._clientSelectNextProto(nextProtos, serverHello)
521
522        #If the server elected to resume the session, it is handled here.
523        for result in self._clientResume(session, serverHello,
524                        clientHello.random,
525                        settings.cipherImplementations,
526                        nextProto):
527            if result in (0,1): yield result
528            else: break
529        if result == "resumed_and_finished":
530            self._handshakeDone(resumed=True)
531            return
532
533        #If the server selected an SRP ciphersuite, the client finishes
534        #reading the post-ServerHello messages, then derives a
535        #premasterSecret and sends a corresponding ClientKeyExchange.
536        if cipherSuite in CipherSuite.srpAllSuites:
537            for result in self._clientSRPKeyExchange(\
538                    settings, cipherSuite, serverHello.certificate_type,
539                    srpUsername, password,
540                    clientHello.random, serverHello.random,
541                    serverHello.tackExt):
542                if result in (0,1): yield result
543                else: break
544            (premasterSecret, serverCertChain, tackExt) = result
545
546        #If the server selected an anonymous ciphersuite, the client
547        #finishes reading the post-ServerHello messages.
548        elif cipherSuite in CipherSuite.anonSuites:
549            for result in self._clientAnonKeyExchange(settings, cipherSuite,
550                                    clientHello.random, serverHello.random):
551                if result in (0,1): yield result
552                else: break
553            (premasterSecret, serverCertChain, tackExt) = result
554
555        #If the server selected a certificate-based RSA ciphersuite,
556        #the client finishes reading the post-ServerHello messages. If
557        #a CertificateRequest message was sent, the client responds with
558        #a Certificate message containing its certificate chain (if any),
559        #and also produces a CertificateVerify message that signs the
560        #ClientKeyExchange.
561        else:
562            for result in self._clientRSAKeyExchange(settings, cipherSuite,
563                                    clientCertChain, privateKey,
564                                    serverHello.certificate_type,
565                                    clientHello.random, serverHello.random,
566                                    serverHello.tackExt):
567                if result in (0,1): yield result
568                else: break
569            (premasterSecret, serverCertChain, clientCertChain,
570             tackExt) = result
571
572        #After having previously sent a ClientKeyExchange, the client now
573        #initiates an exchange of Finished messages.
574        for result in self._clientFinished(premasterSecret,
575                            clientHello.random,
576                            serverHello.random,
577                            cipherSuite, settings.cipherImplementations,
578                            nextProto):
579                if result in (0,1): yield result
580                else: break
581        masterSecret = result
582
583        # Create the session object which is used for resumptions
584        self.session = Session()
585        self.session.create(masterSecret, serverHello.session_id, cipherSuite,
586            srpUsername, clientCertChain, serverCertChain,
587            tackExt, serverHello.tackExt!=None, serverName)
588        self._handshakeDone(resumed=False)
589
590
591    def _clientSendClientHello(self, settings, session, srpUsername,
592                                srpParams, certParams, anonParams,
593                                serverName, nextProtos, reqTack):
594        #Initialize acceptable ciphersuites
595        cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
596        if srpParams:
597            cipherSuites += CipherSuite.getSrpAllSuites(settings)
598        elif certParams:
599            cipherSuites += CipherSuite.getCertSuites(settings)
600            # TODO: Client DHE_RSA not supported.
601            # cipherSuites += CipherSuite.getDheCertSuites(settings)
602        elif anonParams:
603            cipherSuites += CipherSuite.getAnonSuites(settings)
604        else:
605            assert(False)
606
607        #Initialize acceptable certificate types
608        certificateTypes = settings._getCertificateTypes()
609
610        #Either send ClientHello (with a resumable session)...
611        if session and session.sessionID:
612            #If it's resumable, then its
613            #ciphersuite must be one of the acceptable ciphersuites
614            if session.cipherSuite not in cipherSuites:
615                raise ValueError("Session's cipher suite not consistent "\
616                                 "with parameters")
617            else:
618                clientHello = ClientHello()
619                clientHello.create(settings.maxVersion, getRandomBytes(32),
620                                   session.sessionID, cipherSuites,
621                                   certificateTypes,
622                                   session.srpUsername,
623                                   reqTack, nextProtos is not None,
624                                   session.serverName)
625
626        #Or send ClientHello (without)
627        else:
628            clientHello = ClientHello()
629            clientHello.create(settings.maxVersion, getRandomBytes(32),
630                               bytearray(0), cipherSuites,
631                               certificateTypes,
632                               srpUsername,
633                               reqTack, nextProtos is not None,
634                               serverName)
635        for result in self._sendMsg(clientHello):
636            yield result
637        yield clientHello
638
639
640    def _clientGetServerHello(self, settings, clientHello):
641        for result in self._getMsg(ContentType.handshake,
642                                  HandshakeType.server_hello):
643            if result in (0,1): yield result
644            else: break
645        serverHello = result
646
647        #Get the server version.  Do this before anything else, so any
648        #error alerts will use the server's version
649        self.version = serverHello.server_version
650
651        #Future responses from server must use this version
652        self._versionCheck = True
653
654        #Check ServerHello
655        if serverHello.server_version < settings.minVersion:
656            for result in self._sendError(\
657                AlertDescription.protocol_version,
658                "Too old version: %s" % str(serverHello.server_version)):
659                yield result
660        if serverHello.server_version > settings.maxVersion:
661            for result in self._sendError(\
662                AlertDescription.protocol_version,
663                "Too new version: %s" % str(serverHello.server_version)):
664                yield result
665        if serverHello.cipher_suite not in clientHello.cipher_suites:
666            for result in self._sendError(\
667                AlertDescription.illegal_parameter,
668                "Server responded with incorrect ciphersuite"):
669                yield result
670        if serverHello.certificate_type not in clientHello.certificate_types:
671            for result in self._sendError(\
672                AlertDescription.illegal_parameter,
673                "Server responded with incorrect certificate type"):
674                yield result
675        if serverHello.compression_method != 0:
676            for result in self._sendError(\
677                AlertDescription.illegal_parameter,
678                "Server responded with incorrect compression method"):
679                yield result
680        if serverHello.tackExt:
681            if not clientHello.tack:
682                for result in self._sendError(\
683                    AlertDescription.illegal_parameter,
684                    "Server responded with unrequested Tack Extension"):
685                    yield result
686        if serverHello.next_protos and not clientHello.supports_npn:
687            for result in self._sendError(\
688                AlertDescription.illegal_parameter,
689                "Server responded with unrequested NPN Extension"):
690                yield result
691            if not serverHello.tackExt.verifySignatures():
692                for result in self._sendError(\
693                    AlertDescription.decrypt_error,
694                    "TackExtension contains an invalid signature"):
695                    yield result
696        yield serverHello
697
698    def _clientSelectNextProto(self, nextProtos, serverHello):
699        # nextProtos is None or non-empty list of strings
700        # serverHello.next_protos is None or possibly-empty list of strings
701        #
702        # !!! We assume the client may have specified nextProtos as a list of
703        # strings so we convert them to bytearrays (it's awkward to require
704        # the user to specify a list of bytearrays or "bytes", and in
705        # Python 2.6 bytes() is just an alias for str() anyways...
706        if nextProtos is not None and serverHello.next_protos is not None:
707            for p in nextProtos:
708                if bytearray(p) in serverHello.next_protos:
709                    return bytearray(p)
710            else:
711                # If the client doesn't support any of server's protocols,
712                # or the server doesn't advertise any (next_protos == [])
713                # the client SHOULD select the first protocol it supports.
714                return bytearray(nextProtos[0])
715        return None
716
717    def _clientResume(self, session, serverHello, clientRandom,
718                      cipherImplementations, nextProto):
719        #If the server agrees to resume
720        if session and session.sessionID and \
721            serverHello.session_id == session.sessionID:
722
723            if serverHello.cipher_suite != session.cipherSuite:
724                for result in self._sendError(\
725                    AlertDescription.illegal_parameter,\
726                    "Server's ciphersuite doesn't match session"):
727                    yield result
728
729            #Calculate pending connection states
730            self._calcPendingStates(session.cipherSuite,
731                                    session.masterSecret,
732                                    clientRandom, serverHello.random,
733                                    cipherImplementations)
734
735            #Exchange ChangeCipherSpec and Finished messages
736            for result in self._getFinished(session.masterSecret):
737                yield result
738            for result in self._sendFinished(session.masterSecret, nextProto):
739                yield result
740
741            #Set the session for this connection
742            self.session = session
743            yield "resumed_and_finished"
744
745    def _clientSRPKeyExchange(self, settings, cipherSuite, certificateType,
746            srpUsername, password,
747            clientRandom, serverRandom, tackExt):
748
749        #If the server chose an SRP+RSA suite...
750        if cipherSuite in CipherSuite.srpCertSuites:
751            #Get Certificate, ServerKeyExchange, ServerHelloDone
752            for result in self._getMsg(ContentType.handshake,
753                    HandshakeType.certificate, certificateType):
754                if result in (0,1): yield result
755                else: break
756            serverCertificate = result
757        else:
758            serverCertificate = None
759
760        for result in self._getMsg(ContentType.handshake,
761                HandshakeType.server_key_exchange, cipherSuite):
762            if result in (0,1): yield result
763            else: break
764        serverKeyExchange = result
765
766        for result in self._getMsg(ContentType.handshake,
767                HandshakeType.server_hello_done):
768            if result in (0,1): yield result
769            else: break
770        serverHelloDone = result
771
772        #Calculate SRP premaster secret
773        #Get and check the server's group parameters and B value
774        N = serverKeyExchange.srp_N
775        g = serverKeyExchange.srp_g
776        s = serverKeyExchange.srp_s
777        B = serverKeyExchange.srp_B
778
779        if (g,N) not in goodGroupParameters:
780            for result in self._sendError(\
781                    AlertDescription.insufficient_security,
782                    "Unknown group parameters"):
783                yield result
784        if numBits(N) < settings.minKeySize:
785            for result in self._sendError(\
786                    AlertDescription.insufficient_security,
787                    "N value is too small: %d" % numBits(N)):
788                yield result
789        if numBits(N) > settings.maxKeySize:
790            for result in self._sendError(\
791                    AlertDescription.insufficient_security,
792                    "N value is too large: %d" % numBits(N)):
793                yield result
794        if B % N == 0:
795            for result in self._sendError(\
796                    AlertDescription.illegal_parameter,
797                    "Suspicious B value"):
798                yield result
799
800        #Check the server's signature, if server chose an
801        #SRP+RSA suite
802        serverCertChain = None
803        if cipherSuite in CipherSuite.srpCertSuites:
804            #Hash ServerKeyExchange/ServerSRPParams
805            hashBytes = serverKeyExchange.hash(clientRandom, serverRandom)
806
807            #Extract signature bytes from ServerKeyExchange
808            sigBytes = serverKeyExchange.signature
809            if len(sigBytes) == 0:
810                for result in self._sendError(\
811                        AlertDescription.illegal_parameter,
812                        "Server sent an SRP ServerKeyExchange "\
813                        "message without a signature"):
814                    yield result
815
816            # Get server's public key from the Certificate message
817            # Also validate the chain against the ServerHello's TACKext (if any)
818            # If none, and a TACK cert is present, return its TACKext
819            for result in self._clientGetKeyFromChain(serverCertificate,
820                                               settings, tackExt):
821                if result in (0,1): yield result
822                else: break
823            publicKey, serverCertChain, tackExt = result
824
825            #Verify signature
826            if not publicKey.verify(sigBytes, hashBytes):
827                for result in self._sendError(\
828                        AlertDescription.decrypt_error,
829                        "Signature failed to verify"):
830                    yield result
831
832        #Calculate client's ephemeral DH values (a, A)
833        a = bytesToNumber(getRandomBytes(32))
834        A = powMod(g, a, N)
835
836        #Calculate client's static DH values (x, v)
837        x = makeX(s, bytearray(srpUsername, "utf-8"),
838                    bytearray(password, "utf-8"))
839        v = powMod(g, x, N)
840
841        #Calculate u
842        u = makeU(N, A, B)
843
844        #Calculate premaster secret
845        k = makeK(N, g)
846        S = powMod((B - (k*v)) % N, a+(u*x), N)
847
848        if self.fault == Fault.badA:
849            A = N
850            S = 0
851
852        premasterSecret = numberToByteArray(S)
853
854        #Send ClientKeyExchange
855        for result in self._sendMsg(\
856                ClientKeyExchange(cipherSuite).createSRP(A)):
857            yield result
858        yield (premasterSecret, serverCertChain, tackExt)
859
860
861    def _clientRSAKeyExchange(self, settings, cipherSuite,
862                                clientCertChain, privateKey,
863                                certificateType,
864                                clientRandom, serverRandom,
865                                tackExt):
866
867        #Get Certificate[, CertificateRequest], ServerHelloDone
868        for result in self._getMsg(ContentType.handshake,
869                HandshakeType.certificate, certificateType):
870            if result in (0,1): yield result
871            else: break
872        serverCertificate = result
873
874        # Get CertificateRequest or ServerHelloDone
875        for result in self._getMsg(ContentType.handshake,
876                (HandshakeType.server_hello_done,
877                HandshakeType.certificate_request)):
878            if result in (0,1): yield result
879            else: break
880        msg = result
881        certificateRequest = None
882        if isinstance(msg, CertificateRequest):
883            certificateRequest = msg
884            # We got CertificateRequest, so this must be ServerHelloDone
885            for result in self._getMsg(ContentType.handshake,
886                    HandshakeType.server_hello_done):
887                if result in (0,1): yield result
888                else: break
889            serverHelloDone = result
890        elif isinstance(msg, ServerHelloDone):
891            serverHelloDone = msg
892
893        # Get server's public key from the Certificate message
894        # Also validate the chain against the ServerHello's TACKext (if any)
895        # If none, and a TACK cert is present, return its TACKext
896        for result in self._clientGetKeyFromChain(serverCertificate,
897                                           settings, tackExt):
898            if result in (0,1): yield result
899            else: break
900        publicKey, serverCertChain, tackExt = result
901
902        #Calculate premaster secret
903        premasterSecret = getRandomBytes(48)
904        premasterSecret[0] = settings.maxVersion[0]
905        premasterSecret[1] = settings.maxVersion[1]
906
907        if self.fault == Fault.badPremasterPadding:
908            premasterSecret[0] = 5
909        if self.fault == Fault.shortPremasterSecret:
910            premasterSecret = premasterSecret[:-1]
911
912        #Encrypt premaster secret to server's public key
913        encryptedPreMasterSecret = publicKey.encrypt(premasterSecret)
914
915        #If client authentication was requested, send Certificate
916        #message, either with certificates or empty
917        if certificateRequest:
918            clientCertificate = Certificate(certificateType)
919
920            if clientCertChain:
921                #Check to make sure we have the same type of
922                #certificates the server requested
923                wrongType = False
924                if certificateType == CertificateType.x509:
925                    if not isinstance(clientCertChain, X509CertChain):
926                        wrongType = True
927                if wrongType:
928                    for result in self._sendError(\
929                            AlertDescription.handshake_failure,
930                            "Client certificate is of wrong type"):
931                        yield result
932
933                clientCertificate.create(clientCertChain)
934            for result in self._sendMsg(clientCertificate):
935                yield result
936        else:
937            #The server didn't request client auth, so we
938            #zeroize these so the clientCertChain won't be
939            #stored in the session.
940            privateKey = None
941            clientCertChain = None
942
943        #Send ClientKeyExchange
944        clientKeyExchange = ClientKeyExchange(cipherSuite,
945                                              self.version)
946        clientKeyExchange.createRSA(encryptedPreMasterSecret)
947        for result in self._sendMsg(clientKeyExchange):
948            yield result
949
950        #If client authentication was requested and we have a
951        #private key, send CertificateVerify
952        if certificateRequest and privateKey:
953            if self.version == (3,0):
954                masterSecret = calcMasterSecret(self.version,
955                                         premasterSecret,
956                                         clientRandom,
957                                         serverRandom)
958                verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
959            elif self.version in ((3,1), (3,2)):
960                verifyBytes = self._handshake_md5.digest() + \
961                                self._handshake_sha.digest()
962            if self.fault == Fault.badVerifyMessage:
963                verifyBytes[0] = ((verifyBytes[0]+1) % 256)
964            signedBytes = privateKey.sign(verifyBytes)
965            certificateVerify = CertificateVerify()
966            certificateVerify.create(signedBytes)
967            for result in self._sendMsg(certificateVerify):
968                yield result
969        yield (premasterSecret, serverCertChain, clientCertChain, tackExt)
970
971    def _clientAnonKeyExchange(self, settings, cipherSuite, clientRandom,
972                               serverRandom):
973        for result in self._getMsg(ContentType.handshake,
974                HandshakeType.server_key_exchange, cipherSuite):
975            if result in (0,1): yield result
976            else: break
977        serverKeyExchange = result
978
979        for result in self._getMsg(ContentType.handshake,
980                HandshakeType.server_hello_done):
981            if result in (0,1): yield result
982            else: break
983        serverHelloDone = result
984
985        #calculate Yc
986        dh_p = serverKeyExchange.dh_p
987        dh_g = serverKeyExchange.dh_g
988        dh_Xc = bytesToNumber(getRandomBytes(32))
989        dh_Ys = serverKeyExchange.dh_Ys
990        dh_Yc = powMod(dh_g, dh_Xc, dh_p)
991
992        #Send ClientKeyExchange
993        for result in self._sendMsg(\
994                ClientKeyExchange(cipherSuite, self.version).createDH(dh_Yc)):
995            yield result
996
997        #Calculate premaster secret
998        S = powMod(dh_Ys, dh_Xc, dh_p)
999        premasterSecret = numberToByteArray(S)
1000
1001        yield (premasterSecret, None, None)
1002
1003    def _clientFinished(self, premasterSecret, clientRandom, serverRandom,
1004                        cipherSuite, cipherImplementations, nextProto):
1005
1006        masterSecret = calcMasterSecret(self.version, premasterSecret,
1007                            clientRandom, serverRandom)
1008        self._calcPendingStates(cipherSuite, masterSecret,
1009                                clientRandom, serverRandom,
1010                                cipherImplementations)
1011
1012        #Exchange ChangeCipherSpec and Finished messages
1013        for result in self._sendFinished(masterSecret, nextProto):
1014            yield result
1015        for result in self._getFinished(masterSecret, nextProto=nextProto):
1016            yield result
1017        yield masterSecret
1018
1019    def _clientGetKeyFromChain(self, certificate, settings, tackExt=None):
1020        #Get and check cert chain from the Certificate message
1021        certChain = certificate.certChain
1022        if not certChain or certChain.getNumCerts() == 0:
1023            for result in self._sendError(AlertDescription.illegal_parameter,
1024                    "Other party sent a Certificate message without "\
1025                    "certificates"):
1026                yield result
1027
1028        #Get and check public key from the cert chain
1029        publicKey = certChain.getEndEntityPublicKey()
1030        if len(publicKey) < settings.minKeySize:
1031            for result in self._sendError(AlertDescription.handshake_failure,
1032                    "Other party's public key too small: %d" % len(publicKey)):
1033                yield result
1034        if len(publicKey) > settings.maxKeySize:
1035            for result in self._sendError(AlertDescription.handshake_failure,
1036                    "Other party's public key too large: %d" % len(publicKey)):
1037                yield result
1038
1039        # If there's no TLS Extension, look for a TACK cert
1040        if tackpyLoaded:
1041            if not tackExt:
1042                tackExt = certChain.getTackExt()
1043
1044            # If there's a TACK (whether via TLS or TACK Cert), check that it
1045            # matches the cert chain
1046            if tackExt and tackExt.tacks:
1047                for tack in tackExt.tacks:
1048                    if not certChain.checkTack(tack):
1049                        for result in self._sendError(
1050                                AlertDescription.illegal_parameter,
1051                                "Other party's TACK doesn't match their public key"):
1052                                yield result
1053
1054        yield publicKey, certChain, tackExt
1055
1056
1057    #*********************************************************
1058    # Server Handshake Functions
1059    #*********************************************************
1060
1061
1062    def handshakeServer(self, verifierDB=None,
1063                        certChain=None, privateKey=None, reqCert=False,
1064                        sessionCache=None, settings=None, checker=None,
1065                        reqCAs = None, reqCertTypes = None,
1066                        tacks=None, activationFlags=0,
1067                        nextProtos=None, anon=False,
1068                        tlsIntolerant=None, signedCertTimestamps=None,
1069                        fallbackSCSV=False, ocspResponse=None):
1070        """Perform a handshake in the role of server.
1071
1072        This function performs an SSL or TLS handshake.  Depending on
1073        the arguments and the behavior of the client, this function can
1074        perform an SRP, or certificate-based handshake.  It
1075        can also perform a combined SRP and server-certificate
1076        handshake.
1077
1078        Like any handshake function, this can be called on a closed
1079        TLS connection, or on a TLS connection that is already open.
1080        If called on an open connection it performs a re-handshake.
1081        This function does not send a Hello Request message before
1082        performing the handshake, so if re-handshaking is required,
1083        the server must signal the client to begin the re-handshake
1084        through some other means.
1085
1086        If the function completes without raising an exception, the
1087        TLS connection will be open and available for data transfer.
1088
1089        If an exception is raised, the connection will have been
1090        automatically closed (if it was ever open).
1091
1092        @type verifierDB: L{tlslite.verifierdb.VerifierDB}
1093        @param verifierDB: A database of SRP password verifiers
1094        associated with usernames.  If the client performs an SRP
1095        handshake, the session's srpUsername attribute will be set.
1096
1097        @type certChain: L{tlslite.x509certchain.X509CertChain}
1098        @param certChain: The certificate chain to be used if the
1099        client requests server certificate authentication.
1100
1101        @type privateKey: L{tlslite.utils.rsakey.RSAKey}
1102        @param privateKey: The private key to be used if the client
1103        requests server certificate authentication.
1104
1105        @type reqCert: bool
1106        @param reqCert: Whether to request client certificate
1107        authentication.  This only applies if the client chooses server
1108        certificate authentication; if the client chooses SRP
1109        authentication, this will be ignored.  If the client
1110        performs a client certificate authentication, the sessions's
1111        clientCertChain attribute will be set.
1112
1113        @type sessionCache: L{tlslite.sessioncache.SessionCache}
1114        @param sessionCache: An in-memory cache of resumable sessions.
1115        The client can resume sessions from this cache.  Alternatively,
1116        if the client performs a full handshake, a new session will be
1117        added to the cache.
1118
1119        @type settings: L{tlslite.handshakesettings.HandshakeSettings}
1120        @param settings: Various settings which can be used to control
1121        the ciphersuites and SSL/TLS version chosen by the server.
1122
1123        @type checker: L{tlslite.checker.Checker}
1124        @param checker: A Checker instance.  This instance will be
1125        invoked to examine the other party's authentication
1126        credentials, if the handshake completes succesfully.
1127
1128        @type reqCAs: list of L{bytearray} of unsigned bytes
1129        @param reqCAs: A collection of DER-encoded DistinguishedNames that
1130        will be sent along with a certificate request. This does not affect
1131        verification.
1132
1133        @type reqCertTypes: list of int
1134        @param reqCertTypes: A list of certificate_type values to be sent
1135        along with a certificate request. This does not affect verification.
1136
1137        @type nextProtos: list of strings.
1138        @param nextProtos: A list of upper layer protocols to expose to the
1139        clients through the Next-Protocol Negotiation Extension,
1140        if they support it.
1141
1142        @type tlsIntolerant: (int, int) or None
1143        @param tlsIntolerant: If tlsIntolerant is not None, the server will
1144        simulate TLS version intolerance by returning a fatal handshake_failure
1145        alert to all TLS versions tlsIntolerant or higher.
1146
1147        @type signedCertTimestamps: str
1148        @param signedCertTimestamps: A SignedCertificateTimestampList (as a
1149        binary 8-bit string) that will be sent as a TLS extension whenever
1150        the client announces support for the extension.
1151
1152        @type fallbackSCSV: bool
1153        @param fallbackSCSV: if true, the server will implement
1154        TLS_FALLBACK_SCSV and thus reject connections using less than the
1155        server's maximum TLS version that include this cipher suite.
1156
1157        @type ocspResponse: str
1158        @param ocspResponse: An OCSP response (as a binary 8-bit string) that
1159        will be sent stapled in the handshake whenever the client announces
1160        support for the status_request extension.
1161        Note that the response is sent independent of the ClientHello
1162        status_request extension contents, and is thus only meant for testing
1163        environments. Real OCSP stapling is more complicated as it requires
1164        choosing a suitable response based on the ClientHello status_request
1165        extension contents.
1166
1167        @raise socket.error: If a socket error occurs.
1168        @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
1169        without a preceding alert.
1170        @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
1171        @raise tlslite.errors.TLSAuthenticationError: If the checker
1172        doesn't like the other party's authentication credentials.
1173        """
1174        for result in self.handshakeServerAsync(verifierDB,
1175                certChain, privateKey, reqCert, sessionCache, settings,
1176                checker, reqCAs, reqCertTypes,
1177                tacks=tacks, activationFlags=activationFlags,
1178                nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant,
1179                signedCertTimestamps=signedCertTimestamps,
1180                fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse):
1181            pass
1182
1183
1184    def handshakeServerAsync(self, verifierDB=None,
1185                             certChain=None, privateKey=None, reqCert=False,
1186                             sessionCache=None, settings=None, checker=None,
1187                             reqCAs=None, reqCertTypes=None,
1188                             tacks=None, activationFlags=0,
1189                             nextProtos=None, anon=False,
1190                             tlsIntolerant=None,
1191                             signedCertTimestamps=None,
1192                             fallbackSCSV=False,
1193                             ocspResponse=None
1194                             ):
1195        """Start a server handshake operation on the TLS connection.
1196
1197        This function returns a generator which behaves similarly to
1198        handshakeServer().  Successive invocations of the generator
1199        will return 0 if it is waiting to read from the socket, 1 if it is
1200        waiting to write to the socket, or it will raise StopIteration
1201        if the handshake operation is complete.
1202
1203        @rtype: iterable
1204        @return: A generator; see above for details.
1205        """
1206        handshaker = self._handshakeServerAsyncHelper(\
1207            verifierDB=verifierDB, certChain=certChain,
1208            privateKey=privateKey, reqCert=reqCert,
1209            sessionCache=sessionCache, settings=settings,
1210            reqCAs=reqCAs, reqCertTypes=reqCertTypes,
1211            tacks=tacks, activationFlags=activationFlags,
1212            nextProtos=nextProtos, anon=anon,
1213            tlsIntolerant=tlsIntolerant,
1214            signedCertTimestamps=signedCertTimestamps,
1215            fallbackSCSV=fallbackSCSV,
1216            ocspResponse=ocspResponse)
1217        for result in self._handshakeWrapperAsync(handshaker, checker):
1218            yield result
1219
1220
1221    def _handshakeServerAsyncHelper(self, verifierDB,
1222                             certChain, privateKey, reqCert, sessionCache,
1223                             settings, reqCAs, reqCertTypes,
1224                             tacks, activationFlags,
1225                             nextProtos, anon,
1226                             tlsIntolerant, signedCertTimestamps, fallbackSCSV,
1227                             ocspResponse):
1228
1229        self._handshakeStart(client=False)
1230
1231        if (not verifierDB) and (not certChain) and not anon:
1232            raise ValueError("Caller passed no authentication credentials")
1233        if certChain and not privateKey:
1234            raise ValueError("Caller passed a certChain but no privateKey")
1235        if privateKey and not certChain:
1236            raise ValueError("Caller passed a privateKey but no certChain")
1237        if reqCAs and not reqCert:
1238            raise ValueError("Caller passed reqCAs but not reqCert")
1239        if reqCertTypes and not reqCert:
1240            raise ValueError("Caller passed reqCertTypes but not reqCert")
1241        if certChain and not isinstance(certChain, X509CertChain):
1242            raise ValueError("Unrecognized certificate type")
1243        if activationFlags and not tacks:
1244            raise ValueError("Nonzero activationFlags requires tacks")
1245        if tacks:
1246            if not tackpyLoaded:
1247                raise ValueError("tackpy is not loaded")
1248            if not settings or not settings.useExperimentalTackExtension:
1249                raise ValueError("useExperimentalTackExtension not enabled")
1250        if signedCertTimestamps and not certChain:
1251            raise ValueError("Caller passed signedCertTimestamps but no "
1252                             "certChain")
1253
1254        if not settings:
1255            settings = HandshakeSettings()
1256        settings = settings._filter()
1257
1258        # OK Start exchanging messages
1259        # ******************************
1260
1261        # Handle ClientHello and resumption
1262        for result in self._serverGetClientHello(settings, certChain,\
1263                                            verifierDB, sessionCache,
1264                                            anon, tlsIntolerant, fallbackSCSV):
1265            if result in (0,1): yield result
1266            elif result == None:
1267                self._handshakeDone(resumed=True)
1268                return # Handshake was resumed, we're done
1269            else: break
1270        (clientHello, cipherSuite) = result
1271
1272        #If not a resumption...
1273
1274        # Create the ServerHello message
1275        if sessionCache:
1276            sessionID = getRandomBytes(32)
1277        else:
1278            sessionID = bytearray(0)
1279
1280        if not clientHello.supports_npn:
1281            nextProtos = None
1282
1283        # If not doing a certificate-based suite, discard the TACK
1284        if not cipherSuite in CipherSuite.certAllSuites:
1285            tacks = None
1286
1287        # Prepare a TACK Extension if requested
1288        if clientHello.tack:
1289            tackExt = TackExtension.create(tacks, activationFlags)
1290        else:
1291            tackExt = None
1292        serverHello = ServerHello()
1293        serverHello.create(self.version, getRandomBytes(32), sessionID, \
1294                            cipherSuite, CertificateType.x509, tackExt,
1295                            nextProtos)
1296        serverHello.channel_id = clientHello.channel_id
1297        if clientHello.support_signed_cert_timestamps:
1298            serverHello.signed_cert_timestamps = signedCertTimestamps
1299        if clientHello.status_request:
1300            serverHello.status_request = ocspResponse
1301
1302        # Perform the SRP key exchange
1303        clientCertChain = None
1304        if cipherSuite in CipherSuite.srpAllSuites:
1305            for result in self._serverSRPKeyExchange(clientHello, serverHello,
1306                                    verifierDB, cipherSuite,
1307                                    privateKey, certChain):
1308                if result in (0,1): yield result
1309                else: break
1310            premasterSecret = result
1311
1312        # Perform the RSA or DHE_RSA key exchange
1313        elif (cipherSuite in CipherSuite.certSuites or
1314              cipherSuite in CipherSuite.dheCertSuites):
1315            if cipherSuite in CipherSuite.certSuites:
1316                keyExchange = RSAKeyExchange(cipherSuite,
1317                                             clientHello,
1318                                             serverHello,
1319                                             privateKey)
1320            elif cipherSuite in CipherSuite.dheCertSuites:
1321                keyExchange = DHE_RSAKeyExchange(cipherSuite,
1322                                                 clientHello,
1323                                                 serverHello,
1324                                                 privateKey)
1325            else:
1326                assert(False)
1327            for result in self._serverCertKeyExchange(clientHello, serverHello,
1328                                        certChain, keyExchange,
1329                                        reqCert, reqCAs, reqCertTypes, cipherSuite,
1330                                        settings, ocspResponse):
1331                if result in (0,1): yield result
1332                else: break
1333            (premasterSecret, clientCertChain) = result
1334
1335        # Perform anonymous Diffie Hellman key exchange
1336        elif cipherSuite in CipherSuite.anonSuites:
1337            for result in self._serverAnonKeyExchange(clientHello, serverHello,
1338                                        cipherSuite, settings):
1339                if result in (0,1): yield result
1340                else: break
1341            premasterSecret = result
1342
1343        else:
1344            assert(False)
1345
1346        # Exchange Finished messages
1347        for result in self._serverFinished(premasterSecret,
1348                                clientHello.random, serverHello.random,
1349                                cipherSuite, settings.cipherImplementations,
1350                                nextProtos, clientHello.channel_id):
1351                if result in (0,1): yield result
1352                else: break
1353        masterSecret = result
1354
1355        #Create the session object
1356        self.session = Session()
1357        if cipherSuite in CipherSuite.certAllSuites:
1358            serverCertChain = certChain
1359        else:
1360            serverCertChain = None
1361        srpUsername = None
1362        serverName = None
1363        if clientHello.srp_username:
1364            srpUsername = clientHello.srp_username.decode("utf-8")
1365        if clientHello.server_name:
1366            serverName = clientHello.server_name.decode("utf-8")
1367        self.session.create(masterSecret, serverHello.session_id, cipherSuite,
1368            srpUsername, clientCertChain, serverCertChain,
1369            tackExt, serverHello.tackExt!=None, serverName)
1370
1371        #Add the session object to the session cache
1372        if sessionCache and sessionID:
1373            sessionCache[sessionID] = self.session
1374
1375        self._handshakeDone(resumed=False)
1376
1377
1378    def _serverGetClientHello(self, settings, certChain, verifierDB,
1379                                sessionCache, anon, tlsIntolerant, fallbackSCSV):
1380        #Initialize acceptable cipher suites
1381        cipherSuites = []
1382        if verifierDB:
1383            if certChain:
1384                cipherSuites += \
1385                    CipherSuite.getSrpCertSuites(settings)
1386            cipherSuites += CipherSuite.getSrpSuites(settings)
1387        elif certChain:
1388            cipherSuites += CipherSuite.getCertSuites(settings)
1389            cipherSuites += CipherSuite.getDheCertSuites(settings)
1390        elif anon:
1391            cipherSuites += CipherSuite.getAnonSuites(settings)
1392        else:
1393            assert(False)
1394
1395        #Tentatively set version to most-desirable version, so if an error
1396        #occurs parsing the ClientHello, this is what we'll use for the
1397        #error alert
1398        self.version = settings.maxVersion
1399
1400        #Get ClientHello
1401        for result in self._getMsg(ContentType.handshake,
1402                                   HandshakeType.client_hello):
1403            if result in (0,1): yield result
1404            else: break
1405        clientHello = result
1406
1407        #If client's version is too low, reject it
1408        if clientHello.client_version < settings.minVersion:
1409            self.version = settings.minVersion
1410            for result in self._sendError(\
1411                  AlertDescription.protocol_version,
1412                  "Too old version: %s" % str(clientHello.client_version)):
1413                yield result
1414
1415        #If simulating TLS intolerance, reject certain TLS versions.
1416        elif (tlsIntolerant is not None and
1417            clientHello.client_version >= tlsIntolerant):
1418            for result in self._sendError(\
1419                    AlertDescription.handshake_failure):
1420                yield result
1421
1422        #If client's version is too high, propose my highest version
1423        elif clientHello.client_version > settings.maxVersion:
1424            self.version = settings.maxVersion
1425
1426        #Detect if the client performed an inappropriate fallback.
1427        elif fallbackSCSV and clientHello.client_version < settings.maxVersion:
1428            if CipherSuite.TLS_FALLBACK_SCSV in clientHello.cipher_suites:
1429                for result in self._sendError(\
1430                        AlertDescription.inappropriate_fallback):
1431                    yield result
1432
1433        else:
1434            #Set the version to the client's version
1435            self.version = clientHello.client_version
1436
1437        #If resumption was requested and we have a session cache...
1438        if clientHello.session_id and sessionCache:
1439            session = None
1440
1441            #Check in the session cache
1442            if sessionCache and not session:
1443                try:
1444                    session = sessionCache[clientHello.session_id]
1445                    if not session.resumable:
1446                        raise AssertionError()
1447                    #Check for consistency with ClientHello
1448                    if session.cipherSuite not in cipherSuites:
1449                        for result in self._sendError(\
1450                                AlertDescription.handshake_failure):
1451                            yield result
1452                    if session.cipherSuite not in clientHello.cipher_suites:
1453                        for result in self._sendError(\
1454                                AlertDescription.handshake_failure):
1455                            yield result
1456                    if clientHello.srp_username:
1457                        if not session.srpUsername or \
1458                            clientHello.srp_username != bytearray(session.srpUsername, "utf-8"):
1459                            for result in self._sendError(\
1460                                    AlertDescription.handshake_failure):
1461                                yield result
1462                    if clientHello.server_name:
1463                        if not session.serverName or \
1464                            clientHello.server_name != bytearray(session.serverName, "utf-8"):
1465                            for result in self._sendError(\
1466                                    AlertDescription.handshake_failure):
1467                                yield result
1468                except KeyError:
1469                    pass
1470
1471            #If a session is found..
1472            if session:
1473                #Send ServerHello
1474                serverHello = ServerHello()
1475                serverHello.create(self.version, getRandomBytes(32),
1476                                   session.sessionID, session.cipherSuite,
1477                                   CertificateType.x509, None, None)
1478                for result in self._sendMsg(serverHello):
1479                    yield result
1480
1481                #From here on, the client's messages must have right version
1482                self._versionCheck = True
1483
1484                #Calculate pending connection states
1485                self._calcPendingStates(session.cipherSuite,
1486                                        session.masterSecret,
1487                                        clientHello.random,
1488                                        serverHello.random,
1489                                        settings.cipherImplementations)
1490
1491                #Exchange ChangeCipherSpec and Finished messages
1492                for result in self._sendFinished(session.masterSecret):
1493                    yield result
1494                for result in self._getFinished(session.masterSecret):
1495                    yield result
1496
1497                #Set the session
1498                self.session = session
1499
1500                yield None # Handshake done!
1501
1502        #Calculate the first cipher suite intersection.
1503        #This is the 'privileged' ciphersuite.  We'll use it if we're
1504        #doing a new negotiation.  In fact,
1505        #the only time we won't use it is if we're resuming a
1506        #session, in which case we use the ciphersuite from the session.
1507        #
1508        #Use the client's preferences for now.
1509        for cipherSuite in clientHello.cipher_suites:
1510            if cipherSuite in cipherSuites:
1511                break
1512        else:
1513            for result in self._sendError(\
1514                    AlertDescription.handshake_failure,
1515                    "No mutual ciphersuite"):
1516                yield result
1517        if cipherSuite in CipherSuite.srpAllSuites and \
1518                            not clientHello.srp_username:
1519            for result in self._sendError(\
1520                    AlertDescription.unknown_psk_identity,
1521                    "Client sent a hello, but without the SRP username"):
1522                yield result
1523
1524        #If an RSA suite is chosen, check for certificate type intersection
1525        if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \
1526                                not in clientHello.certificate_types:
1527            for result in self._sendError(\
1528                    AlertDescription.handshake_failure,
1529                    "the client doesn't support my certificate type"):
1530                yield result
1531
1532        # If resumption was not requested, or
1533        # we have no session cache, or
1534        # the client's session_id was not found in cache:
1535        yield (clientHello, cipherSuite)
1536
1537    def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB,
1538                                cipherSuite, privateKey, serverCertChain):
1539
1540        srpUsername = clientHello.srp_username.decode("utf-8")
1541        self.allegedSrpUsername = srpUsername
1542        #Get parameters from username
1543        try:
1544            entry = verifierDB[srpUsername]
1545        except KeyError:
1546            for result in self._sendError(\
1547                    AlertDescription.unknown_psk_identity):
1548                yield result
1549        (N, g, s, v) = entry
1550
1551        #Calculate server's ephemeral DH values (b, B)
1552        b = bytesToNumber(getRandomBytes(32))
1553        k = makeK(N, g)
1554        B = (powMod(g, b, N) + (k*v)) % N
1555
1556        #Create ServerKeyExchange, signing it if necessary
1557        serverKeyExchange = ServerKeyExchange(cipherSuite)
1558        serverKeyExchange.createSRP(N, g, s, B)
1559        if cipherSuite in CipherSuite.srpCertSuites:
1560            hashBytes = serverKeyExchange.hash(clientHello.random,
1561                                               serverHello.random)
1562            serverKeyExchange.signature = privateKey.sign(hashBytes)
1563
1564        #Send ServerHello[, Certificate], ServerKeyExchange,
1565        #ServerHelloDone
1566        msgs = []
1567        msgs.append(serverHello)
1568        if cipherSuite in CipherSuite.srpCertSuites:
1569            certificateMsg = Certificate(CertificateType.x509)
1570            certificateMsg.create(serverCertChain)
1571            msgs.append(certificateMsg)
1572        msgs.append(serverKeyExchange)
1573        msgs.append(ServerHelloDone())
1574        for result in self._sendMsgs(msgs):
1575            yield result
1576
1577        #From here on, the client's messages must have the right version
1578        self._versionCheck = True
1579
1580        #Get and check ClientKeyExchange
1581        for result in self._getMsg(ContentType.handshake,
1582                                  HandshakeType.client_key_exchange,
1583                                  cipherSuite):
1584            if result in (0,1): yield result
1585            else: break
1586        clientKeyExchange = result
1587        A = clientKeyExchange.srp_A
1588        if A % N == 0:
1589            for result in self._sendError(AlertDescription.illegal_parameter,
1590                    "Suspicious A value"):
1591                yield result
1592            assert(False) # Just to ensure we don't fall through somehow
1593
1594        #Calculate u
1595        u = makeU(N, A, B)
1596
1597        #Calculate premaster secret
1598        S = powMod((A * powMod(v,u,N)) % N, b, N)
1599        premasterSecret = numberToByteArray(S)
1600
1601        yield premasterSecret
1602
1603
1604    def _serverCertKeyExchange(self, clientHello, serverHello,
1605                                serverCertChain, keyExchange,
1606                                reqCert, reqCAs, reqCertTypes, cipherSuite,
1607                                settings, ocspResponse):
1608        #Send ServerHello, Certificate[, ServerKeyExchange]
1609        #[, CertificateRequest], ServerHelloDone
1610        msgs = []
1611
1612        # If we verify a client cert chain, return it
1613        clientCertChain = None
1614
1615        msgs.append(serverHello)
1616        msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
1617        if serverHello.status_request:
1618            msgs.append(CertificateStatus().create(ocspResponse))
1619        serverKeyExchange = keyExchange.makeServerKeyExchange()
1620        if serverKeyExchange is not None:
1621            msgs.append(serverKeyExchange)
1622        if reqCert:
1623            reqCAs = reqCAs or []
1624            #Apple's Secure Transport library rejects empty certificate_types,
1625            #so default to rsa_sign.
1626            reqCertTypes = reqCertTypes or [ClientCertificateType.rsa_sign]
1627            msgs.append(CertificateRequest().create(reqCertTypes, reqCAs))
1628        msgs.append(ServerHelloDone())
1629        for result in self._sendMsgs(msgs):
1630            yield result
1631
1632        #From here on, the client's messages must have the right version
1633        self._versionCheck = True
1634
1635        #Get [Certificate,] (if was requested)
1636        if reqCert:
1637            if self.version == (3,0):
1638                for result in self._getMsg((ContentType.handshake,
1639                                           ContentType.alert),
1640                                           HandshakeType.certificate,
1641                                           CertificateType.x509):
1642                    if result in (0,1): yield result
1643                    else: break
1644                msg = result
1645
1646                if isinstance(msg, Alert):
1647                    #If it's not a no_certificate alert, re-raise
1648                    alert = msg
1649                    if alert.description != \
1650                            AlertDescription.no_certificate:
1651                        self._shutdown(False)
1652                        raise TLSRemoteAlert(alert)
1653                elif isinstance(msg, Certificate):
1654                    clientCertificate = msg
1655                    if clientCertificate.certChain and \
1656                            clientCertificate.certChain.getNumCerts()!=0:
1657                        clientCertChain = clientCertificate.certChain
1658                else:
1659                    raise AssertionError()
1660            elif self.version in ((3,1), (3,2)):
1661                for result in self._getMsg(ContentType.handshake,
1662                                          HandshakeType.certificate,
1663                                          CertificateType.x509):
1664                    if result in (0,1): yield result
1665                    else: break
1666                clientCertificate = result
1667                if clientCertificate.certChain and \
1668                        clientCertificate.certChain.getNumCerts()!=0:
1669                    clientCertChain = clientCertificate.certChain
1670            else:
1671                raise AssertionError()
1672
1673        #Get ClientKeyExchange
1674        for result in self._getMsg(ContentType.handshake,
1675                                  HandshakeType.client_key_exchange,
1676                                  cipherSuite):
1677            if result in (0,1): yield result
1678            else: break
1679        clientKeyExchange = result
1680
1681        #Process ClientKeyExchange
1682        try:
1683            premasterSecret = \
1684                keyExchange.processClientKeyExchange(clientKeyExchange)
1685        except TLSLocalAlert, alert:
1686            for result in self._sendError(alert.description, alert.message):
1687                yield result
1688
1689        #Get and check CertificateVerify, if relevant
1690        if clientCertChain:
1691            if self.version == (3,0):
1692                masterSecret = calcMasterSecret(self.version, premasterSecret,
1693                                         clientHello.random, serverHello.random)
1694                verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
1695            elif self.version in ((3,1), (3,2)):
1696                verifyBytes = self._handshake_md5.digest() + \
1697                                self._handshake_sha.digest()
1698            for result in self._getMsg(ContentType.handshake,
1699                                      HandshakeType.certificate_verify):
1700                if result in (0,1): yield result
1701                else: break
1702            certificateVerify = result
1703            publicKey = clientCertChain.getEndEntityPublicKey()
1704            if len(publicKey) < settings.minKeySize:
1705                for result in self._sendError(\
1706                        AlertDescription.handshake_failure,
1707                        "Client's public key too small: %d" % len(publicKey)):
1708                    yield result
1709
1710            if len(publicKey) > settings.maxKeySize:
1711                for result in self._sendError(\
1712                        AlertDescription.handshake_failure,
1713                        "Client's public key too large: %d" % len(publicKey)):
1714                    yield result
1715
1716            if not publicKey.verify(certificateVerify.signature, verifyBytes):
1717                for result in self._sendError(\
1718                        AlertDescription.decrypt_error,
1719                        "Signature failed to verify"):
1720                    yield result
1721        yield (premasterSecret, clientCertChain)
1722
1723
1724    def _serverAnonKeyExchange(self, clientHello, serverHello, cipherSuite,
1725                               settings):
1726        # Calculate DH p, g, Xs, Ys
1727        dh_p = getRandomSafePrime(32, False)
1728        dh_g = getRandomNumber(2, dh_p)
1729        dh_Xs = bytesToNumber(getRandomBytes(32))
1730        dh_Ys = powMod(dh_g, dh_Xs, dh_p)
1731
1732        #Create ServerKeyExchange
1733        serverKeyExchange = ServerKeyExchange(cipherSuite)
1734        serverKeyExchange.createDH(dh_p, dh_g, dh_Ys)
1735
1736        #Send ServerHello[, Certificate], ServerKeyExchange,
1737        #ServerHelloDone
1738        msgs = []
1739        msgs.append(serverHello)
1740        msgs.append(serverKeyExchange)
1741        msgs.append(ServerHelloDone())
1742        for result in self._sendMsgs(msgs):
1743            yield result
1744
1745        #From here on, the client's messages must have the right version
1746        self._versionCheck = True
1747
1748        #Get and check ClientKeyExchange
1749        for result in self._getMsg(ContentType.handshake,
1750                                   HandshakeType.client_key_exchange,
1751                                   cipherSuite):
1752            if result in (0,1):
1753                yield result
1754            else:
1755                break
1756        clientKeyExchange = result
1757        dh_Yc = clientKeyExchange.dh_Yc
1758
1759        if dh_Yc % dh_p == 0:
1760            for result in self._sendError(AlertDescription.illegal_parameter,
1761                    "Suspicious dh_Yc value"):
1762                yield result
1763            assert(False) # Just to ensure we don't fall through somehow
1764
1765        #Calculate premaster secre
1766        S = powMod(dh_Yc,dh_Xs,dh_p)
1767        premasterSecret = numberToByteArray(S)
1768
1769        yield premasterSecret
1770
1771
1772    def _serverFinished(self,  premasterSecret, clientRandom, serverRandom,
1773                        cipherSuite, cipherImplementations, nextProtos,
1774                        doingChannelID):
1775        masterSecret = calcMasterSecret(self.version, premasterSecret,
1776                                      clientRandom, serverRandom)
1777
1778        #Calculate pending connection states
1779        self._calcPendingStates(cipherSuite, masterSecret,
1780                                clientRandom, serverRandom,
1781                                cipherImplementations)
1782
1783        #Exchange ChangeCipherSpec and Finished messages
1784        for result in self._getFinished(masterSecret,
1785                        expect_next_protocol=nextProtos is not None,
1786                        expect_channel_id=doingChannelID):
1787            yield result
1788
1789        for result in self._sendFinished(masterSecret):
1790            yield result
1791
1792        yield masterSecret
1793
1794
1795    #*********************************************************
1796    # Shared Handshake Functions
1797    #*********************************************************
1798
1799
1800    def _sendFinished(self, masterSecret, nextProto=None):
1801        #Send ChangeCipherSpec
1802        for result in self._sendMsg(ChangeCipherSpec()):
1803            yield result
1804
1805        #Switch to pending write state
1806        self._changeWriteState()
1807
1808        if nextProto is not None:
1809            nextProtoMsg = NextProtocol().create(nextProto)
1810            for result in self._sendMsg(nextProtoMsg):
1811                yield result
1812
1813        #Calculate verification data
1814        verifyData = self._calcFinished(masterSecret, True)
1815        if self.fault == Fault.badFinished:
1816            verifyData[0] = (verifyData[0]+1)%256
1817
1818        #Send Finished message under new state
1819        finished = Finished(self.version).create(verifyData)
1820        for result in self._sendMsg(finished):
1821            yield result
1822
1823    def _getFinished(self, masterSecret, expect_next_protocol=False, nextProto=None,
1824                     expect_channel_id=False):
1825        #Get and check ChangeCipherSpec
1826        for result in self._getMsg(ContentType.change_cipher_spec):
1827            if result in (0,1):
1828                yield result
1829        changeCipherSpec = result
1830
1831        if changeCipherSpec.type != 1:
1832            for result in self._sendError(AlertDescription.illegal_parameter,
1833                                         "ChangeCipherSpec type incorrect"):
1834                yield result
1835
1836        #Switch to pending read state
1837        self._changeReadState()
1838
1839        #Server Finish - Are we waiting for a next protocol echo?
1840        if expect_next_protocol:
1841            for result in self._getMsg(ContentType.handshake, HandshakeType.next_protocol):
1842                if result in (0,1):
1843                    yield result
1844            if result is None:
1845                for result in self._sendError(AlertDescription.unexpected_message,
1846                                             "Didn't get NextProtocol message"):
1847                    yield result
1848
1849            self.next_proto = result.next_proto
1850        else:
1851            self.next_proto = None
1852
1853        #Client Finish - Only set the next_protocol selected in the connection
1854        if nextProto:
1855            self.next_proto = nextProto
1856
1857        #Server Finish - Are we waiting for a EncryptedExtensions?
1858        if expect_channel_id:
1859            for result in self._getMsg(ContentType.handshake, HandshakeType.encrypted_extensions):
1860                if result in (0,1):
1861                    yield result
1862            if result is None:
1863                for result in self._sendError(AlertDescription.unexpected_message,
1864                                             "Didn't get EncryptedExtensions message"):
1865                    yield result
1866            encrypted_extensions = result
1867            self.channel_id = result.channel_id_key
1868        else:
1869            self.channel_id = None
1870
1871        #Calculate verification data
1872        verifyData = self._calcFinished(masterSecret, False)
1873
1874        #Get and check Finished message under new state
1875        for result in self._getMsg(ContentType.handshake,
1876                                  HandshakeType.finished):
1877            if result in (0,1):
1878                yield result
1879        finished = result
1880        if finished.verify_data != verifyData:
1881            for result in self._sendError(AlertDescription.decrypt_error,
1882                                         "Finished message is incorrect"):
1883                yield result
1884
1885    def _calcFinished(self, masterSecret, send=True):
1886        if self.version == (3,0):
1887            if (self._client and send) or (not self._client and not send):
1888                senderStr = b"\x43\x4C\x4E\x54"
1889            else:
1890                senderStr = b"\x53\x52\x56\x52"
1891
1892            verifyData = self._calcSSLHandshakeHash(masterSecret, senderStr)
1893            return verifyData
1894
1895        elif self.version in ((3,1), (3,2)):
1896            if (self._client and send) or (not self._client and not send):
1897                label = b"client finished"
1898            else:
1899                label = b"server finished"
1900
1901            handshakeHashes = self._handshake_md5.digest() + \
1902                                self._handshake_sha.digest()
1903            verifyData = PRF(masterSecret, label, handshakeHashes, 12)
1904            return verifyData
1905        else:
1906            raise AssertionError()
1907
1908
1909    def _handshakeWrapperAsync(self, handshaker, checker):
1910        if not self.fault:
1911            try:
1912                for result in handshaker:
1913                    yield result
1914                if checker:
1915                    try:
1916                        checker(self)
1917                    except TLSAuthenticationError:
1918                        alert = Alert().create(AlertDescription.close_notify,
1919                                               AlertLevel.fatal)
1920                        for result in self._sendMsg(alert):
1921                            yield result
1922                        raise
1923            except GeneratorExit:
1924                raise
1925            except TLSAlert as alert:
1926                if not self.fault:
1927                    raise
1928                if alert.description not in Fault.faultAlerts[self.fault]:
1929                    raise TLSFaultError(str(alert))
1930                else:
1931                    pass
1932            except:
1933                self._shutdown(False)
1934                raise
1935