/gdata/tlslite/TLSConnection.py
Python | 1487 lines | 1233 code | 120 blank | 134 comment | 244 complexity | 488f8801392a6ecc58a9c48c0afcc63c MD5 | raw file
Large files files are truncated, but you can click here to view the full file
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._getFinished(): 615 yield result 616 for result in self._sendFinished(): 617 yield result 618 619 #Mark the connection as open 620 self._handshakeDone(resumed=True) 621 622 #If server DOES NOT agree to resume 623 else: 624 625 if sharedKeyParams: 626 for result in self._sendError(\ 627 AlertDescription.user_canceled, 628 "Was expecting a shared-key resumption"): 629 yield result 630 631 #We've already validated these 632 cipherSuite = serverHello.cipher_suite 633 certificateType = serverHello.certificate_type 634 635 #If the server chose an SRP suite... 636 if cipherSuite in CipherSuite.srpSuites: 637 #Get ServerKeyExchange, ServerHelloDone 638 for result in self._getMsg(ContentType.handshake, 639 HandshakeType.server_key_exchange, cipherSuite): 640 if result in (0,1): 641 yield result 642 else: 643 break 644 serverKeyExchange = result 645 646 for result in self._getMsg(ContentType.handshake, 647 HandshakeType.server_hello_done): 648 if result in (0,1): 649 yield result 650 else: 651 break 652 serverHelloDone = result 653 654 #If the server chose an SRP+RSA suite... 655 elif cipherSuite in CipherSuite.srpRsaSuites: 656 #Get Certificate, ServerKeyExchange, ServerHelloDone 657 for result in self._getMsg(ContentType.handshake, 658 HandshakeType.certificate, certificateType): 659 if result in (0,1): 660 yield result 661 else: 662 break 663 serverCertificate = result 664 665 for result in self._getMsg(ContentType.handshake, 666 HandshakeType.server_key_exchange, cipherSuite): 667 if result in (0,1): 668 yield result 669 else: 670 break 671 serverKeyExchange = result 672 673 for result in self._getMsg(ContentType.handshake, 674 HandshakeType.server_hello_done): 675 if result in (0,1): 676 yield result 677 else: 678 break 679 serverHelloDone = result 680 681 #If the server chose an RSA suite... 682 elif cipherSuite in CipherSuite.rsaSuites: 683 #Get Certificate[, CertificateRequest], ServerHelloDone 684 for result in self._getMsg(ContentType.handshake, 685 HandshakeType.certificate, certificateType): 686 if result in (0,1): 687 yield result 688 else: 689 break 690 serverCertificate = result 691 692 for result in self._getMsg(ContentType.handshake, 693 (HandshakeType.server_hello_done, 694 HandshakeType.certificate_request)): 695 if result in (0,1): 696 yield result 697 else: 698 break 699 msg = result 700 701 certificateRequest = None 702 if isinstance(msg, CertificateRequest): 703 certificateRequest = msg 704 for result in self._getMsg(ContentType.handshake, 705 HandshakeType.server_hello_done): 706 if result in (0,1): 707 yield result 708 else: 709 break 710 serverHelloDone = result 711 elif isinstance(msg, ServerHelloDone): 712 serverHelloDone = msg 713 else: 714 raise AssertionError() 715 716 717 #Calculate SRP premaster secret, if server chose an SRP or 718 #SRP+RSA suite 719 if cipherSuite in CipherSuite.srpSuites + \ 720 CipherSuite.srpRsaSuites: 721 #Get and check the server's group parameters and B value 722 N = serverKeyExchange.srp_N 723 g = serverKeyExchange.srp_g 724 s = serverKeyExchange.srp_s 725 B = serverKeyExchange.srp_B 726 727 if (g,N) not in goodGroupParameters: 728 for result in self._sendError(\ 729 AlertDescription.untrusted_srp_parameters, 730 "Unknown group parameters"): 731 yield result 732 if numBits(N) < settings.minKeySize: 733 for result in self._sendError(\ 734 AlertDescription.untrusted_srp_parameters, 735 "N value is too small: %d" % numBits(N)): 736 yield result 737 if numBits(N) > settings.maxKeySize: 738 for result in self._sendError(\ 739 AlertDescription.untrusted_srp_parameters, 740 "N value is too large: %d" % numBits(N)): 741 yield result 742 if B % N == 0: 743 for result in self._sendError(\ 744 AlertDescription.illegal_parameter, 745 "Suspicious B value"): 746 yield result 747 748 #Check the server's signature, if server chose an 749 #SRP+RSA suite 750 if cipherSuite in CipherSuite.srpRsaSuites: 751 #Hash ServerKeyExchange/ServerSRPParams 752 hashBytes = serverKeyExchange.hash(clientRandom, 753 serverRandom) 754 755 #Extract signature bytes from ServerKeyExchange 756 sigBytes = serverKeyExchange.signature 757 if len(sigBytes) == 0: 758 for result in self._sendError(\ 759 AlertDescription.illegal_parameter, 760 "Server sent an SRP ServerKeyExchange "\ 761 "message without a signature"): 762 yield result 763 764 #Get server's public key from the Certificate message 765 for result in self._getKeyFromChain(serverCertificate, 766 settings): 767 if result in (0,1): 768 yield result 769 else: 770 break 771 publicKey, serverCertChain = result 772 773 #Verify signature 774 if not publicKey.verify(sigBytes, hashBytes): 775 for result in self._sendError(\ 776 AlertDescription.decrypt_error, 777 "Signature failed to verify"): 778 yield result 779 780 781 #Calculate client's ephemeral DH values (a, A) 782 a = bytesToNumber(getRandomBytes(32)) 783 A = powMod(g, a, N) 784 785 #Calculate client's static DH values (x, v) 786 x = makeX(bytesToString(s), srpUsername, password) 787 v = powMod(g, x, N) 788 789 #Calculate u 790 u = makeU(N, A, B) 791 792 #Calculate premaster secret 793 k = makeK(N, g) 794 S = powMod((B - (k*v)) % N, a+(u*x), N) 795 796 if self.fault == Fault.badA: 797 A = N 798 S = 0 799 premasterSecret = numberToBytes(S) 800 801 #Send ClientKeyExchange 802 for result in self._sendMsg(\ 803 ClientKeyExchange(cipherSuite).createSRP(A)): 804 yield result 805 806 807 #Calculate RSA premaster secret, if server chose an RSA suite 808 elif cipherSuite in CipherSuite.rsaSuites: 809 810 #Handle the presence of a CertificateRequest 811 if certificateRequest: 812 if unknownParams and certCallback: 813 certParamsNew = certCallback() 814 if certParamsNew: 815 clientCertChain, privateKey = certParamsNew 816 817 #Get server's public key from the Certificate message 818 for result in self._getKeyFromChain(serverCertificate, 819 settings): 820 if result in (0,1): 821 yield result 822 else: 823 break 824 publicKey, serverCertChain = result 825 826 827 #Calculate premaster secret 828 premasterSecret = getRandomBytes(48) 829 premasterSecret[0] = settings.maxVersion[0] 830 premasterSecret[1] = settings.maxVersion[1] 831 832 if self.fault == Fault.badPremasterPadding: 833 premasterSecret[0] = 5 834 if self.fault == Fault.shortPremasterSecret: 835 premasterSecret = premasterSecret[:-1] 836 837 #Encrypt premaster secret to server's public key 838 encryptedPreMasterSecret = publicKey.encrypt(premasterSecret) 839 840 #If client authentication was requested, send Certificate 841 #message, either with certificates or empty 842 if certificateRequest: 843 clientCertificate = Certificate(certificateType) 844 845 if clientCertChain: 846 #Check to make sure we have the same type of 847 #certificates the server requested 848 wrongType = False 849 if certificateType == CertificateType.x509: 850 if not isinstance(clientCertChain, X509CertChain): 851 wrongType = True 852 elif certificateType == CertificateType.cryptoID: 853 if not isinstance(clientCertChain, 854 cryptoIDlib.CertChain.CertChain): 855 wrongType = True 856 if wrongType: 857 for result in self._sendError(\ 858 AlertDescription.handshake_failure, 859 "Client certificate is of wrong type"): 860 yield result 861 862 clientCertificate.create(clientCertChain) 863 864 for result in self._sendMsg(clientCertificate): 865 yield result 866 else: 867 #The server didn't request client auth, so we 868 #zeroize these so the clientCertChain won't be 869 #stored in the session. 870 privateKey = None 871 clientCertChain = None 872 873 #Send ClientKeyExchange 874 clientKeyExchange = ClientKeyExchange(cipherSuite, 875 self.version) 876 clientKeyExchange.createRSA(encryptedPreMasterSecret) 877 for result in self._sendMsg(clientKeyExchange): 878 yield result 879 880 #If client authentication was requested and we have a 881 #private key, send CertificateVerify 882 if certificateRequest and privateKey: 883 if self.version == (3,0): 884 #Create a temporary session object, just for the 885 #purpose of creating the CertificateVerify 886 session = Session() 887 session._calcMasterSecret(self.version, 888 premasterSecret, 889 clientRandom, 890 serverRandom) 891 verifyBytes = self._calcSSLHandshakeHash(\ 892 session.masterSecret, "") 893 elif self.version in ((3,1), (3,2)): 894 verifyBytes = stringToBytes(\ 895 self._handshake_md5.digest() + \ 896 self._handshake_sha.digest()) 897 if self.fault == Fault.badVerifyMessage: 898 verifyBytes[0] = ((verifyBytes[0]+1) % 256) 899 signedBytes = privateKey.sign(verifyBytes) 900 certificateVerify = CertificateVerify() 901 certificateVerify.create(signedBytes) 902 for result in self._sendMsg(certificateVerify): 903 yield result 904 905 906 #Create the session object 907 self.session = Session() 908 self.session._calcMasterSecret(self.version, premasterSecret, 909 clientRandom, serverRandom) 910 self.session.sessionID = serverHello.session_id 911 self.session.cipherSuite = cipherSuite 912 self.session.srpUsername = srpUsername 913 self.session.clientCertChain = clientCertChain 914 self.session.serverCertChain = serverCertChain 915 916 #Calculate pending connection states 917 self._calcPendingStates(clientRandom, serverRandom, 918 settings.cipherImplementations) 919 920 #Exchange ChangeCipherSpec and Finished messages 921 for result in self._sendFinished(): 922 yield result 923 for result in self._getFinished(): 924 yield result 925 926 #Mark the connection as open 927 self.session._setResumable(True) 928 self._handshakeDone(resumed=False) 929 930 931 932 def handshakeServer(self, sharedKeyDB=None, verifierDB=None, 933 certChain=None, privateKey=None, reqCert=False, 934 sessionCache=None, settings=None, checker=None): 935 """Perform a handshake in the role of server. 936 937 This function performs an SSL or TLS handshake. Depending on 938 the arguments and the behavior of the client, this function can 939 perform a shared-key, SRP, or certificate-based handshake. It 940 can also perform a combined SRP and server-certificate 941 handshake. 942 943 Like any handshake function, this can be called on a closed 944 TLS connection, or on a TLS connection that is already open. 945 If called on an open connection it performs a re-handshake. 946 This function does not send a Hello Request message before 947 performing the handshake, so if re-handshaking is required, 948 the server must signal the client to begin the re-handshake 949 through some other means. 950 951 If the function completes without raising an exception, the 952 TLS connection will be open and available for data transfer. 953 954 If an exception is raised, the connection will have been 955 automatically closed (if it was ever open). 956 957 @type sharedKeyDB: L{tlslite.SharedKeyDB.SharedKeyDB} 958 @param sharedKeyDB: A database of shared symmetric keys 959 associated with usernames. If the client performs a 960 shared-key handshake, the session's sharedKeyUsername 961 attribute will be set. 962 963 @type verifierDB: L{tlslite.VerifierDB.VerifierDB} 964 @param verifierDB: A database of SRP password verifiers 965 associated with usernames. If the client performs an SRP 966 handshake, the session's srpUsername attribute will be set. 967 968 @type certChain: L{tlslite.X509CertChain.X509CertChain} or 969 L{cryptoIDlib.CertChain.CertChain} 970 @param certChain: The certificate chain to be used if the 971 client requests server certificate authentication. 972 973 @type privateKey: L{tlslite.utils.RSAKey.RSAKey} 974 @param privateKey: The private key to be used if the client 975 requests server certificate authentication. 976 977 @type reqCert: bool 978 @param reqCert: Whether to request client certificate 979 authentication. This only applies if the client chooses server 980 certificate authentication; if the client chooses SRP or 981 shared-key authentication, this will be ignored. If the client 982 performs a client certificate authentication, the sessions's 983 clientCertChain attribute will be set. 984 985 @type sessionCache: L{tlslite.SessionCache.SessionCache} 986 @param sessionCache: An in-memory cache of resumable sessions. 987 The client can resume sessions from this cache. Alternatively, 988 if the client performs a full handshake, a new session will be 989 added to the cache. 990 991 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} 992 @param settings: Various settings which can be used to control 993 the ciphersuites and SSL/TLS version chosen by the server. 994 995 @type checker: L{tlslite.Checker.Checker} 996 @param checker: A Checker instance. This instance will be 997 invoked to examine the other party's authentication 998 credentials, if the handshake completes succesfully. 999 1000 @raise socket.error: If a socket error occurs. 1001 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 1002 without a preceding alert. 1003 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 1004 @raise tlslite.errors.TLSAuthenticationError: If the checker 1005 doesn't like the other party's authentication credentials. 1006 """ 1007 for result in self.handshakeServerAsync(sharedKeyDB, verifierDB, 1008 certChain, privateKey, reqCert, sessionCache, settings, 1009 checker): 1010 pass 1011 1012 1013 def handshakeServerAsync(self, sharedKeyDB=None, verifierDB=None, 1014 certChain=None, privateKey=None, reqCert=False, 1015 sessionCache=None, settings=None, checker=None): 1016 """Start a server handshake operation on the TLS connection. 1017 1018 This function returns a generator which behaves similarly to 1019 handshakeServer(). Successive invocations of the generator 1020 will return 0 if it is waiting to read from the socket, 1 if it is 1021 waiting to write to the socket, or it will raise StopIteration 1022 if the handshake operation is complete. 1023 1024 @rtype: iterable 1025 @return: A generator; see above for details. 1026 """ 1027 handshaker = self._handshakeServerAsyncHelper(\ 1028 sharedKeyDB=sharedKeyDB, 1029 verifierDB=verifierDB, certChain=certChain, 1030 privateKey=privateKey, reqCert=reqCert, 1031 sessionCache=sessionCache, settings=settings) 1032 for result in self._handshakeWrapperAsync(handshaker, checker): 1033 yield result 1034 1035 1036 def _handshakeServerAsyncHelper(self, sharedKeyDB, verifierDB, 1037 certChain, privateKey, reqCert, sessionCache, 1038 settings): 1039 1040 self._handshakeStart(client=False) 1041 1042 if (not sharedKeyDB) and (not verifierDB) and (not certChain): 1043 raise ValueError("Caller passed no authentication credentials") 1044 if certChain and not privateKey: 1045 raise ValueError("Caller passed a certChain but no privateKey") 1046 if privateKey and not certChain: 1047 raise ValueError("Caller passed a privateKey but no certChain") 1048 1049 if not settings: 1050 settings = HandshakeSettings() 1051 settings = settings._filter() 1052 1053 #Initialize acceptable cipher suites 1054 cipherSuites = [] 1055 if verifierDB: 1056 if certChain: 1057 cipherSuites += \ 1058 CipherSuite.getSrpRsaSuites(settings.cipherNames) 1059 cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames) 1060 if sharedKeyDB or certChain: 1061 cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames) 1062 1063 #Initialize acceptable certificate type 1064 certificateType = None 1065 if certChain: 1066 try: 1067 import cryptoIDlib.CertChain 1068 if isinstance(certChain, cryptoIDlib.CertChain.CertChain): 1069 certificateType = CertificateType.cryptoID 1070 except ImportError: 1071 pass 1072 if isinstance(certChain, X509CertChain): 1073 certificateType = CertificateType.x509 1074 if certificateType == None: 1075 raise ValueError("Unrecognized certificate type") 1076 1077 #Initialize locals 1078 clientCertChain = None 1079 serverCertChain = None #We may set certChain to this later 1080 postFinishedError = None 1081 1082 #Tentatively set version to most-desirable version, so if an error 1083 #occurs parsing the ClientHello, this is what we'll use for the 1084 #error alert 1085 self.version = settings.maxVersion 1086 1087 #Get ClientHello 1088 for result in self._getMsg(ContentType.handshake, 1089 HandshakeType.client_hello): 1090 if result in (0,1): 1091 yield result 1092 else: 1093 break 1094 clientHello = result 1095 1096 #If client's version is too low, reject it 1097 if clientHello.client_version < settings.minVersion: 1098 self.version = settings.minVersion 1099 for result in self._sendError(\ 1100 AlertDescription.protocol_version, 1101 "Too old version: %s" % str(clientHello.client_version)): 1102 yield result 1103 1104 #If client's version is too high, propose my highest version 1105 elif clientHello.client_version > settings.maxVersion: 1106 self.version = settings.maxVersion 1107 1108 else: 1109 #Set the version to the client's version 1110 self.version = clientHello.client_version 1111 1112 #Get the client nonce; create server nonce 1113 clientRandom = clientHello.random 1114 serverRandom = getRandomBytes(32) 1115 1116 #Calculate the first cipher suite intersection. 1117 #This is the 'privileged' ciphersuite. We'll use it if we're 1118 #doing a shared-key resumption or a new negotiation. In fact, 1119 #the only time we won't use it is if we're resuming a non-sharedkey 1120 #session, in which case we use the ciphersuite from the session. 1121 # 1122 #Given the current ciphersuite ordering, this means we prefer SRP 1123 #over non-SRP. 1124 for cipherSuite in cipherSuites: 1125 if cipherSuite in clientHello.cipher_suites: 1126 break 1127 else: 1128 for result in self._sendError(\ 1129 AlertDescription.handshake_failure): 1130 yield result 1131 1132 #If resumption was requested... 1133 if clientHello.session_id and (sharedKeyDB or sessionCache): 1134 session = None 1135 1136 #Check in the sharedKeys container 1137 if sharedKeyDB and len(clientHello.session_id)==16: 1138 try: 1139 #Trim off zero padding, if any 1140 for x in range(16): 1141 …
Large files files are truncated, but you can click here to view the full file