Package tlslite :: Module tlsconnection
[hide private]
[frames] | no frames]

Source Code for Module tlslite.tlsconnection

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