Package tlslite :: Module tlsconnection
[hide private]
[frames] | no frames]

Source Code for Module tlslite.tlsconnection

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