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 # Sanity check the ALPN extension 1456 alpnExt = clientHello.getExtension(ExtensionType.alpn) 1457 if alpnExt: 1458 for protocolName in alpnExt.protocol_names: 1459 if not protocolName: 1460 for result in self._sendError( 1461 AlertDescription.illegal_parameter, 1462 "Client sent empty name in ALPN extension"): 1463 yield result 1464 1465 #If client's version is too high, propose my highest version 1466 elif clientHello.client_version > settings.maxVersion: 1467 self.version = settings.maxVersion 1468 1469 else: 1470 #Set the version to the client's version 1471 self.version = clientHello.client_version 1472 1473 #Detect if the client performed an inappropriate fallback. 1474 if clientHello.client_version < settings.maxVersion and \ 1475 CipherSuite.TLS_FALLBACK_SCSV in clientHello.cipher_suites: 1476 for result in self._sendError(\ 1477 AlertDescription.inappropriate_fallback): 1478 yield result 1479 1480 #Check if there's intersection between supported curves by client and 1481 #server 1482 client_groups = clientHello.getExtension(ExtensionType.supported_groups) 1483 group_intersect = [] 1484 if client_groups is not None: 1485 client_groups = client_groups.groups 1486 if client_groups is None: 1487 client_groups = [] 1488 server_groups = self._curveNamesToList(settings) 1489 group_intersect = [x for x in client_groups if x in server_groups] 1490 1491 #Now that the version is known, limit to only the ciphers available to 1492 #that version and client capabilities. 1493 cipherSuites = [] 1494 if verifierDB: 1495 if certChain: 1496 cipherSuites += \ 1497 CipherSuite.getSrpCertSuites(settings, self.version) 1498 cipherSuites += CipherSuite.getSrpSuites(settings, self.version) 1499 elif certChain: 1500 if group_intersect: 1501 cipherSuites += CipherSuite.getEcdheCertSuites(settings, 1502 self.version) 1503 cipherSuites += CipherSuite.getDheCertSuites(settings, self.version) 1504 cipherSuites += CipherSuite.getCertSuites(settings, self.version) 1505 elif anon: 1506 cipherSuites += CipherSuite.getAnonSuites(settings, self.version) 1507 cipherSuites += CipherSuite.getEcdhAnonSuites(settings, 1508 self.version) 1509 else: 1510 assert(False) 1511 cipherSuites = CipherSuite.filterForVersion(cipherSuites, 1512 minVersion=self.version, 1513 maxVersion=self.version) 1514 #If resumption was requested and we have a session cache... 1515 if clientHello.session_id and sessionCache: 1516 session = None 1517 1518 #Check in the session cache 1519 if sessionCache and not session: 1520 try: 1521 session = sessionCache[clientHello.session_id] 1522 if not session.resumable: 1523 raise AssertionError() 1524 #Check for consistency with ClientHello 1525 if session.cipherSuite not in cipherSuites: 1526 for result in self._sendError(\ 1527 AlertDescription.handshake_failure): 1528 yield result 1529 if session.cipherSuite not in clientHello.cipher_suites: 1530 for result in self._sendError(\ 1531 AlertDescription.handshake_failure): 1532 yield result 1533 if clientHello.srp_username: 1534 if not session.srpUsername or \ 1535 clientHello.srp_username != bytearray(session.srpUsername, "utf-8"): 1536 for result in self._sendError(\ 1537 AlertDescription.handshake_failure): 1538 yield result 1539 if clientHello.server_name: 1540 if not session.serverName or \ 1541 clientHello.server_name != bytearray(session.serverName, "utf-8"): 1542 for result in self._sendError(\ 1543 AlertDescription.handshake_failure): 1544 yield result 1545 if session.encryptThenMAC and \ 1546 not clientHello.getExtension( 1547 ExtensionType.encrypt_then_mac): 1548 for result in self._sendError(\ 1549 AlertDescription.handshake_failure): 1550 yield result 1551 if session.extendedMasterSecret and \ 1552 not clientHello.getExtension( 1553 ExtensionType.extended_master_secret): 1554 for result in self._sendError(\ 1555 AlertDescription.handshake_failure): 1556 yield result 1557 except KeyError: 1558 pass 1559 1560 #If a session is found.. 1561 if session: 1562 #Send ServerHello 1563 extensions = [] 1564 if session.encryptThenMAC: 1565 self._recordLayer.encryptThenMAC = True 1566 mte = TLSExtension().create(ExtensionType.encrypt_then_mac, 1567 bytearray(0)) 1568 extensions.append(mte) 1569 if session.extendedMasterSecret: 1570 ems = TLSExtension().create(ExtensionType. 1571 extended_master_secret, 1572 bytearray(0)) 1573 extensions.append(ems) 1574 secureRenego = False 1575 renegoExt = clientHello.\ 1576 getExtension(ExtensionType.renegotiation_info) 1577 if renegoExt: 1578 if renegoExt.renegotiated_connection: 1579 for result in self._sendError( 1580 AlertDescription.handshake_failure): 1581 yield result 1582 secureRenego = True 1583 elif CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV in \ 1584 clientHello.cipher_suites: 1585 secureRenego = True 1586 if secureRenego: 1587 extensions.append(RenegotiationInfoExtension() 1588 .create(bytearray(0))) 1589 selectedALPN = None 1590 if alpn: 1591 alpnExt = clientHello.getExtension(ExtensionType.alpn) 1592 if alpnExt: 1593 for protocolName in alpnExt.protocol_names: 1594 if protocolName in alpn: 1595 ext = ALPNExtension().create([protocolName]) 1596 extensions.append(ext) 1597 selectedALPN = protocolName 1598 break 1599 else: 1600 for result in self._sendError( 1601 AlertDescription.no_application_protocol, 1602 "No commonly supported application layer" 1603 "protocol supported"): 1604 yield result 1605 1606 # don't send empty extensions 1607 if not extensions: 1608 extensions = None 1609 serverHello = ServerHello() 1610 serverHello.create(self.version, getRandomBytes(32), 1611 session.sessionID, session.cipherSuite, 1612 CertificateType.x509, None, None, 1613 extensions=extensions) 1614 for result in self._sendMsg(serverHello): 1615 yield result 1616 1617 #Calculate pending connection states 1618 self._calcPendingStates(session.cipherSuite, 1619 session.masterSecret, 1620 clientHello.random, 1621 serverHello.random, 1622 settings.cipherImplementations) 1623 1624 #Exchange ChangeCipherSpec and Finished messages 1625 for result in self._sendFinished(session.masterSecret, 1626 session.cipherSuite): 1627 yield result 1628 for result in self._getFinished(session.masterSecret, 1629 session.cipherSuite): 1630 yield result 1631 1632 #Set the session 1633 self.session = session 1634 self._clientRandom = clientHello.random 1635 self._serverRandom = serverHello.random 1636 self.session.appProto = selectedALPN 1637 yield None # Handshake done! 1638 1639 #Calculate the first cipher suite intersection. 1640 #This is the 'privileged' ciphersuite. We'll use it if we're 1641 #doing a new negotiation. In fact, 1642 #the only time we won't use it is if we're resuming a 1643 #session, in which case we use the ciphersuite from the session. 1644 # 1645 #Given the current ciphersuite ordering, this means we prefer SRP 1646 #over non-SRP. 1647 for cipherSuite in cipherSuites: 1648 if cipherSuite in clientHello.cipher_suites: 1649 break 1650 else: 1651 for result in self._sendError(\ 1652 AlertDescription.handshake_failure, 1653 "No mutual ciphersuite"): 1654 yield result 1655 if cipherSuite in CipherSuite.srpAllSuites and \ 1656 not clientHello.srp_username: 1657 for result in self._sendError(\ 1658 AlertDescription.unknown_psk_identity, 1659 "Client sent a hello, but without the SRP username"): 1660 yield result 1661 1662 #If an RSA suite is chosen, check for certificate type intersection 1663 if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \ 1664 not in clientHello.certificate_types: 1665 for result in self._sendError(\ 1666 AlertDescription.handshake_failure, 1667 "the client doesn't support my certificate type"): 1668 yield result 1669 1670 # If resumption was not requested, or 1671 # we have no session cache, or 1672 # the client's session_id was not found in cache: 1673 yield (clientHello, cipherSuite)
1674
1675 - def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB, 1676 cipherSuite, privateKey, serverCertChain, 1677 settings):
1678 """Perform the server side of SRP key exchange""" 1679 keyExchange = SRPKeyExchange(cipherSuite, 1680 clientHello, 1681 serverHello, 1682 privateKey, 1683 verifierDB) 1684 1685 sigHash = self._pickServerKeyExchangeSig(settings, clientHello) 1686 1687 #Create ServerKeyExchange, signing it if necessary 1688 try: 1689 serverKeyExchange = keyExchange.makeServerKeyExchange(sigHash) 1690 except TLSUnknownPSKIdentity: 1691 for result in self._sendError(\ 1692 AlertDescription.unknown_psk_identity): 1693 yield result 1694 1695 #Send ServerHello[, Certificate], ServerKeyExchange, 1696 #ServerHelloDone 1697 msgs = [] 1698 msgs.append(serverHello) 1699 if cipherSuite in CipherSuite.srpCertSuites: 1700 certificateMsg = Certificate(CertificateType.x509) 1701 certificateMsg.create(serverCertChain) 1702 msgs.append(certificateMsg) 1703 msgs.append(serverKeyExchange) 1704 msgs.append(ServerHelloDone()) 1705 for result in self._sendMsgs(msgs): 1706 yield result 1707 1708 #Get and check ClientKeyExchange 1709 for result in self._getMsg(ContentType.handshake, 1710 HandshakeType.client_key_exchange, 1711 cipherSuite): 1712 if result in (0,1): yield result 1713 else: break 1714 try: 1715 premasterSecret = keyExchange.processClientKeyExchange(result) 1716 except TLSIllegalParameterException: 1717 for result in self._sendError(AlertDescription.illegal_parameter, 1718 "Suspicious A value"): 1719 yield result 1720 1721 yield premasterSecret
1722
1723 - def _serverCertKeyExchange(self, clientHello, serverHello, 1724 serverCertChain, keyExchange, 1725 reqCert, reqCAs, cipherSuite, 1726 settings):
1727 #Send ServerHello, Certificate[, ServerKeyExchange] 1728 #[, CertificateRequest], ServerHelloDone 1729 msgs = [] 1730 1731 # If we verify a client cert chain, return it 1732 clientCertChain = None 1733 1734 msgs.append(serverHello) 1735 msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) 1736 sigHashAlg = self._pickServerKeyExchangeSig(settings, clientHello) 1737 serverKeyExchange = keyExchange.makeServerKeyExchange(sigHashAlg) 1738 if serverKeyExchange is not None: 1739 msgs.append(serverKeyExchange) 1740 if reqCert: 1741 certificateRequest = CertificateRequest(self.version) 1742 if not reqCAs: 1743 reqCAs = [] 1744 validSigAlgs = self._sigHashesToList(settings) 1745 certificateRequest.create([ClientCertificateType.rsa_sign], 1746 reqCAs, 1747 validSigAlgs) 1748 msgs.append(certificateRequest) 1749 msgs.append(ServerHelloDone()) 1750 for result in self._sendMsgs(msgs): 1751 yield result 1752 1753 #Get [Certificate,] (if was requested) 1754 if reqCert: 1755 if self.version == (3,0): 1756 for result in self._getMsg((ContentType.handshake, 1757 ContentType.alert), 1758 HandshakeType.certificate, 1759 CertificateType.x509): 1760 if result in (0,1): yield result 1761 else: break 1762 msg = result 1763 1764 if isinstance(msg, Alert): 1765 #If it's not a no_certificate alert, re-raise 1766 alert = msg 1767 if alert.description != \ 1768 AlertDescription.no_certificate: 1769 self._shutdown(False) 1770 raise TLSRemoteAlert(alert) 1771 elif isinstance(msg, Certificate): 1772 clientCertificate = msg 1773 if clientCertificate.certChain and \ 1774 clientCertificate.certChain.getNumCerts()!=0: 1775 clientCertChain = clientCertificate.certChain 1776 else: 1777 raise AssertionError() 1778 elif self.version in ((3,1), (3,2), (3,3)): 1779 for result in self._getMsg(ContentType.handshake, 1780 HandshakeType.certificate, 1781 CertificateType.x509): 1782 if result in (0,1): yield result 1783 else: break 1784 clientCertificate = result 1785 if clientCertificate.certChain and \ 1786 clientCertificate.certChain.getNumCerts()!=0: 1787 clientCertChain = clientCertificate.certChain 1788 else: 1789 raise AssertionError() 1790 1791 #Get ClientKeyExchange 1792 for result in self._getMsg(ContentType.handshake, 1793 HandshakeType.client_key_exchange, 1794 cipherSuite): 1795 if result in (0,1): yield result 1796 else: break 1797 clientKeyExchange = result 1798 1799 #Process ClientKeyExchange 1800 try: 1801 premasterSecret = \ 1802 keyExchange.processClientKeyExchange(clientKeyExchange) 1803 except TLSIllegalParameterException as alert: 1804 for result in self._sendError(AlertDescription.illegal_parameter, 1805 str(alert)): 1806 yield result 1807 1808 #Get and check CertificateVerify, if relevant 1809 if clientCertChain: 1810 handshakeHash = self._handshake_hash.copy() 1811 for result in self._getMsg(ContentType.handshake, 1812 HandshakeType.certificate_verify): 1813 if result in (0, 1): 1814 yield result 1815 else: break 1816 certificateVerify = result 1817 signatureAlgorithm = None 1818 if self.version == (3, 3): 1819 validSigAlgs = self._sigHashesToList(settings) 1820 if certificateVerify.signatureAlgorithm not in validSigAlgs: 1821 for result in self._sendError(\ 1822 AlertDescription.decryption_failed, 1823 "Invalid signature on Certificate Verify"): 1824 yield result 1825 signatureAlgorithm = certificateVerify.signatureAlgorithm 1826 1827 verifyBytes = KeyExchange.calcVerifyBytes(self.version, 1828 handshakeHash, 1829 signatureAlgorithm, 1830 premasterSecret, 1831 clientHello.random, 1832 serverHello.random) 1833 publicKey = clientCertChain.getEndEntityPublicKey() 1834 if len(publicKey) < settings.minKeySize: 1835 for result in self._sendError(\ 1836 AlertDescription.handshake_failure, 1837 "Client's public key too small: %d" % len(publicKey)): 1838 yield result 1839 1840 if len(publicKey) > settings.maxKeySize: 1841 for result in self._sendError(\ 1842 AlertDescription.handshake_failure, 1843 "Client's public key too large: %d" % len(publicKey)): 1844 yield result 1845 1846 if not publicKey.verify(certificateVerify.signature, verifyBytes): 1847 for result in self._sendError(\ 1848 AlertDescription.decrypt_error, 1849 "Signature failed to verify"): 1850 yield result 1851 yield (premasterSecret, clientCertChain)
1852 1853
1854 - def _serverAnonKeyExchange(self, serverHello, keyExchange, cipherSuite):
1855 1856 # Create ServerKeyExchange 1857 serverKeyExchange = keyExchange.makeServerKeyExchange() 1858 1859 # Send ServerHello[, Certificate], ServerKeyExchange, 1860 # ServerHelloDone 1861 msgs = [] 1862 msgs.append(serverHello) 1863 msgs.append(serverKeyExchange) 1864 msgs.append(ServerHelloDone()) 1865 for result in self._sendMsgs(msgs): 1866 yield result 1867 1868 # Get and check ClientKeyExchange 1869 for result in self._getMsg(ContentType.handshake, 1870 HandshakeType.client_key_exchange, 1871 cipherSuite): 1872 if result in (0,1): 1873 yield result 1874 else: 1875 break 1876 cke = result 1877 premasterSecret = keyExchange.processClientKeyExchange(cke) 1878 1879 yield premasterSecret
1880 1881
1882 - def _serverFinished(self, premasterSecret, clientRandom, serverRandom, 1883 cipherSuite, cipherImplementations, nextProtos):
1884 if self.extendedMasterSecret: 1885 masterSecret = calcExtendedMasterSecret(self.version, 1886 cipherSuite, 1887 premasterSecret, 1888 self._handshake_hash) 1889 else: 1890 masterSecret = calcMasterSecret(self.version, 1891 cipherSuite, 1892 premasterSecret, 1893 clientRandom, 1894 serverRandom) 1895 1896 #Calculate pending connection states 1897 self._calcPendingStates(cipherSuite, masterSecret, 1898 clientRandom, serverRandom, 1899 cipherImplementations) 1900 1901 #Exchange ChangeCipherSpec and Finished messages 1902 for result in self._getFinished(masterSecret, 1903 cipherSuite, 1904 expect_next_protocol=nextProtos is not None): 1905 yield result 1906 1907 for result in self._sendFinished(masterSecret, cipherSuite): 1908 yield result 1909 1910 yield masterSecret
1911 1912 1913 #********************************************************* 1914 # Shared Handshake Functions 1915 #********************************************************* 1916 1917
1918 - def _sendFinished(self, masterSecret, cipherSuite=None, nextProto=None):
1919 # send the CCS and Finished in single TCP packet 1920 self.sock.buffer_writes = True 1921 #Send ChangeCipherSpec 1922 for result in self._sendMsg(ChangeCipherSpec()): 1923 yield result 1924 1925 #Switch to pending write state 1926 self._changeWriteState() 1927 1928 if nextProto is not None: 1929 nextProtoMsg = NextProtocol().create(nextProto) 1930 for result in self._sendMsg(nextProtoMsg): 1931 yield result 1932 1933 #Calculate verification data 1934 verifyData = calcFinished(self.version, 1935 masterSecret, 1936 cipherSuite, 1937 self._handshake_hash, 1938 self._client) 1939 if self.fault == Fault.badFinished: 1940 verifyData[0] = (verifyData[0]+1)%256 1941 1942 #Send Finished message under new state 1943 finished = Finished(self.version).create(verifyData) 1944 for result in self._sendMsg(finished): 1945 yield result 1946 self.sock.flush() 1947 self.sock.buffer_writes = False
1948
1949 - def _getFinished(self, masterSecret, cipherSuite=None, 1950 expect_next_protocol=False, nextProto=None):
1951 #Get and check ChangeCipherSpec 1952 for result in self._getMsg(ContentType.change_cipher_spec): 1953 if result in (0,1): 1954 yield result 1955 changeCipherSpec = result 1956 1957 if changeCipherSpec.type != 1: 1958 for result in self._sendError(AlertDescription.illegal_parameter, 1959 "ChangeCipherSpec type incorrect"): 1960 yield result 1961 1962 #Switch to pending read state 1963 self._changeReadState() 1964 1965 #Server Finish - Are we waiting for a next protocol echo? 1966 if expect_next_protocol: 1967 for result in self._getMsg(ContentType.handshake, HandshakeType.next_protocol): 1968 if result in (0,1): 1969 yield result 1970 if result is None: 1971 for result in self._sendError(AlertDescription.unexpected_message, 1972 "Didn't get NextProtocol message"): 1973 yield result 1974 1975 self.next_proto = result.next_proto 1976 else: 1977 self.next_proto = None 1978 1979 #Client Finish - Only set the next_protocol selected in the connection 1980 if nextProto: 1981 self.next_proto = nextProto 1982 1983 #Calculate verification data 1984 verifyData = calcFinished(self.version, 1985 masterSecret, 1986 cipherSuite, 1987 self._handshake_hash, 1988 not self._client) 1989 1990 #Get and check Finished message under new state 1991 for result in self._getMsg(ContentType.handshake, 1992 HandshakeType.finished): 1993 if result in (0,1): 1994 yield result 1995 finished = result 1996 if finished.verify_data != verifyData: 1997 for result in self._sendError(AlertDescription.decrypt_error, 1998 "Finished message is incorrect"): 1999 yield result
2000
2001 - def _handshakeWrapperAsync(self, handshaker, checker):
2002 try: 2003 for result in handshaker: 2004 yield result 2005 if checker: 2006 try: 2007 checker(self) 2008 except TLSAuthenticationError: 2009 alert = Alert().create(AlertDescription.close_notify, 2010 AlertLevel.fatal) 2011 for result in self._sendMsg(alert): 2012 yield result 2013 raise 2014 except GeneratorExit: 2015 raise 2016 except TLSAlert as alert: 2017 if not self.fault: 2018 raise 2019 if alert.description not in Fault.faultAlerts[self.fault]: 2020 raise TLSFaultError(str(alert)) 2021 else: 2022 pass 2023 except: 2024 self._shutdown(False) 2025 raise
2026 2027 @staticmethod
2028 - def _pickServerKeyExchangeSig(settings, clientHello):
2029 """Pick a hash that matches most closely the supported ones""" 2030 hashAndAlgsExt = clientHello.getExtension(\ 2031 ExtensionType.signature_algorithms) 2032 2033 if hashAndAlgsExt is None or hashAndAlgsExt.sigalgs is None: 2034 # RFC 5246 states that if there are no hashes advertised, 2035 # sha1 should be picked 2036 return "sha1" 2037 2038 rsaHashes = [alg[0] for alg in hashAndAlgsExt.sigalgs 2039 if alg[1] == SignatureAlgorithm.rsa] 2040 for hashName in settings.rsaSigHashes: 2041 hashID = getattr(HashAlgorithm, hashName) 2042 if hashID in rsaHashes: 2043 return hashName 2044 2045 # if none match, default to sha1 2046 return "sha1"
2047 2048 @staticmethod
2049 - def _sigHashesToList(settings):
2050 """Convert list of valid signature hashes to array of tuples""" 2051 sigAlgs = [] 2052 for hashName in settings.rsaSigHashes: 2053 sigAlgs.append((getattr(HashAlgorithm, hashName), 2054 SignatureAlgorithm.rsa)) 2055 return sigAlgs
2056 2057 @staticmethod
2058 - def _curveNamesToList(settings):
2059 """Convert list of acceptable curves to array identifiers""" 2060 return [getattr(GroupName, val) for val in settings.eccCurves]
2061