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