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