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