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  # 
   5  # See the LICENSE file for legal information regarding use of this file. 
   6   
   7  """ 
   8  MAIN CLASS FOR TLS LITE (START HERE!). 
   9  """ 
  10   
  11  import socket 
  12  from .utils.compat import formatExceptionTrace 
  13  from .tlsrecordlayer import TLSRecordLayer 
  14  from .session import Session 
  15  from .constants import * 
  16  from .utils.cryptomath import getRandomBytes 
  17  from .errors import * 
  18  from .messages import * 
  19  from .mathtls import * 
  20  from .handshakesettings import HandshakeSettings 
  21  from .utils.tackwrapper import * 
  22   
  23   
24 -class TLSConnection(TLSRecordLayer):
25 """ 26 This class wraps a socket and provides TLS handshaking and data 27 transfer. 28 29 To use this class, create a new instance, passing a connected 30 socket into the constructor. Then call some handshake function. 31 If the handshake completes without raising an exception, then a TLS 32 connection has been negotiated. You can transfer data over this 33 connection as if it were a socket. 34 35 This class provides both synchronous and asynchronous versions of 36 its key functions. The synchronous versions should be used when 37 writing single-or multi-threaded code using blocking sockets. The 38 asynchronous versions should be used when performing asynchronous, 39 event-based I/O with non-blocking sockets. 40 41 Asynchronous I/O is a complicated subject; typically, you should 42 not use the asynchronous functions directly, but should use some 43 framework like asyncore or Twisted which TLS Lite integrates with 44 (see 45 L{tlslite.integration.tlsasyncdispatchermixin.TLSAsyncDispatcherMixIn}). 46 """ 47
48 - def __init__(self, sock):
49 """Create a new TLSConnection instance. 50 51 @param sock: The socket data will be transmitted on. The 52 socket should already be connected. It may be in blocking or 53 non-blocking mode. 54 55 @type sock: L{socket.socket} 56 """ 57 TLSRecordLayer.__init__(self, sock)
58 59 #********************************************************* 60 # Client Handshake Functions 61 #********************************************************* 62
63 - def handshakeClientSRP(self, username, password, session=None, 64 settings=None, checker=None, 65 reqTack=False, async=False):
66 """Perform an SRP handshake in the role of client. 67 68 This function performs a TLS/SRP handshake. SRP mutually 69 authenticates both parties to each other using only a 70 username and password. This function may also perform a 71 combined SRP and server-certificate handshake, if the server 72 chooses to authenticate itself with a certificate chain in 73 addition to doing SRP. 74 75 If the function completes without raising an exception, the 76 TLS connection will be open and available for data transfer. 77 78 If an exception is raised, the connection will have been 79 automatically closed (if it was ever open). 80 81 @type username: str 82 @param username: The SRP username. 83 84 @type password: str 85 @param password: The SRP password. 86 87 @type session: L{tlslite.session.Session} 88 @param session: A TLS session to attempt to resume. This 89 session must be an SRP session performed with the same username 90 and password as were passed in. If the resumption does not 91 succeed, a full SRP handshake will be performed. 92 93 @type settings: L{tlslite.handshakesettings.HandshakeSettings} 94 @param settings: Various settings which can be used to control 95 the ciphersuites, certificate types, and SSL/TLS versions 96 offered by the client. 97 98 @type checker: L{tlslite.checker.Checker} 99 @param checker: A Checker instance. This instance will be 100 invoked to examine the other party's authentication 101 credentials, if the handshake completes succesfully. 102 103 @type reqTack: bool 104 @param reqTack: Whether or not to send a "tack" TLS Extension, 105 requesting the server return a TACK_Extension if it has one. 106 107 @type async: bool 108 @param async: If False, this function will block until the 109 handshake is completed. If True, this function will return a 110 generator. Successive invocations of the generator will 111 return 0 if it is waiting to read from the socket, 1 if it is 112 waiting to write to the socket, or will raise StopIteration if 113 the handshake operation is completed. 114 115 @rtype: None or an iterable 116 @return: If 'async' is True, a generator object will be 117 returned. 118 119 @raise socket.error: If a socket error occurs. 120 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 121 without a preceding alert. 122 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 123 @raise tlslite.errors.TLSAuthenticationError: If the checker 124 doesn't like the other party's authentication credentials. 125 """ 126 handshaker = self._handshakeClientAsync(srpParams=(username, password), 127 session=session, settings=settings, checker=checker, 128 reqTack=reqTack) 129 # The handshaker is a Python Generator which executes the handshake. 130 # It allows the handshake to be run in a "piecewise", asynchronous 131 # fashion, returning 1 when it is waiting to able to write, 0 when 132 # it is waiting to read. 133 # 134 # If 'async' is True, the generator is returned to the caller, 135 # otherwise it is executed to completion here. 136 if async: 137 return handshaker 138 for result in handshaker: 139 pass
140
141 - def handshakeClientCert(self, certChain=None, privateKey=None, 142 session=None, settings=None, checker=None, 143 reqTack=False, async=False):
144 """Perform a certificate-based handshake in the role of client. 145 146 This function performs an SSL or TLS handshake. The server 147 will authenticate itself using an X.509 certificate 148 chain. If the handshake succeeds, the server's certificate 149 chain will be stored in the session's serverCertChain attribute. 150 Unless a checker object is passed in, this function does no 151 validation or checking of the server's certificate chain. 152 153 If the server requests client authentication, the 154 client will send the passed-in certificate chain, and use the 155 passed-in private key to authenticate itself. If no 156 certificate chain and private key were passed in, the client 157 will attempt to proceed without client authentication. The 158 server may or may not allow this. 159 160 If the function completes without raising an exception, the 161 TLS connection will be open and available for data transfer. 162 163 If an exception is raised, the connection will have been 164 automatically closed (if it was ever open). 165 166 @type certChain: L{tlslite.x509certchain.X509CertChain} 167 @param certChain: The certificate chain to be used if the 168 server requests client authentication. 169 170 @type privateKey: L{tlslite.utils.rsakey.RSAKey} 171 @param privateKey: The private key to be used if the server 172 requests client authentication. 173 174 @type session: L{tlslite.session.Session} 175 @param session: A TLS session to attempt to resume. If the 176 resumption does not succeed, a full handshake will be 177 performed. 178 179 @type settings: L{tlslite.handshakesettings.HandshakeSettings} 180 @param settings: Various settings which can be used to control 181 the ciphersuites, certificate types, and SSL/TLS versions 182 offered by the client. 183 184 @type checker: L{tlslite.checker.Checker} 185 @param checker: A Checker instance. This instance will be 186 invoked to examine the other party's authentication 187 credentials, if the handshake completes succesfully. 188 189 @type reqTack: bool 190 @param reqTack: Whether or not to send a "tack" TLS Extension, 191 requesting the server return a TACK_Extension if it has one. 192 193 @type async: bool 194 @param async: If False, this function will block until the 195 handshake is completed. If True, this function will return a 196 generator. Successive invocations of the generator will 197 return 0 if it is waiting to read from the socket, 1 if it is 198 waiting to write to the socket, or will raise StopIteration if 199 the handshake operation is completed. 200 201 @rtype: None or an iterable 202 @return: If 'async' is True, a generator object will be 203 returned. 204 205 @raise socket.error: If a socket error occurs. 206 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 207 without a preceding alert. 208 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 209 @raise tlslite.errors.TLSAuthenticationError: If the checker 210 doesn't like the other party's authentication credentials. 211 """ 212 handshaker = self._handshakeClientAsync(certParams=(certChain, 213 privateKey), session=session, settings=settings, 214 checker=checker, reqTack=reqTack) 215 # The handshaker is a Python Generator which executes the handshake. 216 # It allows the handshake to be run in a "piecewise", asynchronous 217 # fashion, returning 1 when it is waiting to able to write, 0 when 218 # it is waiting to read. 219 # 220 # If 'async' is True, the generator is returned to the caller, 221 # otherwise it is executed to completion here. 222 if async: 223 return handshaker 224 for result in handshaker: 225 pass
226 227
228 - def _handshakeClientAsync(self, srpParams=(), certParams=(), 229 session=None, settings=None, checker=None, 230 reqTack=False):
231 232 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, 233 certParams=certParams, 234 session=session, 235 settings=settings, 236 reqTack=reqTack) 237 for result in self._handshakeWrapperAsync(handshaker, checker): 238 yield result
239 240
241 - def _handshakeClientAsyncHelper(self, srpParams, certParams, 242 session, settings, reqTack):
243 244 self._handshakeStart(client=True) 245 246 #Unpack parameters 247 srpUsername = None # srpParams[0] 248 password = None # srpParams[1] 249 clientCertChain = None # certParams[0] 250 privateKey = None # certParams[1] 251 252 # Allow only one of (srpParams, certParams) 253 if srpParams: 254 assert(not certParams) 255 srpUsername, password = srpParams 256 if certParams: 257 assert(not srpParams) 258 clientCertChain, privateKey = certParams 259 260 #Validate parameters 261 if srpUsername and not password: 262 raise ValueError("Caller passed a username but no password") 263 if password and not srpUsername: 264 raise ValueError("Caller passed a password but no username") 265 if clientCertChain and not privateKey: 266 raise ValueError("Caller passed a certChain but no privateKey") 267 if privateKey and not clientCertChain: 268 raise ValueError("Caller passed a privateKey but no certChain") 269 if reqTack and not tackpyLoaded: 270 raise ValueError("TACKpy is not loaded") 271 272 # Validates the settings and filters out any unsupported ciphers 273 # or crypto libraries that were requested 274 if not settings: 275 settings = HandshakeSettings() 276 settings = settings._filter() 277 278 if clientCertChain: 279 if not isinstance(clientCertChain, X509CertChain): 280 raise ValueError("Unrecognized certificate type") 281 if "x509" not in settings.certificateTypes: 282 raise ValueError("Client certificate doesn't match "\ 283 "Handshake Settings") 284 285 if session: 286 # session.valid() ensures session is resumable and has 287 # non-empty sessionID 288 if not session.valid(): 289 session = None #ignore non-resumable sessions... 290 elif session.resumable and \ 291 (session.srpUsername != srpUsername): 292 raise ValueError("Session username doesn't match") 293 294 #Add Faults to parameters 295 if srpUsername and self.fault == Fault.badUsername: 296 srpUsername += "GARBAGE" 297 if password and self.fault == Fault.badPassword: 298 password += "GARBAGE" 299 300 #Tentatively set the version to the client's minimum version. 301 #We'll use this for the ClientHello, and if an error occurs 302 #parsing the Server Hello, we'll use this version for the response 303 self.version = settings.maxVersion 304 305 # OK Start sending messages! 306 # ***************************** 307 308 # Send the ClientHello. 309 for result in self._clientSendClientHello(settings, session, 310 srpUsername, srpParams, certParams, 311 reqTack): 312 if result in (0,1): yield result 313 else: break 314 clientHello = result 315 316 #Get the ServerHello. 317 for result in self._clientGetServerHello(settings, clientHello): 318 if result in (0,1): yield result 319 else: break 320 serverHello = result 321 cipherSuite = serverHello.cipher_suite 322 323 #If the server elected to resume the session, it is handled here. 324 for result in self._clientResume(session, serverHello, 325 clientHello.random, 326 settings.cipherImplementations): 327 if result in (0,1): yield result 328 else: break 329 if result == "resumed_and_finished": 330 self._handshakeDone(resumed=True) 331 return 332 333 #If the server selected an SRP ciphersuite, the client finishes 334 #reading the post-ServerHello messages, then derives a 335 #premasterSecret and sends a corresponding ClientKeyExchange. 336 if cipherSuite in CipherSuite.srpAllSuites: 337 for result in self._clientSRPKeyExchange(\ 338 settings, cipherSuite, serverHello.certificate_type, 339 srpUsername, password, 340 clientHello.random, serverHello.random, 341 serverHello.tackExt): 342 if result in (0,1): yield result 343 else: break 344 (premasterSecret, serverCertChain, tackExt) = result 345 346 #If the server selected a certificate-based RSA ciphersuite, 347 #the client finishes reading the post-ServerHello messages. If 348 #a CertificateRequest message was sent, the client responds with 349 #a Certificate message containing its certificate chain (if any), 350 #and also produces a CertificateVerify message that signs the 351 #ClientKeyExchange. 352 else: 353 for result in self._clientRSAKeyExchange(settings, cipherSuite, 354 clientCertChain, privateKey, 355 serverHello.certificate_type, 356 clientHello.random, serverHello.random, 357 serverHello.tackExt): 358 if result in (0,1): yield result 359 else: break 360 (premasterSecret, serverCertChain, clientCertChain, 361 tackExt) = result 362 363 #After having previously sent a ClientKeyExchange, the client now 364 #initiates an exchange of Finished messages. 365 for result in self._clientFinished(premasterSecret, 366 clientHello.random, 367 serverHello.random, 368 cipherSuite, settings.cipherImplementations): 369 if result in (0,1): yield result 370 else: break 371 masterSecret = result 372 373 # Create the session object which is used for resumptions 374 self.session = Session() 375 self.session.create(masterSecret, serverHello.session_id, cipherSuite, 376 srpUsername, clientCertChain, serverCertChain, 377 tackExt) 378 self._handshakeDone(resumed=False)
379 380
381 - def _clientSendClientHello(self, settings, session, srpUsername, 382 srpParams, certParams, reqTack):
383 #Initialize acceptable ciphersuites 384 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 385 if srpParams: 386 cipherSuites += CipherSuite.getSrpAllSuites(settings.cipherNames) 387 elif certParams: 388 cipherSuites += CipherSuite.getCertSuites(settings.cipherNames) 389 else: 390 cipherSuites += CipherSuite.getCertSuites(settings.cipherNames) 391 392 #Initialize acceptable certificate types 393 certificateTypes = settings._getCertificateTypes() 394 395 #Either send ClientHello (with a resumable session)... 396 if session and session.sessionID: 397 #If it's resumable, then its 398 #ciphersuite must be one of the acceptable ciphersuites 399 if session.cipherSuite not in cipherSuites: 400 raise ValueError("Session's cipher suite not consistent "\ 401 "with parameters") 402 else: 403 clientHello = ClientHello() 404 clientHello.create(settings.maxVersion, getRandomBytes(32), 405 session.sessionID, cipherSuites, 406 certificateTypes, session.srpUsername, 407 reqTack) 408 409 #Or send ClientHello (without) 410 else: 411 clientHello = ClientHello() 412 clientHello.create(settings.maxVersion, getRandomBytes(32), 413 createByteArraySequence([]), cipherSuites, 414 certificateTypes, srpUsername, 415 reqTack) 416 for result in self._sendMsg(clientHello): 417 yield result 418 yield clientHello
419 420
421 - def _clientGetServerHello(self, settings, clientHello):
422 for result in self._getMsg(ContentType.handshake, 423 HandshakeType.server_hello): 424 if result in (0,1): yield result 425 else: break 426 serverHello = result 427 428 #Get the server version. Do this before anything else, so any 429 #error alerts will use the server's version 430 self.version = serverHello.server_version 431 432 #Future responses from server must use this version 433 self._versionCheck = True 434 435 #Check ServerHello 436 if serverHello.server_version < settings.minVersion: 437 for result in self._sendError(\ 438 AlertDescription.protocol_version, 439 "Too old version: %s" % str(serverHello.server_version)): 440 yield result 441 if serverHello.server_version > settings.maxVersion: 442 for result in self._sendError(\ 443 AlertDescription.protocol_version, 444 "Too new version: %s" % str(serverHello.server_version)): 445 yield result 446 if serverHello.cipher_suite not in clientHello.cipher_suites: 447 for result in self._sendError(\ 448 AlertDescription.illegal_parameter, 449 "Server responded with incorrect ciphersuite"): 450 yield result 451 if serverHello.certificate_type not in clientHello.certificate_types: 452 for result in self._sendError(\ 453 AlertDescription.illegal_parameter, 454 "Server responded with incorrect certificate type"): 455 yield result 456 if serverHello.compression_method != 0: 457 for result in self._sendError(\ 458 AlertDescription.illegal_parameter, 459 "Server responded with incorrect compression method"): 460 yield result 461 if serverHello.tackExt and not clientHello.tack: 462 for result in self._sendError(\ 463 AlertDescription.illegal_parameter, 464 "Server responded with unrequested TACK Extension"): 465 yield result 466 yield serverHello
467
468 - def _clientResume(self, session, serverHello, clientRandom, 469 cipherImplementations):
470 #If the server agrees to resume 471 if session and session.sessionID and \ 472 serverHello.session_id == session.sessionID: 473 474 if serverHello.cipher_suite != session.cipherSuite: 475 for result in self._sendError(\ 476 AlertDescription.illegal_parameter,\ 477 "Server's ciphersuite doesn't match session"): 478 yield result 479 480 #Calculate pending connection states 481 self._calcPendingStates(session.cipherSuite, 482 session.masterSecret, 483 clientRandom, serverHello.random, 484 cipherImplementations) 485 486 #Exchange ChangeCipherSpec and Finished messages 487 for result in self._getFinished(session.masterSecret): 488 yield result 489 for result in self._sendFinished(session.masterSecret): 490 yield result 491 492 #Set the session for this connection 493 self.session = session 494 yield "resumed_and_finished"
495
496 - def _clientSRPKeyExchange(self, settings, cipherSuite, certificateType, 497 srpUsername, password, 498 clientRandom, serverRandom, tackExt):
499 500 #If the server chose an SRP+RSA suite... 501 if cipherSuite in CipherSuite.srpCertSuites: 502 #Get Certificate, ServerKeyExchange, ServerHelloDone 503 for result in self._getMsg(ContentType.handshake, 504 HandshakeType.certificate, certificateType): 505 if result in (0,1): yield result 506 else: break 507 serverCertificate = result 508 else: 509 serverCertificate = None 510 511 for result in self._getMsg(ContentType.handshake, 512 HandshakeType.server_key_exchange, cipherSuite): 513 if result in (0,1): yield result 514 else: break 515 serverKeyExchange = result 516 517 for result in self._getMsg(ContentType.handshake, 518 HandshakeType.server_hello_done): 519 if result in (0,1): yield result 520 else: break 521 serverHelloDone = result 522 523 #Calculate SRP premaster secret 524 #Get and check the server's group parameters and B value 525 N = serverKeyExchange.srp_N 526 g = serverKeyExchange.srp_g 527 s = serverKeyExchange.srp_s 528 B = serverKeyExchange.srp_B 529 530 if (g,N) not in goodGroupParameters: 531 for result in self._sendError(\ 532 AlertDescription.insufficient_security, 533 "Unknown group parameters"): 534 yield result 535 if numBits(N) < settings.minKeySize: 536 for result in self._sendError(\ 537 AlertDescription.insufficient_security, 538 "N value is too small: %d" % numBits(N)): 539 yield result 540 if numBits(N) > settings.maxKeySize: 541 for result in self._sendError(\ 542 AlertDescription.insufficient_security, 543 "N value is too large: %d" % numBits(N)): 544 yield result 545 if B % N == 0: 546 for result in self._sendError(\ 547 AlertDescription.illegal_parameter, 548 "Suspicious B value"): 549 yield result 550 551 #Check the server's signature, if server chose an 552 #SRP+RSA suite 553 serverCertChain = None 554 if cipherSuite in CipherSuite.srpCertSuites: 555 #Hash ServerKeyExchange/ServerSRPParams 556 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom) 557 558 #Extract signature bytes from ServerKeyExchange 559 sigBytes = serverKeyExchange.signature 560 if len(sigBytes) == 0: 561 for result in self._sendError(\ 562 AlertDescription.illegal_parameter, 563 "Server sent an SRP ServerKeyExchange "\ 564 "message without a signature"): 565 yield result 566 567 # Get server's public key from the Certificate message 568 # Also validate the chain against the ServerHello's TACKext (if any) 569 # If none, and a TACK cert is present, return its TACKext 570 for result in self._clientGetKeyFromChain(serverCertificate, 571 settings, tackExt): 572 if result in (0,1): yield result 573 else: break 574 publicKey, serverCertChain, tackExt = result 575 576 #Verify signature 577 if not publicKey.verify(sigBytes, hashBytes): 578 for result in self._sendError(\ 579 AlertDescription.decrypt_error, 580 "Signature failed to verify"): 581 yield result 582 583 #Calculate client's ephemeral DH values (a, A) 584 a = bytesToNumber(getRandomBytes(32)) 585 A = powMod(g, a, N) 586 587 #Calculate client's static DH values (x, v) 588 x = makeX(bytesToString(s), srpUsername, password) 589 v = powMod(g, x, N) 590 591 #Calculate u 592 u = makeU(N, A, B) 593 594 #Calculate premaster secret 595 k = makeK(N, g) 596 S = powMod((B - (k*v)) % N, a+(u*x), N) 597 598 if self.fault == Fault.badA: 599 A = N 600 S = 0 601 602 premasterSecret = numberToBytes(S) 603 604 #Send ClientKeyExchange 605 for result in self._sendMsg(\ 606 ClientKeyExchange(cipherSuite).createSRP(A)): 607 yield result 608 yield (premasterSecret, serverCertChain, tackExt)
609 610
611 - def _clientRSAKeyExchange(self, settings, cipherSuite, 612 clientCertChain, privateKey, 613 certificateType, 614 clientRandom, serverRandom, 615 tackExt):
616 617 #Get Certificate[, CertificateRequest], ServerHelloDone 618 for result in self._getMsg(ContentType.handshake, 619 HandshakeType.certificate, certificateType): 620 if result in (0,1): yield result 621 else: break 622 serverCertificate = result 623 624 # Get CertificateRequest or ServerHelloDone 625 for result in self._getMsg(ContentType.handshake, 626 (HandshakeType.server_hello_done, 627 HandshakeType.certificate_request)): 628 if result in (0,1): yield result 629 else: break 630 msg = result 631 certificateRequest = None 632 if isinstance(msg, CertificateRequest): 633 certificateRequest = msg 634 # We got CertificateRequest, so this must be ServerHelloDone 635 for result in self._getMsg(ContentType.handshake, 636 HandshakeType.server_hello_done): 637 if result in (0,1): yield result 638 else: break 639 serverHelloDone = result 640 elif isinstance(msg, ServerHelloDone): 641 serverHelloDone = msg 642 643 # Get server's public key from the Certificate message 644 # Also validate the chain against the ServerHello's TACKext (if any) 645 # If none, and a TACK cert is present, return its TACKext 646 for result in self._clientGetKeyFromChain(serverCertificate, 647 settings, tackExt): 648 if result in (0,1): yield result 649 else: break 650 publicKey, serverCertChain, tackExt = result 651 652 #Calculate premaster secret 653 premasterSecret = getRandomBytes(48) 654 premasterSecret[0] = settings.maxVersion[0] 655 premasterSecret[1] = settings.maxVersion[1] 656 657 if self.fault == Fault.badPremasterPadding: 658 premasterSecret[0] = 5 659 if self.fault == Fault.shortPremasterSecret: 660 premasterSecret = premasterSecret[:-1] 661 662 #Encrypt premaster secret to server's public key 663 encryptedPreMasterSecret = publicKey.encrypt(premasterSecret) 664 665 #If client authentication was requested, send Certificate 666 #message, either with certificates or empty 667 if certificateRequest: 668 clientCertificate = Certificate(certificateType) 669 670 if clientCertChain: 671 #Check to make sure we have the same type of 672 #certificates the server requested 673 wrongType = False 674 if certificateType == CertificateType.x509: 675 if not isinstance(clientCertChain, X509CertChain): 676 wrongType = True 677 if wrongType: 678 for result in self._sendError(\ 679 AlertDescription.handshake_failure, 680 "Client certificate is of wrong type"): 681 yield result 682 683 clientCertificate.create(clientCertChain) 684 for result in self._sendMsg(clientCertificate): 685 yield result 686 else: 687 #The server didn't request client auth, so we 688 #zeroize these so the clientCertChain won't be 689 #stored in the session. 690 privateKey = None 691 clientCertChain = None 692 693 #Send ClientKeyExchange 694 clientKeyExchange = ClientKeyExchange(cipherSuite, 695 self.version) 696 clientKeyExchange.createRSA(encryptedPreMasterSecret) 697 for result in self._sendMsg(clientKeyExchange): 698 yield result 699 700 #If client authentication was requested and we have a 701 #private key, send CertificateVerify 702 if certificateRequest and privateKey: 703 if self.version == (3,0): 704 masterSecret = calcMasterSecret(self.version, 705 premasterSecret, 706 clientRandom, 707 serverRandom) 708 verifyBytes = self._calcSSLHandshakeHash(masterSecret, "") 709 elif self.version in ((3,1), (3,2)): 710 verifyBytes = stringToBytes(\ 711 self._handshake_md5.digest() + \ 712 self._handshake_sha.digest()) 713 if self.fault == Fault.badVerifyMessage: 714 verifyBytes[0] = ((verifyBytes[0]+1) % 256) 715 signedBytes = privateKey.sign(verifyBytes) 716 certificateVerify = CertificateVerify() 717 certificateVerify.create(signedBytes) 718 for result in self._sendMsg(certificateVerify): 719 yield result 720 yield (premasterSecret, serverCertChain, clientCertChain, tackExt)
721
722 - def _clientFinished(self, premasterSecret, clientRandom, serverRandom, 723 cipherSuite, cipherImplementations):
724 725 masterSecret = calcMasterSecret(self.version, premasterSecret, 726 clientRandom, serverRandom) 727 self._calcPendingStates(cipherSuite, masterSecret, 728 clientRandom, serverRandom, 729 cipherImplementations) 730 731 #Exchange ChangeCipherSpec and Finished messages 732 for result in self._sendFinished(masterSecret): 733 yield result 734 for result in self._getFinished(masterSecret): 735 yield result 736 yield masterSecret
737
738 - def _clientGetKeyFromChain(self, certificate, settings, tackExt=None):
739 #Get and check cert chain from the Certificate message 740 certChain = certificate.certChain 741 if not certChain or certChain.getNumCerts() == 0: 742 for result in self._sendError(AlertDescription.illegal_parameter, 743 "Other party sent a Certificate message without "\ 744 "certificates"): 745 yield result 746 747 #Get and check public key from the cert chain 748 publicKey = certChain.getEndEntityPublicKey() 749 if len(publicKey) < settings.minKeySize: 750 for result in self._sendError(AlertDescription.handshake_failure, 751 "Other party's public key too small: %d" % len(publicKey)): 752 yield result 753 if len(publicKey) > settings.maxKeySize: 754 for result in self._sendError(AlertDescription.handshake_failure, 755 "Other party's public key too large: %d" % len(publicKey)): 756 yield result 757 758 # If there's no TLS Extension, look for a TACK cert 759 if tackpyLoaded: 760 if not tackExt: 761 tackExt = certChain.getTackExt() 762 763 # If there's a TACK (whether via TLS or TACK Cert), check that it 764 # matches the cert chain 765 if tackExt and tackExt.tack and \ 766 not certChain.checkTack(tackExt.tack): 767 for result in self._sendError(AlertDescription.handshake_failure, 768 "Other party's TACK doesn't match their cert chain"): 769 yield result 770 771 yield publicKey, certChain, tackExt
772 773 774 #********************************************************* 775 # Server Handshake Functions 776 #********************************************************* 777 778
779 - def handshakeServer(self, verifierDB=None, 780 certChain=None, privateKey=None, reqCert=False, 781 sessionCache=None, settings=None, checker=None, 782 reqCAs = None, tack=None, breakSigs=None):
783 """Perform a handshake in the role of server. 784 785 This function performs an SSL or TLS handshake. Depending on 786 the arguments and the behavior of the client, this function can 787 perform an SRP, or certificate-based handshake. It 788 can also perform a combined SRP and server-certificate 789 handshake. 790 791 Like any handshake function, this can be called on a closed 792 TLS connection, or on a TLS connection that is already open. 793 If called on an open connection it performs a re-handshake. 794 This function does not send a Hello Request message before 795 performing the handshake, so if re-handshaking is required, 796 the server must signal the client to begin the re-handshake 797 through some other means. 798 799 If the function completes without raising an exception, the 800 TLS connection will be open and available for data transfer. 801 802 If an exception is raised, the connection will have been 803 automatically closed (if it was ever open). 804 805 @type verifierDB: L{tlslite.verifierdb.VerifierDB} 806 @param verifierDB: A database of SRP password verifiers 807 associated with usernames. If the client performs an SRP 808 handshake, the session's srpUsername attribute will be set. 809 810 @type certChain: L{tlslite.x509certchain.X509CertChain} 811 @param certChain: The certificate chain to be used if the 812 client requests server certificate authentication. 813 814 @type privateKey: L{tlslite.utils.rsakey.RSAKey} 815 @param privateKey: The private key to be used if the client 816 requests server certificate authentication. 817 818 @type reqCert: bool 819 @param reqCert: Whether to request client certificate 820 authentication. This only applies if the client chooses server 821 certificate authentication; if the client chooses SRP 822 authentication, this will be ignored. If the client 823 performs a client certificate authentication, the sessions's 824 clientCertChain attribute will be set. 825 826 @type sessionCache: L{tlslite.sessioncache.SessionCache} 827 @param sessionCache: An in-memory cache of resumable sessions. 828 The client can resume sessions from this cache. Alternatively, 829 if the client performs a full handshake, a new session will be 830 added to the cache. 831 832 @type settings: L{tlslite.handshakesettings.HandshakeSettings} 833 @param settings: Various settings which can be used to control 834 the ciphersuites and SSL/TLS version chosen by the server. 835 836 @type checker: L{tlslite.checker.Checker} 837 @param checker: A Checker instance. This instance will be 838 invoked to examine the other party's authentication 839 credentials, if the handshake completes succesfully. 840 841 @type reqCAs: list of L{bytearray} of unsigned bytes 842 @param reqCAs: A collection of DER-encoded DistinguishedNames that 843 will be sent along with a certificate request. This does not affect 844 verification. 845 846 @raise socket.error: If a socket error occurs. 847 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 848 without a preceding alert. 849 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 850 @raise tlslite.errors.TLSAuthenticationError: If the checker 851 doesn't like the other party's authentication credentials. 852 """ 853 for result in self.handshakeServerAsync(verifierDB, 854 certChain, privateKey, reqCert, sessionCache, settings, 855 checker, reqCAs, tack=tack, breakSigs=breakSigs): 856 pass
857 858
859 - def handshakeServerAsync(self, verifierDB=None, 860 certChain=None, privateKey=None, reqCert=False, 861 sessionCache=None, settings=None, checker=None, 862 reqCAs=None, tack=None, breakSigs=None):
863 """Start a server handshake operation on the TLS connection. 864 865 This function returns a generator which behaves similarly to 866 handshakeServer(). Successive invocations of the generator 867 will return 0 if it is waiting to read from the socket, 1 if it is 868 waiting to write to the socket, or it will raise StopIteration 869 if the handshake operation is complete. 870 871 @rtype: iterable 872 @return: A generator; see above for details. 873 """ 874 handshaker = self._handshakeServerAsyncHelper(\ 875 verifierDB=verifierDB, certChain=certChain, 876 privateKey=privateKey, reqCert=reqCert, 877 sessionCache=sessionCache, settings=settings, 878 reqCAs=reqCAs, tack=tack, breakSigs=breakSigs) 879 for result in self._handshakeWrapperAsync(handshaker, checker): 880 yield result
881 882
883 - def _handshakeServerAsyncHelper(self, verifierDB, 884 certChain, privateKey, reqCert, sessionCache, 885 settings, reqCAs, tack, breakSigs):
886 887 self._handshakeStart(client=False) 888 889 if (not verifierDB) and (not certChain): 890 raise ValueError("Caller passed no authentication credentials") 891 if certChain and not privateKey: 892 raise ValueError("Caller passed a certChain but no privateKey") 893 if privateKey and not certChain: 894 raise ValueError("Caller passed a privateKey but no certChain") 895 if reqCAs and not reqCert: 896 raise ValueError("Caller passed reqCAs but not reqCert") 897 if certChain and not isinstance(certChain, X509CertChain): 898 raise ValueError("Unrecognized certificate type") 899 if (tack or breakSigs) and not tackpyLoaded: 900 raise ValueError("TACKpy is not loaded") 901 902 if not settings: 903 settings = HandshakeSettings() 904 settings = settings._filter() 905 906 # OK Start exchanging messages 907 # ****************************** 908 909 # Handle ClientHello and resumption 910 for result in self._serverGetClientHello(settings, certChain,\ 911 verifierDB, sessionCache): 912 if result in (0,1): yield result 913 elif result == None: 914 self._handshakeDone(resumed=True) 915 return # Handshake was resumed, we're done 916 else: break 917 (clientHello, cipherSuite) = result 918 919 #If not a resumption... 920 921 # Create the ServerHello message 922 if sessionCache: 923 sessionID = getRandomBytes(32) 924 else: 925 sessionID = createByteArraySequence([]) 926 927 # If not doing a certificate-based suite, discard the TACK 928 if not cipherSuite in CipherSuite.certAllSuites: 929 tack = None 930 931 # Prepare a TACK Extension if requested 932 if clientHello.tack: 933 tackExt = TACK_Extension() 934 tackExt.create(tack, breakSigs) 935 else: 936 tackExt = None 937 serverHello = ServerHello() 938 serverHello.create(self.version, getRandomBytes(32), sessionID, \ 939 cipherSuite, CertificateType.x509, tackExt) 940 941 # Perform the SRP key exchange 942 clientCertChain = None 943 if cipherSuite in CipherSuite.srpAllSuites: 944 for result in self._serverSRPKeyExchange(clientHello, serverHello, 945 verifierDB, cipherSuite, 946 privateKey, certChain): 947 if result in (0,1): yield result 948 else: break 949 premasterSecret = result 950 951 952 # Perform the RSA key exchange 953 elif cipherSuite in CipherSuite.certSuites: 954 for result in self._serverCertKeyExchange(clientHello, serverHello, 955 certChain, privateKey, 956 reqCert, reqCAs, cipherSuite, 957 settings): 958 if result in (0,1): yield result 959 else: break 960 (premasterSecret, clientCertChain) = result 961 962 # Exchange Finished messages 963 for result in self._serverFinished(premasterSecret, 964 clientHello.random, serverHello.random, 965 cipherSuite, settings.cipherImplementations): 966 if result in (0,1): yield result 967 else: break 968 masterSecret = result 969 970 #Create the session object 971 self.session = Session() 972 if cipherSuite in CipherSuite.certAllSuites: 973 serverCertChain = certChain 974 else: 975 serverCertChain = None 976 self.session.create(masterSecret, serverHello.session_id, cipherSuite, 977 clientHello.srp_username, clientCertChain, serverCertChain, 978 tackExt) 979 980 #Add the session object to the session cache 981 if sessionCache and sessionID: 982 sessionCache[bytesToString(sessionID)] = self.session 983 984 self._handshakeDone(resumed=False)
985 986
987 - def _serverGetClientHello(self, settings, certChain, verifierDB, 988 sessionCache):
989 #Initialize acceptable cipher suites 990 cipherSuites = [] 991 if verifierDB: 992 if certChain: 993 cipherSuites += \ 994 CipherSuite.getSrpCertSuites(settings.cipherNames) 995 cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames) 996 elif certChain: 997 cipherSuites += CipherSuite.getCertSuites(settings.cipherNames) 998 else: 999 assert(False) 1000 1001 #Tentatively set version to most-desirable version, so if an error 1002 #occurs parsing the ClientHello, this is what we'll use for the 1003 #error alert 1004 self.version = settings.maxVersion 1005 1006 #Get ClientHello 1007 for result in self._getMsg(ContentType.handshake, 1008 HandshakeType.client_hello): 1009 if result in (0,1): yield result 1010 else: break 1011 clientHello = result 1012 1013 #If client's version is too low, reject it 1014 if clientHello.client_version < settings.minVersion: 1015 self.version = settings.minVersion 1016 for result in self._sendError(\ 1017 AlertDescription.protocol_version, 1018 "Too old version: %s" % str(clientHello.client_version)): 1019 yield result 1020 1021 #If client's version is too high, propose my highest version 1022 elif clientHello.client_version > settings.maxVersion: 1023 self.version = settings.maxVersion 1024 1025 else: 1026 #Set the version to the client's version 1027 self.version = clientHello.client_version 1028 1029 #If resumption was requested and we have a session cache... 1030 if clientHello.session_id and sessionCache: 1031 session = None 1032 1033 #Check in the session cache 1034 if sessionCache and not session: 1035 try: 1036 session = sessionCache[bytesToString(\ 1037 clientHello.session_id)] 1038 if not session.resumable: 1039 raise AssertionError() 1040 #Check for consistency with ClientHello 1041 if session.cipherSuite not in cipherSuites: 1042 for result in self._sendError(\ 1043 AlertDescription.handshake_failure): 1044 yield result 1045 if session.cipherSuite not in clientHello.cipher_suites: 1046 for result in self._sendError(\ 1047 AlertDescription.handshake_failure): 1048 yield result 1049 if clientHello.srp_username: 1050 if clientHello.srp_username != session.srpUsername: 1051 for result in self._sendError(\ 1052 AlertDescription.handshake_failure): 1053 yield result 1054 except KeyError: 1055 pass 1056 1057 #If a session is found.. 1058 if session: 1059 #Send ServerHello 1060 serverHello = ServerHello() 1061 serverHello.create(self.version, getRandomBytes(32), 1062 session.sessionID, session.cipherSuite, 1063 CertificateType.x509, None) 1064 for result in self._sendMsg(serverHello): 1065 yield result 1066 1067 #From here on, the client's messages must have right version 1068 self._versionCheck = True 1069 1070 #Calculate pending connection states 1071 self._calcPendingStates(session.cipherSuite, 1072 session.masterSecret, 1073 clientHello.random, 1074 serverHello.random, 1075 settings.cipherImplementations) 1076 1077 #Exchange ChangeCipherSpec and Finished messages 1078 for result in self._sendFinished(session.masterSecret): 1079 yield result 1080 for result in self._getFinished(session.masterSecret): 1081 yield result 1082 1083 #Set the session 1084 self.session = session 1085 1086 yield None # Handshake done! 1087 1088 #Calculate the first cipher suite intersection. 1089 #This is the 'privileged' ciphersuite. We'll use it if we're 1090 #doing a new negotiation. In fact, 1091 #the only time we won't use it is if we're resuming a 1092 #session, in which case we use the ciphersuite from the session. 1093 # 1094 #Given the current ciphersuite ordering, this means we prefer SRP 1095 #over non-SRP. 1096 for cipherSuite in cipherSuites: 1097 if cipherSuite in clientHello.cipher_suites: 1098 break 1099 else: 1100 for result in self._sendError(\ 1101 AlertDescription.handshake_failure, 1102 "No mutual ciphersuite"): 1103 yield result 1104 1105 if cipherSuite in CipherSuite.srpAllSuites and \ 1106 not clientHello.srp_username: 1107 for result in self._sendError(\ 1108 AlertDescription.unknown_psk_identity, 1109 "Client sent a hello, but without the SRP username"): 1110 yield result 1111 1112 #If an RSA suite is chosen, check for certificate type intersection 1113 if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \ 1114 not in clientHello.certificate_types: 1115 for result in self._sendError(\ 1116 AlertDescription.handshake_failure, 1117 "the client doesn't support my certificate type"): 1118 yield result 1119 1120 # If resumption was not requested, or 1121 # we have no session cache, or 1122 # the client's session_id was not found in cache: 1123 yield (clientHello, cipherSuite)
1124
1125 - def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB, 1126 cipherSuite, privateKey, serverCertChain):
1127 1128 self.allegedSrpUsername = clientHello.srp_username 1129 #Get parameters from username 1130 try: 1131 entry = verifierDB[clientHello.srp_username] 1132 except KeyError: 1133 for result in self._sendError(\ 1134 AlertDescription.unknown_psk_identity): 1135 yield result 1136 (N, g, s, v) = entry 1137 1138 #Calculate server's ephemeral DH values (b, B) 1139 b = bytesToNumber(getRandomBytes(32)) 1140 k = makeK(N, g) 1141 B = (powMod(g, b, N) + (k*v)) % N 1142 1143 #Create ServerKeyExchange, signing it if necessary 1144 serverKeyExchange = ServerKeyExchange(cipherSuite) 1145 serverKeyExchange.createSRP(N, g, stringToBytes(s), B) 1146 if cipherSuite in CipherSuite.srpCertSuites: 1147 hashBytes = serverKeyExchange.hash(clientHello.random, 1148 serverHello.random) 1149 serverKeyExchange.signature = privateKey.sign(hashBytes) 1150 1151 #Send ServerHello[, Certificate], ServerKeyExchange, 1152 #ServerHelloDone 1153 msgs = [] 1154 msgs.append(serverHello) 1155 if cipherSuite in CipherSuite.srpCertSuites: 1156 certificateMsg = Certificate(CertificateType.x509) 1157 certificateMsg.create(serverCertChain) 1158 msgs.append(certificateMsg) 1159 msgs.append(serverKeyExchange) 1160 msgs.append(ServerHelloDone()) 1161 for result in self._sendMsgs(msgs): 1162 yield result 1163 1164 #From here on, the client's messages must have the right version 1165 self._versionCheck = True 1166 1167 #Get and check ClientKeyExchange 1168 for result in self._getMsg(ContentType.handshake, 1169 HandshakeType.client_key_exchange, 1170 cipherSuite): 1171 if result in (0,1): yield result 1172 else: break 1173 clientKeyExchange = result 1174 A = clientKeyExchange.srp_A 1175 if A % N == 0: 1176 for result in self._sendError(AlertDescription.illegal_parameter, 1177 "Suspicious A value"): 1178 yield result 1179 assert(False) # Just to ensure we don't fall through somehow 1180 1181 #Calculate u 1182 u = makeU(N, A, B) 1183 1184 #Calculate premaster secret 1185 S = powMod((A * powMod(v,u,N)) % N, b, N) 1186 premasterSecret = numberToBytes(S) 1187 1188 yield premasterSecret
1189 1190
1191 - def _serverCertKeyExchange(self, clientHello, serverHello, 1192 serverCertChain, privateKey, 1193 reqCert, reqCAs, cipherSuite, 1194 settings):
1195 #Send ServerHello, Certificate[, CertificateRequest], 1196 #ServerHelloDone 1197 msgs = [] 1198 1199 # If we verify a client cert chain, return it 1200 clientCertChain = None 1201 1202 msgs.append(serverHello) 1203 msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) 1204 if reqCert and reqCAs: 1205 msgs.append(CertificateRequest().create(\ 1206 [ClientCertificateType.rsa_sign], reqCAs)) 1207 elif reqCert: 1208 msgs.append(CertificateRequest()) 1209 msgs.append(ServerHelloDone()) 1210 for result in self._sendMsgs(msgs): 1211 yield result 1212 1213 #From here on, the client's messages must have the right version 1214 self._versionCheck = True 1215 1216 #Get [Certificate,] (if was requested) 1217 if reqCert: 1218 if self.version == (3,0): 1219 for result in self._getMsg((ContentType.handshake, 1220 ContentType.alert), 1221 HandshakeType.certificate, 1222 CertificateType.x509): 1223 if result in (0,1): yield result 1224 else: break 1225 msg = result 1226 1227 if isinstance(msg, Alert): 1228 #If it's not a no_certificate alert, re-raise 1229 alert = msg 1230 if alert.description != \ 1231 AlertDescription.no_certificate: 1232 self._shutdown(False) 1233 raise TLSRemoteAlert(alert) 1234 elif isinstance(msg, Certificate): 1235 clientCertificate = msg 1236 if clientCertificate.certChain and \ 1237 clientCertificate.certChain.getNumCerts()!=0: 1238 clientCertChain = clientCertificate.certChain 1239 else: 1240 raise AssertionError() 1241 elif self.version in ((3,1), (3,2)): 1242 for result in self._getMsg(ContentType.handshake, 1243 HandshakeType.certificate, 1244 CertificateType.x509): 1245 if result in (0,1): yield result 1246 else: break 1247 clientCertificate = result 1248 if clientCertificate.certChain and \ 1249 clientCertificate.certChain.getNumCerts()!=0: 1250 clientCertChain = clientCertificate.certChain 1251 else: 1252 raise AssertionError() 1253 1254 #Get ClientKeyExchange 1255 for result in self._getMsg(ContentType.handshake, 1256 HandshakeType.client_key_exchange, 1257 cipherSuite): 1258 if result in (0,1): yield result 1259 else: break 1260 clientKeyExchange = result 1261 1262 #Decrypt ClientKeyExchange 1263 premasterSecret = privateKey.decrypt(\ 1264 clientKeyExchange.encryptedPreMasterSecret) 1265 1266 randomPreMasterSecret = getRandomBytes(48) 1267 versionCheck = (premasterSecret[0], premasterSecret[1]) 1268 if not premasterSecret: 1269 premasterSecret = randomPreMasterSecret 1270 elif len(premasterSecret)!=48: 1271 premasterSecret = randomPreMasterSecret 1272 elif versionCheck != clientHello.client_version: 1273 if versionCheck != self.version: #Tolerate buggy IE clients 1274 premasterSecret = randomPreMasterSecret 1275 1276 #Get and check CertificateVerify, if relevant 1277 if clientCertChain: 1278 if self.version == (3,0): 1279 masterSecret = calcMasterSecret(self.version, premasterSecret, 1280 clientHello.random, serverHello.random) 1281 verifyBytes = self._calcSSLHandshakeHash(masterSecret, "") 1282 elif self.version in ((3,1), (3,2)): 1283 verifyBytes = stringToBytes(self._handshake_md5.digest() +\ 1284 self._handshake_sha.digest()) 1285 for result in self._getMsg(ContentType.handshake, 1286 HandshakeType.certificate_verify): 1287 if result in (0,1): yield result 1288 else: break 1289 certificateVerify = result 1290 publicKey = clientCertChain.getEndEntityPublicKey() 1291 if len(publicKey) < settings.minKeySize: 1292 for result in self._sendError(\ 1293 AlertDescription.handshake_failure, 1294 "Client's public key too small: %d" % len(publicKey)): 1295 yield result 1296 1297 if len(publicKey) > settings.maxKeySize: 1298 for result in self._sendError(\ 1299 AlertDescription.handshake_failure, 1300 "Client's public key too large: %d" % len(publicKey)): 1301 yield result 1302 1303 if not publicKey.verify(certificateVerify.signature, verifyBytes): 1304 for result in self._sendError(\ 1305 AlertDescription.decrypt_error, 1306 "Signature failed to verify"): 1307 yield result 1308 yield (premasterSecret, clientCertChain)
1309 1310 1311
1312 - def _serverFinished(self, premasterSecret, clientRandom, serverRandom, 1313 cipherSuite, cipherImplementations):
1314 1315 masterSecret = calcMasterSecret(self.version, premasterSecret, 1316 clientRandom, serverRandom) 1317 1318 #Calculate pending connection states 1319 self._calcPendingStates(cipherSuite, masterSecret, 1320 clientRandom, serverRandom, 1321 cipherImplementations) 1322 1323 #Exchange ChangeCipherSpec and Finished messages 1324 for result in self._getFinished(masterSecret): 1325 yield result 1326 1327 for result in self._sendFinished(masterSecret): 1328 yield result 1329 1330 yield masterSecret
1331 1332 1333 #********************************************************* 1334 # Shared Handshake Functions 1335 #********************************************************* 1336 1337
1338 - def _sendFinished(self, masterSecret):
1339 #Send ChangeCipherSpec 1340 for result in self._sendMsg(ChangeCipherSpec()): 1341 yield result 1342 1343 #Switch to pending write state 1344 self._changeWriteState() 1345 1346 #Calculate verification data 1347 verifyData = self._calcFinished(masterSecret, True) 1348 if self.fault == Fault.badFinished: 1349 verifyData[0] = (verifyData[0]+1)%256 1350 1351 #Send Finished message under new state 1352 finished = Finished(self.version).create(verifyData) 1353 for result in self._sendMsg(finished): 1354 yield result
1355
1356 - def _getFinished(self, masterSecret):
1357 #Get and check ChangeCipherSpec 1358 for result in self._getMsg(ContentType.change_cipher_spec): 1359 if result in (0,1): 1360 yield result 1361 changeCipherSpec = result 1362 1363 if changeCipherSpec.type != 1: 1364 for result in self._sendError(AlertDescription.illegal_parameter, 1365 "ChangeCipherSpec type incorrect"): 1366 yield result 1367 1368 #Switch to pending read state 1369 self._changeReadState() 1370 1371 #Calculate verification data 1372 verifyData = self._calcFinished(masterSecret, False) 1373 1374 #Get and check Finished message under new state 1375 for result in self._getMsg(ContentType.handshake, 1376 HandshakeType.finished): 1377 if result in (0,1): 1378 yield result 1379 finished = result 1380 if finished.verify_data != verifyData: 1381 for result in self._sendError(AlertDescription.decrypt_error, 1382 "Finished message is incorrect"): 1383 yield result
1384
1385 - def _calcFinished(self, masterSecret, send=True):
1386 if self.version == (3,0): 1387 if (self._client and send) or (not self._client and not send): 1388 senderStr = "\x43\x4C\x4E\x54" 1389 else: 1390 senderStr = "\x53\x52\x56\x52" 1391 1392 verifyData = self._calcSSLHandshakeHash(masterSecret, senderStr) 1393 return verifyData 1394 1395 elif self.version in ((3,1), (3,2)): 1396 if (self._client and send) or (not self._client and not send): 1397 label = "client finished" 1398 else: 1399 label = "server finished" 1400 1401 handshakeHashes = stringToBytes(self._handshake_md5.digest() + \ 1402 self._handshake_sha.digest()) 1403 verifyData = PRF(masterSecret, label, handshakeHashes, 12) 1404 return verifyData 1405 else: 1406 raise AssertionError()
1407 1408
1409 - def _handshakeWrapperAsync(self, handshaker, checker):
1410 if not self.fault: 1411 try: 1412 for result in handshaker: 1413 yield result 1414 if checker: 1415 try: 1416 checker(self) 1417 except TLSAuthenticationError: 1418 alert = Alert().create(AlertDescription.close_notify, 1419 AlertLevel.fatal) 1420 for result in self._sendMsg(alert): 1421 yield result 1422 raise 1423 except GeneratorExit: 1424 raise 1425 except TLSAlert, alert: 1426 if not self.fault: 1427 raise 1428 if alert.description not in Fault.faultAlerts[self.fault]: 1429 raise TLSFaultError(str(alert)) 1430 else: 1431 pass 1432 except: 1433 self._shutdown(False) 1434 raise
1435