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