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.streamSuites and \ 1422 cipherSuite not in CipherSuite.aeadSuites: 1423 extensions = [TLSExtension().create(ExtensionType.encrypt_then_mac, 1424 bytearray(0))] 1425 self._recordLayer.encryptThenMAC = True 1426 else: 1427 extensions = None 1428 1429 serverHello = ServerHello() 1430 serverHello.create(self.version, getRandomBytes(32), sessionID, \ 1431 cipherSuite, CertificateType.x509, tackExt, 1432 nextProtos, extensions=extensions) 1433 1434 # Perform the SRP key exchange 1435 clientCertChain = None 1436 if cipherSuite in CipherSuite.srpAllSuites: 1437 for result in self._serverSRPKeyExchange(clientHello, serverHello, 1438 verifierDB, cipherSuite, 1439 privateKey, certChain): 1440 if result in (0,1): yield result 1441 else: break 1442 premasterSecret = result 1443 1444 # Perform a certificate-based key exchange 1445 elif (cipherSuite in CipherSuite.certSuites or 1446 cipherSuite in CipherSuite.dheCertSuites): 1447 if cipherSuite in CipherSuite.certSuites: 1448 keyExchange = RSAKeyExchange(cipherSuite, 1449 clientHello, 1450 serverHello, 1451 privateKey) 1452 elif cipherSuite in CipherSuite.dheCertSuites: 1453 keyExchange = DHE_RSAKeyExchange(cipherSuite, 1454 clientHello, 1455 serverHello, 1456 privateKey) 1457 else: 1458 assert(False) 1459 for result in self._serverCertKeyExchange(clientHello, serverHello, 1460 certChain, keyExchange, 1461 reqCert, reqCAs, cipherSuite, 1462 settings): 1463 if result in (0,1): yield result 1464 else: break 1465 (premasterSecret, clientCertChain) = result 1466 1467 # Perform anonymous Diffie Hellman key exchange 1468 elif cipherSuite in CipherSuite.anonSuites: 1469 for result in self._serverAnonKeyExchange(clientHello, serverHello, 1470 cipherSuite, settings): 1471 if result in (0,1): yield result 1472 else: break 1473 premasterSecret = result 1474 1475 else: 1476 assert(False) 1477 1478 # Exchange Finished messages 1479 for result in self._serverFinished(premasterSecret, 1480 clientHello.random, serverHello.random, 1481 cipherSuite, settings.cipherImplementations, 1482 nextProtos): 1483 if result in (0,1): yield result 1484 else: break 1485 masterSecret = result 1486 1487 #Create the session object 1488 self.session = Session() 1489 if cipherSuite in CipherSuite.certAllSuites: 1490 serverCertChain = certChain 1491 else: 1492 serverCertChain = None 1493 srpUsername = None 1494 serverName = None 1495 if clientHello.srp_username: 1496 srpUsername = clientHello.srp_username.decode("utf-8") 1497 if clientHello.server_name: 1498 serverName = clientHello.server_name.decode("utf-8") 1499 self.session.create(masterSecret, serverHello.session_id, cipherSuite, 1500 srpUsername, clientCertChain, serverCertChain, 1501 tackExt, (serverHello.tackExt is not None), 1502 serverName, 1503 encryptThenMAC=self._recordLayer.encryptThenMAC) 1504 1505 #Add the session object to the session cache 1506 if sessionCache and sessionID: 1507 sessionCache[sessionID] = self.session 1508 1509 self._handshakeDone(resumed=False)
1510 1511
1512 - def _serverGetClientHello(self, settings, certChain, verifierDB, 1513 sessionCache, anon):
1514 #Tentatively set version to most-desirable version, so if an error 1515 #occurs parsing the ClientHello, this is what we'll use for the 1516 #error alert 1517 self.version = settings.maxVersion 1518 1519 #Get ClientHello 1520 for result in self._getMsg(ContentType.handshake, 1521 HandshakeType.client_hello): 1522 if result in (0,1): yield result 1523 else: break 1524 clientHello = result 1525 1526 #If client's version is too low, reject it 1527 if clientHello.client_version < settings.minVersion: 1528 self.version = settings.minVersion 1529 for result in self._sendError(\ 1530 AlertDescription.protocol_version, 1531 "Too old version: %s" % str(clientHello.client_version)): 1532 yield result 1533 1534 #If client's version is too high, propose my highest version 1535 elif clientHello.client_version > settings.maxVersion: 1536 self.version = settings.maxVersion 1537 1538 else: 1539 #Set the version to the client's version 1540 self.version = clientHello.client_version 1541 1542 #Detect if the client performed an inappropriate fallback. 1543 if clientHello.client_version < settings.maxVersion and \ 1544 CipherSuite.TLS_FALLBACK_SCSV in clientHello.cipher_suites: 1545 for result in self._sendError(\ 1546 AlertDescription.inappropriate_fallback): 1547 yield result 1548 1549 #Now that the version is known, limit to only the ciphers available to 1550 #that version. 1551 cipherSuites = [] 1552 if verifierDB: 1553 if certChain: 1554 cipherSuites += \ 1555 CipherSuite.getSrpCertSuites(settings, self.version) 1556 cipherSuites += CipherSuite.getSrpSuites(settings, self.version) 1557 elif certChain: 1558 cipherSuites += CipherSuite.getDheCertSuites(settings, self.version) 1559 cipherSuites += CipherSuite.getCertSuites(settings, self.version) 1560 elif anon: 1561 cipherSuites += CipherSuite.getAnonSuites(settings, self.version) 1562 else: 1563 assert(False) 1564 cipherSuites = CipherSuite.filterForVersion(cipherSuites, 1565 minVersion=self.version, 1566 maxVersion=self.version) 1567 1568 #If resumption was requested and we have a session cache... 1569 if clientHello.session_id and sessionCache: 1570 session = None 1571 1572 #Check in the session cache 1573 if sessionCache and not session: 1574 try: 1575 session = sessionCache[clientHello.session_id] 1576 if not session.resumable: 1577 raise AssertionError() 1578 #Check for consistency with ClientHello 1579 if session.cipherSuite not in cipherSuites: 1580 for result in self._sendError(\ 1581 AlertDescription.handshake_failure): 1582 yield result 1583 if session.cipherSuite not in clientHello.cipher_suites: 1584 for result in self._sendError(\ 1585 AlertDescription.handshake_failure): 1586 yield result 1587 if clientHello.srp_username: 1588 if not session.srpUsername or \ 1589 clientHello.srp_username != bytearray(session.srpUsername, "utf-8"): 1590 for result in self._sendError(\ 1591 AlertDescription.handshake_failure): 1592 yield result 1593 if clientHello.server_name: 1594 if not session.serverName or \ 1595 clientHello.server_name != bytearray(session.serverName, "utf-8"): 1596 for result in self._sendError(\ 1597 AlertDescription.handshake_failure): 1598 yield result 1599 if session.encryptThenMAC and \ 1600 not clientHello.getExtension( 1601 ExtensionType.encrypt_then_mac): 1602 for result in self._sendError(\ 1603 AlertDescription.handshake_failure): 1604 yield result 1605 except KeyError: 1606 pass 1607 1608 #If a session is found.. 1609 if session: 1610 #Send ServerHello 1611 if session.encryptThenMAC: 1612 self._recordLayer.encryptThenMAC = True 1613 mte = TLSExtension().create(ExtensionType.encrypt_then_mac, 1614 bytearray(0)) 1615 extensions = [mte] 1616 else: 1617 extensions = None 1618 serverHello = ServerHello() 1619 serverHello.create(self.version, getRandomBytes(32), 1620 session.sessionID, session.cipherSuite, 1621 CertificateType.x509, None, None, 1622 extensions=extensions) 1623 for result in self._sendMsg(serverHello): 1624 yield result 1625 1626 #Calculate pending connection states 1627 self._calcPendingStates(session.cipherSuite, 1628 session.masterSecret, 1629 clientHello.random, 1630 serverHello.random, 1631 settings.cipherImplementations) 1632 1633 #Exchange ChangeCipherSpec and Finished messages 1634 for result in self._sendFinished(session.masterSecret, 1635 session.cipherSuite): 1636 yield result 1637 for result in self._getFinished(session.masterSecret, 1638 session.cipherSuite): 1639 yield result 1640 1641 #Set the session 1642 self.session = session 1643 1644 yield None # Handshake done! 1645 1646 #Calculate the first cipher suite intersection. 1647 #This is the 'privileged' ciphersuite. We'll use it if we're 1648 #doing a new negotiation. In fact, 1649 #the only time we won't use it is if we're resuming a 1650 #session, in which case we use the ciphersuite from the session. 1651 # 1652 #Given the current ciphersuite ordering, this means we prefer SRP 1653 #over non-SRP. 1654 for cipherSuite in cipherSuites: 1655 if cipherSuite in clientHello.cipher_suites: 1656 break 1657 else: 1658 for result in self._sendError(\ 1659 AlertDescription.handshake_failure, 1660 "No mutual ciphersuite"): 1661 yield result 1662 if cipherSuite in CipherSuite.srpAllSuites and \ 1663 not clientHello.srp_username: 1664 for result in self._sendError(\ 1665 AlertDescription.unknown_psk_identity, 1666 "Client sent a hello, but without the SRP username"): 1667 yield result 1668 1669 #If an RSA suite is chosen, check for certificate type intersection 1670 if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \ 1671 not in clientHello.certificate_types: 1672 for result in self._sendError(\ 1673 AlertDescription.handshake_failure, 1674 "the client doesn't support my certificate type"): 1675 yield result 1676 1677 # If resumption was not requested, or 1678 # we have no session cache, or 1679 # the client's session_id was not found in cache: 1680 yield (clientHello, cipherSuite)
1681
1682 - def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB, 1683 cipherSuite, privateKey, serverCertChain):
1684 1685 srpUsername = clientHello.srp_username.decode("utf-8") 1686 self.allegedSrpUsername = srpUsername 1687 #Get parameters from username 1688 try: 1689 entry = verifierDB[srpUsername] 1690 except KeyError: 1691 for result in self._sendError(\ 1692 AlertDescription.unknown_psk_identity): 1693 yield result 1694 (N, g, s, v) = entry 1695 1696 #Calculate server's ephemeral DH values (b, B) 1697 b = bytesToNumber(getRandomBytes(32)) 1698 k = makeK(N, g) 1699 B = (powMod(g, b, N) + (k*v)) % N 1700 1701 #Create ServerKeyExchange, signing it if necessary 1702 serverKeyExchange = ServerKeyExchange(cipherSuite, self.version) 1703 serverKeyExchange.createSRP(N, g, s, B) 1704 if cipherSuite in CipherSuite.srpCertSuites: 1705 hashBytes = serverKeyExchange.hash(clientHello.random, 1706 serverHello.random) 1707 serverKeyExchange.signature = privateKey.sign(hashBytes) 1708 if self.version == (3, 3): 1709 # TODO signing algorithm not negotiatied 1710 serverKeyExchange.signAlg = SignatureAlgorithm.rsa 1711 serverKeyExchange.hashAlg = HashAlgorithm.sha1 1712 1713 #Send ServerHello[, Certificate], ServerKeyExchange, 1714 #ServerHelloDone 1715 msgs = [] 1716 msgs.append(serverHello) 1717 if cipherSuite in CipherSuite.srpCertSuites: 1718 certificateMsg = Certificate(CertificateType.x509) 1719 certificateMsg.create(serverCertChain) 1720 msgs.append(certificateMsg) 1721 msgs.append(serverKeyExchange) 1722 msgs.append(ServerHelloDone()) 1723 for result in self._sendMsgs(msgs): 1724 yield result 1725 1726 #Get and check ClientKeyExchange 1727 for result in self._getMsg(ContentType.handshake, 1728 HandshakeType.client_key_exchange, 1729 cipherSuite): 1730 if result in (0,1): yield result 1731 else: break 1732 clientKeyExchange = result 1733 A = clientKeyExchange.srp_A 1734 if A % N == 0: 1735 for result in self._sendError(AlertDescription.illegal_parameter, 1736 "Suspicious A value"): 1737 yield result 1738 assert(False) # Just to ensure we don't fall through somehow 1739 1740 #Calculate u 1741 u = makeU(N, A, B) 1742 1743 #Calculate premaster secret 1744 S = powMod((A * powMod(v,u,N)) % N, b, N) 1745 premasterSecret = numberToByteArray(S) 1746 1747 yield premasterSecret
1748 1749
1750 - def _serverCertKeyExchange(self, clientHello, serverHello, 1751 serverCertChain, keyExchange, 1752 reqCert, reqCAs, cipherSuite, 1753 settings):
1754 #Send ServerHello, Certificate[, ServerKeyExchange] 1755 #[, CertificateRequest], ServerHelloDone 1756 msgs = [] 1757 1758 # If we verify a client cert chain, return it 1759 clientCertChain = None 1760 1761 msgs.append(serverHello) 1762 msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) 1763 serverKeyExchange = keyExchange.makeServerKeyExchange() 1764 if serverKeyExchange is not None: 1765 msgs.append(serverKeyExchange) 1766 if reqCert: 1767 certificateRequest = CertificateRequest(self.version) 1768 if not reqCAs: 1769 reqCAs = [] 1770 # TODO add support for more HashAlgorithms 1771 certificateRequest.create([ClientCertificateType.rsa_sign], 1772 reqCAs, 1773 [(HashAlgorithm.sha1, 1774 SignatureAlgorithm.rsa)]) 1775 msgs.append(certificateRequest) 1776 msgs.append(ServerHelloDone()) 1777 for result in self._sendMsgs(msgs): 1778 yield result 1779 1780 #Get [Certificate,] (if was requested) 1781 if reqCert: 1782 if self.version == (3,0): 1783 for result in self._getMsg((ContentType.handshake, 1784 ContentType.alert), 1785 HandshakeType.certificate, 1786 CertificateType.x509): 1787 if result in (0,1): yield result 1788 else: break 1789 msg = result 1790 1791 if isinstance(msg, Alert): 1792 #If it's not a no_certificate alert, re-raise 1793 alert = msg 1794 if alert.description != \ 1795 AlertDescription.no_certificate: 1796 self._shutdown(False) 1797 raise TLSRemoteAlert(alert) 1798 elif isinstance(msg, Certificate): 1799 clientCertificate = msg 1800 if clientCertificate.certChain and \ 1801 clientCertificate.certChain.getNumCerts()!=0: 1802 clientCertChain = clientCertificate.certChain 1803 else: 1804 raise AssertionError() 1805 elif self.version in ((3,1), (3,2), (3,3)): 1806 for result in self._getMsg(ContentType.handshake, 1807 HandshakeType.certificate, 1808 CertificateType.x509): 1809 if result in (0,1): yield result 1810 else: break 1811 clientCertificate = result 1812 if clientCertificate.certChain and \ 1813 clientCertificate.certChain.getNumCerts()!=0: 1814 clientCertChain = clientCertificate.certChain 1815 else: 1816 raise AssertionError() 1817 1818 #Get ClientKeyExchange 1819 for result in self._getMsg(ContentType.handshake, 1820 HandshakeType.client_key_exchange, 1821 cipherSuite): 1822 if result in (0,1): yield result 1823 else: break 1824 clientKeyExchange = result 1825 1826 #Process ClientKeyExchange 1827 try: 1828 premasterSecret = \ 1829 keyExchange.processClientKeyExchange(clientKeyExchange) 1830 except TLSLocalAlert as alert: 1831 for result in self._sendError(alert.description, alert.message): 1832 yield result 1833 1834 #Get and check CertificateVerify, if relevant 1835 if clientCertChain: 1836 if self.version == (3,0): 1837 masterSecret = calcMasterSecret(self.version, 1838 cipherSuite, 1839 premasterSecret, 1840 clientHello.random, 1841 serverHello.random) 1842 verifyBytes = self._handshake_hash.digestSSL(masterSecret, b"") 1843 elif self.version in ((3,1), (3,2)): 1844 verifyBytes = self._handshake_hash.digest() 1845 elif self.version == (3,3): 1846 verifyBytes = self._handshake_hash.digest('sha1') 1847 verifyBytes = RSAKey.addPKCS1SHA1Prefix(verifyBytes) 1848 for result in self._getMsg(ContentType.handshake, 1849 HandshakeType.certificate_verify): 1850 if result in (0,1): yield result 1851 else: break 1852 certificateVerify = result 1853 publicKey = clientCertChain.getEndEntityPublicKey() 1854 if len(publicKey) < settings.minKeySize: 1855 for result in self._sendError(\ 1856 AlertDescription.handshake_failure, 1857 "Client's public key too small: %d" % len(publicKey)): 1858 yield result 1859 1860 if len(publicKey) > settings.maxKeySize: 1861 for result in self._sendError(\ 1862 AlertDescription.handshake_failure, 1863 "Client's public key too large: %d" % len(publicKey)): 1864 yield result 1865 1866 if not publicKey.verify(certificateVerify.signature, verifyBytes): 1867 for result in self._sendError(\ 1868 AlertDescription.decrypt_error, 1869 "Signature failed to verify"): 1870 yield result 1871 yield (premasterSecret, clientCertChain)
1872 1873
1874 - def _serverAnonKeyExchange(self, clientHello, serverHello, cipherSuite, 1875 settings):
1876 # Calculate DH p, g, Xs, Ys 1877 # TODO make configurable 1878 dh_g, dh_p = goodGroupParameters[2] 1879 dh_Xs = bytesToNumber(getRandomBytes(32)) 1880 dh_Ys = powMod(dh_g, dh_Xs, dh_p) 1881 1882 #Create ServerKeyExchange 1883 serverKeyExchange = ServerKeyExchange(cipherSuite, self.version) 1884 serverKeyExchange.createDH(dh_p, dh_g, dh_Ys) 1885 1886 #Send ServerHello[, Certificate], ServerKeyExchange, 1887 #ServerHelloDone 1888 msgs = [] 1889 msgs.append(serverHello) 1890 msgs.append(serverKeyExchange) 1891 msgs.append(ServerHelloDone()) 1892 for result in self._sendMsgs(msgs): 1893 yield result 1894 1895 #Get and check ClientKeyExchange 1896 for result in self._getMsg(ContentType.handshake, 1897 HandshakeType.client_key_exchange, 1898 cipherSuite): 1899 if result in (0,1): 1900 yield result 1901 else: 1902 break 1903 clientKeyExchange = result 1904 dh_Yc = clientKeyExchange.dh_Yc 1905 1906 if dh_Yc % dh_p == 0: 1907 for result in self._sendError(AlertDescription.illegal_parameter, 1908 "Suspicious dh_Yc value"): 1909 yield result 1910 assert(False) # Just to ensure we don't fall through somehow 1911 1912 #Calculate premaster secre 1913 S = powMod(dh_Yc,dh_Xs,dh_p) 1914 premasterSecret = numberToByteArray(S) 1915 1916 yield premasterSecret
1917 1918
1919 - def _serverFinished(self, premasterSecret, clientRandom, serverRandom, 1920 cipherSuite, cipherImplementations, nextProtos):
1921 masterSecret = calcMasterSecret(self.version, 1922 cipherSuite, 1923 premasterSecret, 1924 clientRandom, 1925 serverRandom) 1926 1927 #Calculate pending connection states 1928 self._calcPendingStates(cipherSuite, masterSecret, 1929 clientRandom, serverRandom, 1930 cipherImplementations) 1931 1932 #Exchange ChangeCipherSpec and Finished messages 1933 for result in self._getFinished(masterSecret, 1934 cipherSuite, 1935 expect_next_protocol=nextProtos is not None): 1936 yield result 1937 1938 for result in self._sendFinished(masterSecret, cipherSuite): 1939 yield result 1940 1941 yield masterSecret
1942 1943 1944 #********************************************************* 1945 # Shared Handshake Functions 1946 #********************************************************* 1947 1948
1949 - def _sendFinished(self, masterSecret, cipherSuite=None, nextProto=None):
1950 #Send ChangeCipherSpec 1951 for result in self._sendMsg(ChangeCipherSpec()): 1952 yield result 1953 1954 #Switch to pending write state 1955 self._changeWriteState() 1956 1957 if nextProto is not None: 1958 nextProtoMsg = NextProtocol().create(nextProto) 1959 for result in self._sendMsg(nextProtoMsg): 1960 yield result 1961 1962 #Calculate verification data 1963 verifyData = calcFinished(self.version, 1964 masterSecret, 1965 cipherSuite, 1966 self._handshake_hash, 1967 self._client) 1968 if self.fault == Fault.badFinished: 1969 verifyData[0] = (verifyData[0]+1)%256 1970 1971 #Send Finished message under new state 1972 finished = Finished(self.version).create(verifyData) 1973 for result in self._sendMsg(finished): 1974 yield result
1975
1976 - def _getFinished(self, masterSecret, cipherSuite=None, 1977 expect_next_protocol=False, nextProto=None):
1978 #Get and check ChangeCipherSpec 1979 for result in self._getMsg(ContentType.change_cipher_spec): 1980 if result in (0,1): 1981 yield result 1982 changeCipherSpec = result 1983 1984 if changeCipherSpec.type != 1: 1985 for result in self._sendError(AlertDescription.illegal_parameter, 1986 "ChangeCipherSpec type incorrect"): 1987 yield result 1988 1989 #Switch to pending read state 1990 self._changeReadState() 1991 1992 #Server Finish - Are we waiting for a next protocol echo? 1993 if expect_next_protocol: 1994 for result in self._getMsg(ContentType.handshake, HandshakeType.next_protocol): 1995 if result in (0,1): 1996 yield result 1997 if result is None: 1998 for result in self._sendError(AlertDescription.unexpected_message, 1999 "Didn't get NextProtocol message"): 2000 yield result 2001 2002 self.next_proto = result.next_proto 2003 else: 2004 self.next_proto = None 2005 2006 #Client Finish - Only set the next_protocol selected in the connection 2007 if nextProto: 2008 self.next_proto = nextProto 2009 2010 #Calculate verification data 2011 verifyData = calcFinished(self.version, 2012 masterSecret, 2013 cipherSuite, 2014 self._handshake_hash, 2015 not self._client) 2016 2017 #Get and check Finished message under new state 2018 for result in self._getMsg(ContentType.handshake, 2019 HandshakeType.finished): 2020 if result in (0,1): 2021 yield result 2022 finished = result 2023 if finished.verify_data != verifyData: 2024 for result in self._sendError(AlertDescription.decrypt_error, 2025 "Finished message is incorrect"): 2026 yield result
2027
2028 - def _handshakeWrapperAsync(self, handshaker, checker):
2029 try: 2030 for result in handshaker: 2031 yield result 2032 if checker: 2033 try: 2034 checker(self) 2035 except TLSAuthenticationError: 2036 alert = Alert().create(AlertDescription.close_notify, 2037 AlertLevel.fatal) 2038 for result in self._sendMsg(alert): 2039 yield result 2040 raise 2041 except GeneratorExit: 2042 raise 2043 except TLSAlert as alert: 2044 if not self.fault: 2045 raise 2046 if alert.description not in Fault.faultAlerts[self.fault]: 2047 raise TLSFaultError(str(alert)) 2048 else: 2049 pass 2050 except: 2051 self._shutdown(False) 2052 raise
2053