tlslite.tlsconnection

Package tlslite :: Module tlsconnection |
[hide private]
[frames] | no frames]

# Source Code for Module tlslite.tlsconnection

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