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