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