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