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              if self.fault == Fault.badVerifyMessage:
     864                  verifyBytes[0] = ((verifyBytes[0]+1) % 256)
     865              signedBytes = privateKey.sign(verifyBytes)
     866              certificateVerify = CertificateVerify()
     867              certificateVerify.create(signedBytes)
     868              for result in self._sendMsg(certificateVerify):
     869                  yield result
     870          yield (premasterSecret, serverCertChain, clientCertChain, tackExt)
     871
     872 -    def _clientAnonKeyExchange(self, settings, cipherSuite, clientRandom,
     873                                 serverRandom):
     874          for result in self._getMsg(ContentType.handshake,
     875                  HandshakeType.server_key_exchange, cipherSuite):
     876              if result in (0,1): yield result
     877              else: break
     878          serverKeyExchange = result
     879
     880          for result in self._getMsg(ContentType.handshake,
     881                  HandshakeType.server_hello_done):
     882              if result in (0,1): yield result
     883              else: break
     884          serverHelloDone = result
     885
     886          #calculate Yc
     887          dh_p = serverKeyExchange.dh_p
     888          dh_g = serverKeyExchange.dh_g
     889          dh_Xc = bytesToNumber(getRandomBytes(32))
     890          dh_Ys = serverKeyExchange.dh_Ys
     891          dh_Yc = powMod(dh_g, dh_Xc, dh_p)
     892
     893          #Send ClientKeyExchange
     894          for result in self._sendMsg(\
     895                  ClientKeyExchange(cipherSuite, self.version).createDH(dh_Yc)):
     896              yield result
     897
     898          #Calculate premaster secret
     899          S = powMod(dh_Ys, dh_Xc, dh_p)
     900          premasterSecret = numberToByteArray(S)
     901
     902          yield (premasterSecret, None, None)
     903
     904 -    def _clientFinished(self, premasterSecret, clientRandom, serverRandom,
     905                          cipherSuite, cipherImplementations, nextProto):
     906
     907          masterSecret = calcMasterSecret(self.version, premasterSecret,
     908                              clientRandom, serverRandom)
     909          self._calcPendingStates(cipherSuite, masterSecret,
     910                                  clientRandom, serverRandom,
     911                                  cipherImplementations)
     912
     913          #Exchange ChangeCipherSpec and Finished messages
     914          for result in self._sendFinished(masterSecret, nextProto):
     915              yield result
     916          for result in self._getFinished(masterSecret, nextProto=nextProto):
     917              yield result
     918          yield masterSecret
     919
     920 -    def _clientGetKeyFromChain(self, certificate, settings, tackExt=None):
     921          #Get and check cert chain from the Certificate message
     922          certChain = certificate.certChain
     923          if not certChain or certChain.getNumCerts() == 0:
     924              for result in self._sendError(AlertDescription.illegal_parameter,
     925                      "Other party sent a Certificate message without "\
     926                      "certificates"):
     927                  yield result
     928
     929          #Get and check public key from the cert chain
     930          publicKey = certChain.getEndEntityPublicKey()
     931          if len(publicKey) < settings.minKeySize:
     932              for result in self._sendError(AlertDescription.handshake_failure,
     933                      "Other party's public key too small: %d" % len(publicKey)):
     934                  yield result
     935          if len(publicKey) > settings.maxKeySize:
     936              for result in self._sendError(AlertDescription.handshake_failure,
     937                      "Other party's public key too large: %d" % len(publicKey)):
     938                  yield result
     939
     940          # If there's no TLS Extension, look for a TACK cert
     941          if tackpyLoaded:
     942              if not tackExt:
     943                  tackExt = certChain.getTackExt()
     944
     945              # If there's a TACK (whether via TLS or TACK Cert), check that it
     946              # matches the cert chain
     947              if tackExt and tackExt.tacks:
     948                  for tack in tackExt.tacks:
     949                      if not certChain.checkTack(tack):
     950                          for result in self._sendError(
     951                                  AlertDescription.illegal_parameter,
     952                                  "Other party's TACK doesn't match their public key"):
     953                                  yield result
     954
     955          yield publicKey, certChain, tackExt
     956
     957
     958      #*********************************************************
     959      # Server Handshake Functions
     960      #*********************************************************
     961
     962
     963 -    def handshakeServer(self, verifierDB=None,
     964                          certChain=None, privateKey=None, reqCert=False,
     965                          sessionCache=None, settings=None, checker=None,
     966                          reqCAs = None,
     967                          tacks=None, activationFlags=0,
     968                          nextProtos=None, anon=False):
     969          """Perform a handshake in the role of server.
     970
     971          This function performs an SSL or TLS handshake.  Depending on
     972          the arguments and the behavior of the client, this function can
     973          perform an SRP, or certificate-based handshake.  It
     974          can also perform a combined SRP and server-certificate
     975          handshake.
     976
     977          Like any handshake function, this can be called on a closed
     978          TLS connection, or on a TLS connection that is already open.
     979          If called on an open connection it performs a re-handshake.
     980          This function does not send a Hello Request message before
     981          performing the handshake, so if re-handshaking is required,
     982          the server must signal the client to begin the re-handshake
     983          through some other means.
     984
     985          If the function completes without raising an exception, the
     986          TLS connection will be open and available for data transfer.
     987
     988          If an exception is raised, the connection will have been
     989          automatically closed (if it was ever open).
     990
     991          @type verifierDB: L{tlslite.verifierdb.VerifierDB}
     992          @param verifierDB: A database of SRP password verifiers
     993          associated with usernames.  If the client performs an SRP
     994          handshake, the session's srpUsername attribute will be set.
     995
     996          @type certChain: L{tlslite.x509certchain.X509CertChain}
     997          @param certChain: The certificate chain to be used if the
     998          client requests server certificate authentication.
     999
    1000          @type privateKey: L{tlslite.utils.rsakey.RSAKey}
    1001          @param privateKey: The private key to be used if the client
    1002          requests server certificate authentication.
    1003
    1004          @type reqCert: bool
    1005          @param reqCert: Whether to request client certificate
    1006          authentication.  This only applies if the client chooses server
    1007          certificate authentication; if the client chooses SRP
    1008          authentication, this will be ignored.  If the client
    1009          performs a client certificate authentication, the sessions's
    1010          clientCertChain attribute will be set.
    1011
    1012          @type sessionCache: L{tlslite.sessioncache.SessionCache}
    1013          @param sessionCache: An in-memory cache of resumable sessions.
    1014          The client can resume sessions from this cache.  Alternatively,
    1015          if the client performs a full handshake, a new session will be
    1016          added to the cache.
    1017
    1018          @type settings: L{tlslite.handshakesettings.HandshakeSettings}
    1019          @param settings: Various settings which can be used to control
    1020          the ciphersuites and SSL/TLS version chosen by the server.
    1021
    1022          @type checker: L{tlslite.checker.Checker}
    1023          @param checker: A Checker instance.  This instance will be
    1024          invoked to examine the other party's authentication
    1025          credentials, if the handshake completes succesfully.
    1026
    1027          @type reqCAs: list of L{bytearray} of unsigned bytes
    1028          @param reqCAs: A collection of DER-encoded DistinguishedNames that
    1029          will be sent along with a certificate request. This does not affect
    1030          verification.
    1031
    1032          @type nextProtos: list of strings.
    1033          @param nextProtos: A list of upper layer protocols to expose to the
    1034          clients through the Next-Protocol Negotiation Extension,
    1035          if they support it.
    1036
    1037          @raise socket.error: If a socket error occurs.
    1038          @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
    1039          without a preceding alert.
    1040          @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
    1041          @raise tlslite.errors.TLSAuthenticationError: If the checker
    1042          doesn't like the other party's authentication credentials.
    1043          """
    1044          for result in self.handshakeServerAsync(verifierDB,
    1045                  certChain, privateKey, reqCert, sessionCache, settings,
    1046                  checker, reqCAs,
    1047                  tacks=tacks, activationFlags=activationFlags,
    1048                  nextProtos=nextProtos, anon=anon):
    1049              pass
    1050
    1051
    1052 -    def handshakeServerAsync(self, verifierDB=None,
    1053                               certChain=None, privateKey=None, reqCert=False,
    1054                               sessionCache=None, settings=None, checker=None,
    1055                               reqCAs=None,
    1056                               tacks=None, activationFlags=0,
    1057                               nextProtos=None, anon=False
    1058                               ):
    1059          """Start a server handshake operation on the TLS connection.
    1060
    1061          This function returns a generator which behaves similarly to
    1062          handshakeServer().  Successive invocations of the generator
    1063          will return 0 if it is waiting to read from the socket, 1 if it is
    1064          waiting to write to the socket, or it will raise StopIteration
    1065          if the handshake operation is complete.
    1066
    1067          @rtype: iterable
    1068          @return: A generator; see above for details.
    1069          """
    1070          handshaker = self._handshakeServerAsyncHelper(\
    1071              verifierDB=verifierDB, certChain=certChain,
    1072              privateKey=privateKey, reqCert=reqCert,
    1073              sessionCache=sessionCache, settings=settings,
    1074              reqCAs=reqCAs,
    1075              tacks=tacks, activationFlags=activationFlags,
    1076              nextProtos=nextProtos, anon=anon)
    1077          for result in self._handshakeWrapperAsync(handshaker, checker):
    1078              yield result
    1079
    1080
    1081 -    def _handshakeServerAsyncHelper(self, verifierDB,
    1082                               certChain, privateKey, reqCert, sessionCache,
    1083                               settings, reqCAs,
    1084                               tacks, activationFlags,
    1085                               nextProtos, anon):
    1086
    1087          self._handshakeStart(client=False)
    1088
    1089          if (not verifierDB) and (not certChain) and not anon:
    1090              raise ValueError("Caller passed no authentication credentials")
    1091          if certChain and not privateKey:
    1092              raise ValueError("Caller passed a certChain but no privateKey")
    1093          if privateKey and not certChain:
    1094              raise ValueError("Caller passed a privateKey but no certChain")
    1095          if reqCAs and not reqCert:
    1096              raise ValueError("Caller passed reqCAs but not reqCert")
    1097          if certChain and not isinstance(certChain, X509CertChain):
    1098              raise ValueError("Unrecognized certificate type")
    1099          if activationFlags and not tacks:
    1100              raise ValueError("Nonzero activationFlags requires tacks")
    1101          if tacks:
    1102              if not tackpyLoaded:
    1103                  raise ValueError("tackpy is not loaded")
    1104              if not settings or not settings.useExperimentalTackExtension:
    1105                  raise ValueError("useExperimentalTackExtension not enabled")
    1106
    1107          if not settings:
    1108              settings = HandshakeSettings()
    1109          settings = settings._filter()
    1110
    1111          # OK Start exchanging messages
    1112          # ******************************
    1113
    1114          # Handle ClientHello and resumption
    1115          for result in self._serverGetClientHello(settings, certChain,\
    1116                                              verifierDB, sessionCache,
    1117                                              anon):
    1118              if result in (0,1): yield result
    1119              elif result == None:
    1120                  self._handshakeDone(resumed=True)
    1121                  return # Handshake was resumed, we're done
    1122              else: break
    1123          (clientHello, cipherSuite) = result
    1124
    1125          #If not a resumption...
    1126
    1127          # Create the ServerHello message
    1128          if sessionCache:
    1129              sessionID = getRandomBytes(32)
    1130          else:
    1131              sessionID = bytearray(0)
    1132
    1133          if not clientHello.supports_npn:
    1134              nextProtos = None
    1135
    1136          # If not doing a certificate-based suite, discard the TACK
    1137          if not cipherSuite in CipherSuite.certAllSuites:
    1138              tacks = None
    1139
    1140          # Prepare a TACK Extension if requested
    1141          if clientHello.tack:
    1142              tackExt = TackExtension.create(tacks, activationFlags)
    1143          else:
    1144              tackExt = None
    1145          serverHello = ServerHello()
    1146          serverHello.create(self.version, getRandomBytes(32), sessionID, \
    1147                              cipherSuite, CertificateType.x509, tackExt,
    1148                              nextProtos)
    1149
    1150          # Perform the SRP key exchange
    1151          clientCertChain = None
    1152          if cipherSuite in CipherSuite.srpAllSuites:
    1153              for result in self._serverSRPKeyExchange(clientHello, serverHello,
    1154                                      verifierDB, cipherSuite,
    1155                                      privateKey, certChain):
    1156                  if result in (0,1): yield result
    1157                  else: break
    1158              premasterSecret = result
    1159
    1160          # Perform the RSA key exchange
    1161          elif cipherSuite in CipherSuite.certSuites:
    1162              for result in self._serverCertKeyExchange(clientHello, serverHello,
    1163                                          certChain, privateKey,
    1164                                          reqCert, reqCAs, cipherSuite,
    1165                                          settings):
    1166                  if result in (0,1): yield result
    1167                  else: break
    1168              (premasterSecret, clientCertChain) = result
    1169
    1170          # Perform anonymous Diffie Hellman key exchange
    1171          elif cipherSuite in CipherSuite.anonSuites:
    1172              for result in self._serverAnonKeyExchange(clientHello, serverHello,
    1173                                          cipherSuite, settings):
    1174                  if result in (0,1): yield result
    1175                  else: break
    1176              premasterSecret = result
    1177
    1178          else:
    1179              assert(False)
    1180
    1181          # Exchange Finished messages
    1182          for result in self._serverFinished(premasterSecret,
    1183                                  clientHello.random, serverHello.random,
    1184                                  cipherSuite, settings.cipherImplementations,
    1185                                  nextProtos):
    1186                  if result in (0,1): yield result
    1187                  else: break
    1188          masterSecret = result
    1189
    1190          #Create the session object
    1191          self.session = Session()
    1192          if cipherSuite in CipherSuite.certAllSuites:
    1193              serverCertChain = certChain
    1194          else:
    1195              serverCertChain = None
    1196          srpUsername = None
    1197          serverName = None
    1198          if clientHello.srp_username:
    1199              srpUsername = clientHello.srp_username.decode("utf-8")
    1200          if clientHello.server_name:
    1201              serverName = clientHello.server_name.decode("utf-8")
    1202          self.session.create(masterSecret, serverHello.session_id, cipherSuite,
    1203              srpUsername, clientCertChain, serverCertChain,
    1204              tackExt, serverHello.tackExt!=None, serverName)
    1205
    1206          #Add the session object to the session cache
    1207          if sessionCache and sessionID:
    1208              sessionCache[sessionID] = self.session
    1209
    1210          self._handshakeDone(resumed=False)
    1211
    1212
    1213 -    def _serverGetClientHello(self, settings, certChain, verifierDB,
    1214                                  sessionCache, anon):
    1215          #Initialize acceptable cipher suites
    1216          cipherSuites = []
    1217          if verifierDB:
    1218              if certChain:
    1219                  cipherSuites += \
    1220                      CipherSuite.getSrpCertSuites(settings)
    1221              cipherSuites += CipherSuite.getSrpSuites(settings)
    1222          elif certChain:
    1223              cipherSuites += CipherSuite.getCertSuites(settings)
    1224          elif anon:
    1225              cipherSuites += CipherSuite.getAnonSuites(settings)
    1226          else:
    1227              assert(False)
    1228
    1229          #Tentatively set version to most-desirable version, so if an error
    1230          #occurs parsing the ClientHello, this is what we'll use for the
    1231          #error alert
    1232          self.version = settings.maxVersion
    1233
    1234          #Get ClientHello
    1235          for result in self._getMsg(ContentType.handshake,
    1236                                     HandshakeType.client_hello):
    1237              if result in (0,1): yield result
    1238              else: break
    1239          clientHello = result
    1240
    1241          #If client's version is too low, reject it
    1242          if clientHello.client_version < settings.minVersion:
    1243              self.version = settings.minVersion
    1244              for result in self._sendError(\
    1245                    AlertDescription.protocol_version,
    1246                    "Too old version: %s" % str(clientHello.client_version)):
    1247                  yield result
    1248
    1249          #If client's version is too high, propose my highest version
    1250          elif clientHello.client_version > settings.maxVersion:
    1251              self.version = settings.maxVersion
    1252
    1253          else:
    1254              #Set the version to the client's version
    1255              self.version = clientHello.client_version
    1256
    1257          #If resumption was requested and we have a session cache...
    1258          if clientHello.session_id and sessionCache:
    1259              session = None
    1260
    1261              #Check in the session cache
    1262              if sessionCache and not session:
    1263                  try:
    1264                      session = sessionCache[clientHello.session_id]
    1265                      if not session.resumable:
    1266                          raise AssertionError()
    1267                      #Check for consistency with ClientHello
    1268                      if session.cipherSuite not in cipherSuites:
    1269                          for result in self._sendError(\
    1270                                  AlertDescription.handshake_failure):
    1271                              yield result
    1272                      if session.cipherSuite not in clientHello.cipher_suites:
    1273                          for result in self._sendError(\
    1274                                  AlertDescription.handshake_failure):
    1275                              yield result
    1276                      if clientHello.srp_username:
    1277                          if not session.srpUsername or \
    1278                              clientHello.srp_username != bytearray(session.srpUsername, "utf-8"):
    1279                              for result in self._sendError(\
    1280                                      AlertDescription.handshake_failure):
    1281                                  yield result
    1282                      if clientHello.server_name:
    1283                          if not session.serverName or \
    1284                              clientHello.server_name != bytearray(session.serverName, "utf-8"):
    1285                              for result in self._sendError(\
    1286                                      AlertDescription.handshake_failure):
    1287                                  yield result
    1288                  except KeyError:
    1289                      pass
    1290
    1291              #If a session is found..
    1292              if session:
    1293                  #Send ServerHello
    1294                  serverHello = ServerHello()
    1295                  serverHello.create(self.version, getRandomBytes(32),
    1296                                     session.sessionID, session.cipherSuite,
    1297                                     CertificateType.x509, None, None)
    1298                  for result in self._sendMsg(serverHello):
    1299                      yield result
    1300
    1301                  #From here on, the client's messages must have right version
    1302                  self._versionCheck = True
    1303
    1304                  #Calculate pending connection states
    1305                  self._calcPendingStates(session.cipherSuite,
    1306                                          session.masterSecret,
    1307                                          clientHello.random,
    1308                                          serverHello.random,
    1309                                          settings.cipherImplementations)
    1310
    1311                  #Exchange ChangeCipherSpec and Finished messages
    1312                  for result in self._sendFinished(session.masterSecret):
    1313                      yield result
    1314                  for result in self._getFinished(session.masterSecret):
    1315                      yield result
    1316
    1317                  #Set the session
    1318                  self.session = session
    1319
    1320                  yield None # Handshake done!
    1321
    1322          #Calculate the first cipher suite intersection.
    1323          #This is the 'privileged' ciphersuite.  We'll use it if we're
    1324          #doing a new negotiation.  In fact,
    1325          #the only time we won't use it is if we're resuming a
    1326          #session, in which case we use the ciphersuite from the session.
    1327          #
    1328          #Given the current ciphersuite ordering, this means we prefer SRP
    1329          #over non-SRP.
    1330          for cipherSuite in cipherSuites:
    1331              if cipherSuite in clientHello.cipher_suites:
    1332                  break
    1333          else:
    1334              for result in self._sendError(\
    1335                      AlertDescription.handshake_failure,
    1336                      "No mutual ciphersuite"):
    1337                  yield result
    1338          if cipherSuite in CipherSuite.srpAllSuites and \
    1339                              not clientHello.srp_username:
    1340              for result in self._sendError(\
    1341                      AlertDescription.unknown_psk_identity,
    1342                      "Client sent a hello, but without the SRP username"):
    1343                  yield result
    1344
    1345          #If an RSA suite is chosen, check for certificate type intersection
    1346          if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \
    1347                                  not in clientHello.certificate_types:
    1348              for result in self._sendError(\
    1349                      AlertDescription.handshake_failure,
    1350                      "the client doesn't support my certificate type"):
    1351                  yield result
    1352
    1353          # If resumption was not requested, or
    1354          # we have no session cache, or
    1355          # the client's session_id was not found in cache:
    1356          yield (clientHello, cipherSuite)
    1357
    1358 -    def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB,
    1359                                  cipherSuite, privateKey, serverCertChain):
    1360
    1361          srpUsername = clientHello.srp_username.decode("utf-8")
    1362          self.allegedSrpUsername = srpUsername
    1363          #Get parameters from username
    1364          try:
    1365              entry = verifierDB[srpUsername]
    1366          except KeyError:
    1367              for result in self._sendError(\
    1368                      AlertDescription.unknown_psk_identity):
    1369                  yield result
    1370          (N, g, s, v) = entry
    1371
    1372          #Calculate server's ephemeral DH values (b, B)
    1373          b = bytesToNumber(getRandomBytes(32))
    1374          k = makeK(N, g)
    1375          B = (powMod(g, b, N) + (k*v)) % N
    1376
    1377          #Create ServerKeyExchange, signing it if necessary
    1378          serverKeyExchange = ServerKeyExchange(cipherSuite)
    1379          serverKeyExchange.createSRP(N, g, s, B)
    1380          if cipherSuite in CipherSuite.srpCertSuites:
    1381              hashBytes = serverKeyExchange.hash(clientHello.random,
    1382                                                 serverHello.random)
    1383              serverKeyExchange.signature = privateKey.sign(hashBytes)
    1384
    1385          #Send ServerHello[, Certificate], ServerKeyExchange,
    1386          #ServerHelloDone
    1387          msgs = []
    1388          msgs.append(serverHello)
    1389          if cipherSuite in CipherSuite.srpCertSuites:
    1390              certificateMsg = Certificate(CertificateType.x509)
    1391              certificateMsg.create(serverCertChain)
    1392              msgs.append(certificateMsg)
    1393          msgs.append(serverKeyExchange)
    1394          msgs.append(ServerHelloDone())
    1395          for result in self._sendMsgs(msgs):
    1396              yield result
    1397
    1398          #From here on, the client's messages must have the right version
    1399          self._versionCheck = True
    1400
    1401          #Get and check ClientKeyExchange
    1402          for result in self._getMsg(ContentType.handshake,
    1403                                    HandshakeType.client_key_exchange,
    1404                                    cipherSuite):
    1405              if result in (0,1): yield result
    1406              else: break
    1407          clientKeyExchange = result
    1408          A = clientKeyExchange.srp_A
    1409          if A % N == 0:
    1410              for result in self._sendError(AlertDescription.illegal_parameter,
    1411                      "Suspicious A value"):
    1412                  yield result
    1413              assert(False) # Just to ensure we don't fall through somehow
    1414
    1415          #Calculate u
    1416          u = makeU(N, A, B)
    1417
    1418          #Calculate premaster secret
    1419          S = powMod((A * powMod(v,u,N)) % N, b, N)
    1420          premasterSecret = numberToByteArray(S)
    1421
    1422          yield premasterSecret
    1423
    1424
    1425 -    def _serverCertKeyExchange(self, clientHello, serverHello,
    1426                                  serverCertChain, privateKey,
    1427                                  reqCert, reqCAs, cipherSuite,
    1428                                  settings):
    1429          #Send ServerHello, Certificate[, CertificateRequest],
    1430          #ServerHelloDone
    1431          msgs = []
    1432
    1433          # If we verify a client cert chain, return it
    1434          clientCertChain = None
    1435
    1436          msgs.append(serverHello)
    1437          msgs.append(Certificate(CertificateType.x509).create(serverCertChain))
    1438          if reqCert and reqCAs:
    1439              msgs.append(CertificateRequest().create(\
    1440                  [ClientCertificateType.rsa_sign], reqCAs))
    1441          elif reqCert:
    1442              msgs.append(CertificateRequest())
    1443          msgs.append(ServerHelloDone())
    1444          for result in self._sendMsgs(msgs):
    1445              yield result
    1446
    1447          #From here on, the client's messages must have the right version
    1448          self._versionCheck = True
    1449
    1450          #Get [Certificate,] (if was requested)
    1451          if reqCert:
    1452              if self.version == (3,0):
    1453                  for result in self._getMsg((ContentType.handshake,
    1454                                             ContentType.alert),
    1455                                             HandshakeType.certificate,
    1456                                             CertificateType.x509):
    1457                      if result in (0,1): yield result
    1458                      else: break
    1459                  msg = result
    1460
    1461                  if isinstance(msg, Alert):
    1462                      #If it's not a no_certificate alert, re-raise
    1463                      alert = msg
    1464                      if alert.description != \
    1465                              AlertDescription.no_certificate:
    1466                          self._shutdown(False)
    1467                          raise TLSRemoteAlert(alert)
    1468                  elif isinstance(msg, Certificate):
    1469                      clientCertificate = msg
    1470                      if clientCertificate.certChain and \
    1471                              clientCertificate.certChain.getNumCerts()!=0:
    1472                          clientCertChain = clientCertificate.certChain
    1473                  else:
    1474                      raise AssertionError()
    1475              elif self.version in ((3,1), (3,2)):
    1476                  for result in self._getMsg(ContentType.handshake,
    1477                                            HandshakeType.certificate,
    1478                                            CertificateType.x509):
    1479                      if result in (0,1): yield result
    1480                      else: break
    1481                  clientCertificate = result
    1482                  if clientCertificate.certChain and \
    1483                          clientCertificate.certChain.getNumCerts()!=0:
    1484                      clientCertChain = clientCertificate.certChain
    1485              else:
    1486                  raise AssertionError()
    1487
    1488          #Get ClientKeyExchange
    1489          for result in self._getMsg(ContentType.handshake,
    1490                                    HandshakeType.client_key_exchange,
    1491                                    cipherSuite):
    1492              if result in (0,1): yield result
    1493              else: break
    1494          clientKeyExchange = result
    1495
    1496          #Decrypt ClientKeyExchange
    1497          premasterSecret = privateKey.decrypt(\
    1498              clientKeyExchange.encryptedPreMasterSecret)
    1499
    1500          # On decryption failure randomize premaster secret to avoid
    1501          # Bleichenbacher's "million message" attack
    1502          randomPreMasterSecret = getRandomBytes(48)
    1503          versionCheck = (premasterSecret[0], premasterSecret[1])
    1504          if not premasterSecret:
    1505              premasterSecret = randomPreMasterSecret
    1506          elif len(premasterSecret)!=48:
    1507              premasterSecret = randomPreMasterSecret
    1508          elif versionCheck != clientHello.client_version:
    1509              if versionCheck != self.version: #Tolerate buggy IE clients
    1510                  premasterSecret = randomPreMasterSecret
    1511
    1512          #Get and check CertificateVerify, if relevant
    1513          if clientCertChain:
    1514              if self.version == (3,0):
    1515                  masterSecret = calcMasterSecret(self.version, premasterSecret,
    1516                                           clientHello.random, serverHello.random)
    1517                  verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"")
    1518              elif self.version in ((3,1), (3,2)):
    1519                  verifyBytes = self._handshake_md5.digest() + \
    1520                                  self._handshake_sha.digest()
    1521              for result in self._getMsg(ContentType.handshake,
    1522                                        HandshakeType.certificate_verify):
    1523                  if result in (0,1): yield result
    1524                  else: break
    1525              certificateVerify = result
    1526              publicKey = clientCertChain.getEndEntityPublicKey()
    1527              if len(publicKey) < settings.minKeySize:
    1528                  for result in self._sendError(\
    1529                          AlertDescription.handshake_failure,
    1530                          "Client's public key too small: %d" % len(publicKey)):
    1531                      yield result
    1532
    1533              if len(publicKey) > settings.maxKeySize:
    1534                  for result in self._sendError(\
    1535                          AlertDescription.handshake_failure,
    1536                          "Client's public key too large: %d" % len(publicKey)):
    1537                      yield result
    1538
    1539              if not publicKey.verify(certificateVerify.signature, verifyBytes):
    1540                  for result in self._sendError(\
    1541                          AlertDescription.decrypt_error,
    1542                          "Signature failed to verify"):
    1543                      yield result
    1544          yield (premasterSecret, clientCertChain)
    1545
    1546
    1547 -    def _serverAnonKeyExchange(self, clientHello, serverHello, cipherSuite,
    1548                                 settings):
    1549          # Calculate DH p, g, Xs, Ys
    1550          dh_p = getRandomSafePrime(32, False)
    1551          dh_g = getRandomNumber(2, dh_p)
    1552          dh_Xs = bytesToNumber(getRandomBytes(32))
    1553          dh_Ys = powMod(dh_g, dh_Xs, dh_p)
    1554
    1555          #Create ServerKeyExchange
    1556          serverKeyExchange = ServerKeyExchange(cipherSuite)
    1557          serverKeyExchange.createDH(dh_p, dh_g, dh_Ys)
    1558
    1559          #Send ServerHello[, Certificate], ServerKeyExchange,
    1560          #ServerHelloDone
    1561          msgs = []
    1562          msgs.append(serverHello)
    1563          msgs.append(serverKeyExchange)
    1564          msgs.append(ServerHelloDone())
    1565          for result in self._sendMsgs(msgs):
    1566              yield result
    1567
    1568          #From here on, the client's messages must have the right version
    1569          self._versionCheck = True
    1570
    1571          #Get and check ClientKeyExchange
    1572          for result in self._getMsg(ContentType.handshake,
    1573                                     HandshakeType.client_key_exchange,
    1574                                     cipherSuite):
    1575              if result in (0,1):
    1576                  yield result
    1577              else:
    1578                  break
    1579          clientKeyExchange = result
    1580          dh_Yc = clientKeyExchange.dh_Yc
    1581
    1582          if dh_Yc % dh_p == 0:
    1583              for result in self._sendError(AlertDescription.illegal_parameter,
    1584                      "Suspicious dh_Yc value"):
    1585                  yield result
    1586              assert(False) # Just to ensure we don't fall through somehow
    1587
    1588          #Calculate premaster secre
    1589          S = powMod(dh_Yc,dh_Xs,dh_p)
    1590          premasterSecret = numberToByteArray(S)
    1591
    1592          yield premasterSecret
    1593
    1594
    1595 -    def _serverFinished(self,  premasterSecret, clientRandom, serverRandom,
    1596                          cipherSuite, cipherImplementations, nextProtos):
    1597          masterSecret = calcMasterSecret(self.version, premasterSecret,
    1598                                        clientRandom, serverRandom)
    1599
    1600          #Calculate pending connection states
    1601          self._calcPendingStates(cipherSuite, masterSecret,
    1602                                  clientRandom, serverRandom,
    1603                                  cipherImplementations)
    1604
    1605          #Exchange ChangeCipherSpec and Finished messages
    1606          for result in self._getFinished(masterSecret,
    1607                          expect_next_protocol=nextProtos is not None):
    1608              yield result
    1609
    1610          for result in self._sendFinished(masterSecret):
    1611              yield result
    1612
    1613          yield masterSecret
    1614
    1615
    1616      #*********************************************************
    1617      # Shared Handshake Functions
    1618      #*********************************************************
    1619
    1620
    1621 -    def _sendFinished(self, masterSecret, nextProto=None):
    1622          #Send ChangeCipherSpec
    1623          for result in self._sendMsg(ChangeCipherSpec()):
    1624              yield result
    1625
    1626          #Switch to pending write state
    1627          self._changeWriteState()
    1628
    1629          if nextProto is not None:
    1630              nextProtoMsg = NextProtocol().create(nextProto)
    1631              for result in self._sendMsg(nextProtoMsg):
    1632                  yield result
    1633
    1634          #Calculate verification data
    1635          verifyData = self._calcFinished(masterSecret, True)
    1636          if self.fault == Fault.badFinished:
    1637              verifyData[0] = (verifyData[0]+1)%256
    1638
    1639          #Send Finished message under new state
    1640          finished = Finished(self.version).create(verifyData)
    1641          for result in self._sendMsg(finished):
    1642              yield result
    1643
    1644 -    def _getFinished(self, masterSecret, expect_next_protocol=False, nextProto=None):
    1645          #Get and check ChangeCipherSpec
    1646          for result in self._getMsg(ContentType.change_cipher_spec):
    1647              if result in (0,1):
    1648                  yield result
    1649          changeCipherSpec = result
    1650
    1651          if changeCipherSpec.type != 1:
    1652              for result in self._sendError(AlertDescription.illegal_parameter,
    1653                                           "ChangeCipherSpec type incorrect"):
    1654                  yield result
    1655
    1656          #Switch to pending read state
    1657          self._changeReadState()
    1658
    1659          #Server Finish - Are we waiting for a next protocol echo?
    1660          if expect_next_protocol:
    1661              for result in self._getMsg(ContentType.handshake, HandshakeType.next_protocol):
    1662                  if result in (0,1):
    1663                      yield result
    1664              if result is None:
    1665                  for result in self._sendError(AlertDescription.unexpected_message,
    1666                                               "Didn't get NextProtocol message"):
    1667                      yield result
    1668
    1669              self.next_proto = result.next_proto
    1670          else:
    1671              self.next_proto = None
    1672
    1673          #Client Finish - Only set the next_protocol selected in the connection
    1674          if nextProto:
    1675              self.next_proto = nextProto
    1676
    1677          #Calculate verification data
    1678          verifyData = self._calcFinished(masterSecret, False)
    1679
    1680          #Get and check Finished message under new state
    1681          for result in self._getMsg(ContentType.handshake,
    1682                                    HandshakeType.finished):
    1683              if result in (0,1):
    1684                  yield result
    1685          finished = result
    1686          if finished.verify_data != verifyData:
    1687              for result in self._sendError(AlertDescription.decrypt_error,
    1688                                           "Finished message is incorrect"):
    1689                  yield result
    1690
    1691 -    def _calcFinished(self, masterSecret, send=True):
    1692          if self.version == (3,0):
    1693              if (self._client and send) or (not self._client and not send):
    1694                  senderStr = b"\x43\x4C\x4E\x54"
    1695              else:
    1696                  senderStr = b"\x53\x52\x56\x52"
    1697
    1698              verifyData = self._calcSSLHandshakeHash(masterSecret, senderStr)
    1699              return verifyData
    1700
    1701          elif self.version in ((3,1), (3,2)):
    1702              if (self._client and send) or (not self._client and not send):
    1703                  label = b"client finished"
    1704              else:
    1705                  label = b"server finished"
    1706
    1707              handshakeHashes = self._handshake_md5.digest() + \
    1708                                  self._handshake_sha.digest()
    1709              verifyData = PRF(masterSecret, label, handshakeHashes, 12)
    1710              return verifyData
    1711          else:
    1712              raise AssertionError()
    1713
    1714
    1715 -    def _handshakeWrapperAsync(self, handshaker, checker):
    1716          if not self.fault:
    1717              try:
    1718                  for result in handshaker:
    1719                      yield result
    1720                  if checker:
    1721                      try:
    1722                          checker(self)
    1723                      except TLSAuthenticationError:
    1724                          alert = Alert().create(AlertDescription.close_notify,
    1725                                                 AlertLevel.fatal)
    1726                          for result in self._sendMsg(alert):
    1727                              yield result
    1728                          raise
    1729              except GeneratorExit:
    1730                  raise
    1731              except TLSAlert as alert:
    1732                  if not self.fault:
    1733                      raise
    1734                  if alert.description not in Fault.faultAlerts[self.fault]:
    1735                      raise TLSFaultError(str(alert))
    1736                  else:
    1737                      pass
    1738              except:
    1739                  self._shutdown(False)
    1740                  raise
    1741