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