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