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