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