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