1# Authors: 2# Trevor Perrin 3# Google - added reqCAs parameter 4# Google (adapted by Sam Rushing and Marcelo Fernandez) - NPN support 5# Dimitris Moraitis - Anon ciphersuites 6# Martin von Loewis - python 3 port 7# Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2 8# 9# See the LICENSE file for legal information regarding use of this file. 10 11""" 12MAIN CLASS FOR TLS LITE (START HERE!). 13""" 14 15import socket 16from .utils.compat import formatExceptionTrace 17from .tlsrecordlayer import TLSRecordLayer 18from .session import Session 19from .constants import * 20from .utils.cryptomath import getRandomBytes, MD5, SHA1, SHA256 21from .errors import * 22from .messages import * 23from .mathtls import * 24from .handshakesettings import HandshakeSettings 25from .utils.tackwrapper import * 26from .utils.rsakey import RSAKey 27from .utils import p256 28 29class KeyExchange(object): 30 def __init__(self, cipherSuite, clientHello, serverHello, privateKey): 31 """ 32 Initializes the KeyExchange. privateKey is the signing private key. 33 """ 34 self.cipherSuite = cipherSuite 35 self.clientHello = clientHello 36 self.serverHello = serverHello 37 self.privateKey = privateKey 38 39 def makeServerKeyExchange(): 40 """ 41 Returns a ServerKeyExchange object for the server's initial leg in the 42 handshake. If the key exchange method does not send ServerKeyExchange 43 (e.g. RSA), it returns None. 44 """ 45 raise NotImplementedError() 46 47 def processClientKeyExchange(clientKeyExchange): 48 """ 49 Processes the client's ClientKeyExchange message and returns the 50 premaster secret. Raises TLSLocalAlert on error. 51 """ 52 raise NotImplementedError() 53 54 def sign(self, inpBytes): 55 algorithm = None 56 if self.serverHello.server_version >= (3, 3): 57 # Negotiate a signature algorithm. 58 peerPrefs = self.clientHello.signature_algorithms 59 if (HashAlgorithm.sha256, SignatureAlgorithm.rsa) in peerPrefs: 60 algorithm = (HashAlgorithm.sha256, SignatureAlgorithm.rsa) 61 inpBytes = RSAKey.addPKCS1SHA256Prefix(SHA256(inpBytes)) 62 elif (HashAlgorithm.sha1, SignatureAlgorithm.rsa) in peerPrefs: 63 algorithm = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) 64 inpBytes = RSAKey.addPKCS1SHA1Prefix(SHA1(inpBytes)) 65 else: 66 raise TLSLocalAlert(AlertDescription.handshake_failure, 67 "no common signature algorithms") 68 else: 69 inpBytes = MD5(inpBytes) + SHA1(inpBytes) 70 return algorithm, self.privateKey.sign(inpBytes) 71 72class RSAKeyExchange(KeyExchange): 73 def makeServerKeyExchange(self): 74 return None 75 76 def processClientKeyExchange(self, clientKeyExchange): 77 premasterSecret = self.privateKey.decrypt(\ 78 clientKeyExchange.encryptedPreMasterSecret) 79 80 # On decryption failure randomize premaster secret to avoid 81 # Bleichenbacher's "million message" attack 82 randomPreMasterSecret = getRandomBytes(48) 83 if not premasterSecret: 84 premasterSecret = randomPreMasterSecret 85 elif len(premasterSecret)!=48: 86 premasterSecret = randomPreMasterSecret 87 else: 88 versionCheck = (premasterSecret[0], premasterSecret[1]) 89 if versionCheck != self.clientHello.client_version: 90 #Tolerate buggy IE clients 91 if versionCheck != self.serverHello.server_version: 92 premasterSecret = randomPreMasterSecret 93 return premasterSecret 94 95def _hexStringToNumber(s): 96 s = s.replace(" ", "").replace("\n", "") 97 if len(s) % 2 != 0: 98 raise ValueError("Length is not even") 99 return bytesToNumber(bytearray.fromhex(s)) 100 101class DHE_RSAKeyExchange(KeyExchange): 102 # 2048-bit MODP Group (RFC 3526, Section 3) 103 dh_p = _hexStringToNumber(""" 104FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 10529024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD 106EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 107E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED 108EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D 109C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F 11083655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D 111670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B 112E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 113DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 11415728E5A 8AACAA68 FFFFFFFF FFFFFFFF""") 115 dh_g = 2 116 117 # RFC 3526, Section 8. 118 strength = 160 119 120 def makeServerKeyExchange(self): 121 # Per RFC 3526, Section 1, the exponent should have double the entropy 122 # of the strength of the curve. 123 self.dh_Xs = bytesToNumber(getRandomBytes(self.strength * 2 / 8)) 124 dh_Ys = powMod(self.dh_g, self.dh_Xs, self.dh_p) 125 126 version = self.serverHello.server_version 127 serverKeyExchange = ServerKeyExchange(self.cipherSuite, version) 128 serverKeyExchange.createDH(self.dh_p, self.dh_g, dh_Ys) 129 serverKeyExchange.signature_algorithm, serverKeyExchange.signature = \ 130 self.sign(serverKeyExchange.signingPayload(self.clientHello.random, 131 self.serverHello.random)) 132 return serverKeyExchange 133 134 def processClientKeyExchange(self, clientKeyExchange): 135 dh_Yc = clientKeyExchange.dh_Yc 136 137 # First half of RFC 2631, Section 2.1.5. Validate the client's public 138 # key. 139 if not 2 <= dh_Yc <= self.dh_p - 1: 140 raise TLSLocalAlert(AlertDescription.illegal_parameter, 141 "Invalid dh_Yc value") 142 143 S = powMod(dh_Yc, self.dh_Xs, self.dh_p) 144 return numberToByteArray(S) 145 146class ECDHE_RSAKeyExchange(KeyExchange): 147 def makeServerKeyExchange(self): 148 public, self.private = p256.generatePublicPrivate() 149 150 version = self.serverHello.server_version 151 serverKeyExchange = ServerKeyExchange(self.cipherSuite, version) 152 serverKeyExchange.createECDH(NamedCurve.secp256r1, bytearray(public)) 153 serverKeyExchange.signature_algorithm, serverKeyExchange.signature = \ 154 self.sign(serverKeyExchange.signingPayload(self.clientHello.random, 155 self.serverHello.random)) 156 return serverKeyExchange 157 158 def processClientKeyExchange(self, clientKeyExchange): 159 ecdh_Yc = clientKeyExchange.ecdh_Yc 160 return bytearray(p256.generateSharedValue(bytes(ecdh_Yc), self.private)) 161 162class TLSConnection(TLSRecordLayer): 163 """ 164 This class wraps a socket and provides TLS handshaking and data 165 transfer. 166 167 To use this class, create a new instance, passing a connected 168 socket into the constructor. Then call some handshake function. 169 If the handshake completes without raising an exception, then a TLS 170 connection has been negotiated. You can transfer data over this 171 connection as if it were a socket. 172 173 This class provides both synchronous and asynchronous versions of 174 its key functions. The synchronous versions should be used when 175 writing single-or multi-threaded code using blocking sockets. The 176 asynchronous versions should be used when performing asynchronous, 177 event-based I/O with non-blocking sockets. 178 179 Asynchronous I/O is a complicated subject; typically, you should 180 not use the asynchronous functions directly, but should use some 181 framework like asyncore or Twisted which TLS Lite integrates with 182 (see 183 L{tlslite.integration.tlsasyncdispatchermixin.TLSAsyncDispatcherMixIn}). 184 """ 185 186 def __init__(self, sock): 187 """Create a new TLSConnection instance. 188 189 @param sock: The socket data will be transmitted on. The 190 socket should already be connected. It may be in blocking or 191 non-blocking mode. 192 193 @type sock: L{socket.socket} 194 """ 195 TLSRecordLayer.__init__(self, sock) 196 self.clientRandom = b"" 197 self.serverRandom = b"" 198 199 #********************************************************* 200 # Client Handshake Functions 201 #********************************************************* 202 203 def handshakeClientAnonymous(self, session=None, settings=None, 204 checker=None, serverName="", 205 async=False): 206 """Perform an anonymous handshake in the role of client. 207 208 This function performs an SSL or TLS handshake using an 209 anonymous Diffie Hellman ciphersuite. 210 211 Like any handshake function, this can be called on a closed 212 TLS connection, or on a TLS connection that is already open. 213 If called on an open connection it performs a re-handshake. 214 215 If the function completes without raising an exception, the 216 TLS connection will be open and available for data transfer. 217 218 If an exception is raised, the connection will have been 219 automatically closed (if it was ever open). 220 221 @type session: L{tlslite.Session.Session} 222 @param session: A TLS session to attempt to resume. If the 223 resumption does not succeed, a full handshake will be 224 performed. 225 226 @type settings: L{tlslite.HandshakeSettings.HandshakeSettings} 227 @param settings: Various settings which can be used to control 228 the ciphersuites, certificate types, and SSL/TLS versions 229 offered by the client. 230 231 @type checker: L{tlslite.Checker.Checker} 232 @param checker: A Checker instance. This instance will be 233 invoked to examine the other party's authentication 234 credentials, if the handshake completes succesfully. 235 236 @type serverName: string 237 @param serverName: The ServerNameIndication TLS Extension. 238 239 @type async: bool 240 @param async: If False, this function will block until the 241 handshake is completed. If True, this function will return a 242 generator. Successive invocations of the generator will 243 return 0 if it is waiting to read from the socket, 1 if it is 244 waiting to write to the socket, or will raise StopIteration if 245 the handshake operation is completed. 246 247 @rtype: None or an iterable 248 @return: If 'async' is True, a generator object will be 249 returned. 250 251 @raise socket.error: If a socket error occurs. 252 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 253 without a preceding alert. 254 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 255 @raise tlslite.errors.TLSAuthenticationError: If the checker 256 doesn't like the other party's authentication credentials. 257 """ 258 handshaker = self._handshakeClientAsync(anonParams=(True), 259 session=session, 260 settings=settings, 261 checker=checker, 262 serverName=serverName) 263 if async: 264 return handshaker 265 for result in handshaker: 266 pass 267 268 def handshakeClientSRP(self, username, password, session=None, 269 settings=None, checker=None, 270 reqTack=True, serverName="", 271 async=False): 272 """Perform an SRP handshake in the role of client. 273 274 This function performs a TLS/SRP handshake. SRP mutually 275 authenticates both parties to each other using only a 276 username and password. This function may also perform a 277 combined SRP and server-certificate handshake, if the server 278 chooses to authenticate itself with a certificate chain in 279 addition to doing SRP. 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 username: str 288 @param username: The SRP username. 289 290 @type password: str 291 @param password: The SRP password. 292 293 @type session: L{tlslite.session.Session} 294 @param session: A TLS session to attempt to resume. This 295 session must be an SRP session performed with the same username 296 and password as were passed in. If the resumption does not 297 succeed, a full SRP handshake will be performed. 298 299 @type settings: L{tlslite.handshakesettings.HandshakeSettings} 300 @param settings: Various settings which can be used to control 301 the ciphersuites, certificate types, and SSL/TLS versions 302 offered by the client. 303 304 @type checker: L{tlslite.checker.Checker} 305 @param checker: A Checker instance. This instance will be 306 invoked to examine the other party's authentication 307 credentials, if the handshake completes succesfully. 308 309 @type reqTack: bool 310 @param reqTack: Whether or not to send a "tack" TLS Extension, 311 requesting the server return a TackExtension if it has one. 312 313 @type serverName: string 314 @param serverName: The ServerNameIndication TLS Extension. 315 316 @type async: bool 317 @param async: If False, this function will block until the 318 handshake is completed. If True, this function will return a 319 generator. Successive invocations of the generator will 320 return 0 if it is waiting to read from the socket, 1 if it is 321 waiting to write to the socket, or will raise StopIteration if 322 the handshake operation is completed. 323 324 @rtype: None or an iterable 325 @return: If 'async' is True, a generator object will be 326 returned. 327 328 @raise socket.error: If a socket error occurs. 329 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 330 without a preceding alert. 331 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 332 @raise tlslite.errors.TLSAuthenticationError: If the checker 333 doesn't like the other party's authentication credentials. 334 """ 335 handshaker = self._handshakeClientAsync(srpParams=(username, password), 336 session=session, settings=settings, checker=checker, 337 reqTack=reqTack, serverName=serverName) 338 # The handshaker is a Python Generator which executes the handshake. 339 # It allows the handshake to be run in a "piecewise", asynchronous 340 # fashion, returning 1 when it is waiting to able to write, 0 when 341 # it is waiting to read. 342 # 343 # If 'async' is True, the generator is returned to the caller, 344 # otherwise it is executed to completion here. 345 if async: 346 return handshaker 347 for result in handshaker: 348 pass 349 350 def handshakeClientCert(self, certChain=None, privateKey=None, 351 session=None, settings=None, checker=None, 352 nextProtos=None, reqTack=True, serverName="", 353 async=False): 354 """Perform a certificate-based handshake in the role of client. 355 356 This function performs an SSL or TLS handshake. The server 357 will authenticate itself using an X.509 certificate 358 chain. If the handshake succeeds, the server's certificate 359 chain will be stored in the session's serverCertChain attribute. 360 Unless a checker object is passed in, this function does no 361 validation or checking of the server's certificate chain. 362 363 If the server requests client authentication, the 364 client will send the passed-in certificate chain, and use the 365 passed-in private key to authenticate itself. If no 366 certificate chain and private key were passed in, the client 367 will attempt to proceed without client authentication. The 368 server may or may not allow this. 369 370 If the function completes without raising an exception, the 371 TLS connection will be open and available for data transfer. 372 373 If an exception is raised, the connection will have been 374 automatically closed (if it was ever open). 375 376 @type certChain: L{tlslite.x509certchain.X509CertChain} 377 @param certChain: The certificate chain to be used if the 378 server requests client authentication. 379 380 @type privateKey: L{tlslite.utils.rsakey.RSAKey} 381 @param privateKey: The private key to be used if the server 382 requests client authentication. 383 384 @type session: L{tlslite.session.Session} 385 @param session: A TLS session to attempt to resume. If the 386 resumption does not succeed, a full handshake will be 387 performed. 388 389 @type settings: L{tlslite.handshakesettings.HandshakeSettings} 390 @param settings: Various settings which can be used to control 391 the ciphersuites, certificate types, and SSL/TLS versions 392 offered by the client. 393 394 @type checker: L{tlslite.checker.Checker} 395 @param checker: A Checker instance. This instance will be 396 invoked to examine the other party's authentication 397 credentials, if the handshake completes succesfully. 398 399 @type nextProtos: list of strings. 400 @param nextProtos: A list of upper layer protocols ordered by 401 preference, to use in the Next-Protocol Negotiation Extension. 402 403 @type reqTack: bool 404 @param reqTack: Whether or not to send a "tack" TLS Extension, 405 requesting the server return a TackExtension if it has one. 406 407 @type serverName: string 408 @param serverName: The ServerNameIndication TLS Extension. 409 410 @type async: bool 411 @param async: If False, this function will block until the 412 handshake is completed. If True, this function will return a 413 generator. Successive invocations of the generator will 414 return 0 if it is waiting to read from the socket, 1 if it is 415 waiting to write to the socket, or will raise StopIteration if 416 the handshake operation is completed. 417 418 @rtype: None or an iterable 419 @return: If 'async' is True, a generator object will be 420 returned. 421 422 @raise socket.error: If a socket error occurs. 423 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 424 without a preceding alert. 425 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 426 @raise tlslite.errors.TLSAuthenticationError: If the checker 427 doesn't like the other party's authentication credentials. 428 """ 429 handshaker = self._handshakeClientAsync(certParams=(certChain, 430 privateKey), session=session, settings=settings, 431 checker=checker, serverName=serverName, 432 nextProtos=nextProtos, reqTack=reqTack) 433 # The handshaker is a Python Generator which executes the handshake. 434 # It allows the handshake to be run in a "piecewise", asynchronous 435 # fashion, returning 1 when it is waiting to able to write, 0 when 436 # it is waiting to read. 437 # 438 # If 'async' is True, the generator is returned to the caller, 439 # otherwise it is executed to completion here. 440 if async: 441 return handshaker 442 for result in handshaker: 443 pass 444 445 446 def _handshakeClientAsync(self, srpParams=(), certParams=(), anonParams=(), 447 session=None, settings=None, checker=None, 448 nextProtos=None, serverName="", reqTack=True): 449 450 handshaker = self._handshakeClientAsyncHelper(srpParams=srpParams, 451 certParams=certParams, 452 anonParams=anonParams, 453 session=session, 454 settings=settings, 455 serverName=serverName, 456 nextProtos=nextProtos, 457 reqTack=reqTack) 458 for result in self._handshakeWrapperAsync(handshaker, checker): 459 yield result 460 461 462 def _handshakeClientAsyncHelper(self, srpParams, certParams, anonParams, 463 session, settings, serverName, nextProtos, reqTack): 464 465 self._handshakeStart(client=True) 466 467 #Unpack parameters 468 srpUsername = None # srpParams[0] 469 password = None # srpParams[1] 470 clientCertChain = None # certParams[0] 471 privateKey = None # certParams[1] 472 473 # Allow only one of (srpParams, certParams, anonParams) 474 if srpParams: 475 assert(not certParams) 476 assert(not anonParams) 477 srpUsername, password = srpParams 478 if certParams: 479 assert(not srpParams) 480 assert(not anonParams) 481 clientCertChain, privateKey = certParams 482 if anonParams: 483 assert(not srpParams) 484 assert(not certParams) 485 486 #Validate parameters 487 if srpUsername and not password: 488 raise ValueError("Caller passed a username but no password") 489 if password and not srpUsername: 490 raise ValueError("Caller passed a password but no username") 491 if clientCertChain and not privateKey: 492 raise ValueError("Caller passed a certChain but no privateKey") 493 if privateKey and not clientCertChain: 494 raise ValueError("Caller passed a privateKey but no certChain") 495 if reqTack: 496 if not tackpyLoaded: 497 reqTack = False 498 if not settings or not settings.useExperimentalTackExtension: 499 reqTack = False 500 if nextProtos is not None: 501 if len(nextProtos) == 0: 502 raise ValueError("Caller passed no nextProtos") 503 504 # Validates the settings and filters out any unsupported ciphers 505 # or crypto libraries that were requested 506 if not settings: 507 settings = HandshakeSettings() 508 settings = settings._filter() 509 510 if settings.alpnProtos is not None: 511 if len(settings.alpnProtos) == 0: 512 raise ValueError("Caller passed no alpnProtos") 513 514 if clientCertChain: 515 if not isinstance(clientCertChain, X509CertChain): 516 raise ValueError("Unrecognized certificate type") 517 if "x509" not in settings.certificateTypes: 518 raise ValueError("Client certificate doesn't match "\ 519 "Handshake Settings") 520 521 if session: 522 # session.valid() ensures session is resumable and has 523 # non-empty sessionID 524 if not session.valid(): 525 session = None #ignore non-resumable sessions... 526 elif session.resumable: 527 if session.srpUsername != srpUsername: 528 raise ValueError("Session username doesn't match") 529 if session.serverName != serverName: 530 raise ValueError("Session servername doesn't match") 531 532 #Add Faults to parameters 533 if srpUsername and self.fault == Fault.badUsername: 534 srpUsername += "GARBAGE" 535 if password and self.fault == Fault.badPassword: 536 password += "GARBAGE" 537 538 #Tentatively set the version to the client's minimum version. 539 #We'll use this for the ClientHello, and if an error occurs 540 #parsing the Server Hello, we'll use this version for the response 541 self.version = settings.maxVersion 542 543 # OK Start sending messages! 544 # ***************************** 545 546 # Send the ClientHello. 547 for result in self._clientSendClientHello(settings, session, 548 srpUsername, srpParams, certParams, 549 anonParams, serverName, nextProtos, 550 reqTack): 551 if result in (0,1): yield result 552 else: break 553 clientHello = result 554 555 #Get the ServerHello. 556 for result in self._clientGetServerHello(settings, clientHello): 557 if result in (0,1): yield result 558 else: break 559 serverHello = result 560 cipherSuite = serverHello.cipher_suite 561 562 # Choose a matching Next Protocol from server list against ours 563 # (string or None) 564 nextProto = self._clientSelectNextProto(nextProtos, serverHello) 565 566 #If the server elected to resume the session, it is handled here. 567 for result in self._clientResume(session, serverHello, 568 clientHello.random, 569 settings.cipherImplementations, 570 nextProto): 571 if result in (0,1): yield result 572 else: break 573 if result == "resumed_and_finished": 574 self._handshakeDone(resumed=True) 575 return 576 577 #If the server selected an SRP ciphersuite, the client finishes 578 #reading the post-ServerHello messages, then derives a 579 #premasterSecret and sends a corresponding ClientKeyExchange. 580 if cipherSuite in CipherSuite.srpAllSuites: 581 for result in self._clientSRPKeyExchange(\ 582 settings, cipherSuite, serverHello.certificate_type, 583 srpUsername, password, 584 clientHello.random, serverHello.random, 585 serverHello.tackExt): 586 if result in (0,1): yield result 587 else: break 588 (premasterSecret, serverCertChain, tackExt) = result 589 590 #If the server selected an anonymous ciphersuite, the client 591 #finishes reading the post-ServerHello messages. 592 elif cipherSuite in CipherSuite.anonSuites: 593 for result in self._clientAnonKeyExchange(settings, cipherSuite, 594 clientHello.random, serverHello.random): 595 if result in (0,1): yield result 596 else: break 597 (premasterSecret, serverCertChain, tackExt) = result 598 599 #If the server selected a certificate-based RSA ciphersuite, 600 #the client finishes reading the post-ServerHello messages. If 601 #a CertificateRequest message was sent, the client responds with 602 #a Certificate message containing its certificate chain (if any), 603 #and also produces a CertificateVerify message that signs the 604 #ClientKeyExchange. 605 else: 606 for result in self._clientRSAKeyExchange(settings, cipherSuite, 607 clientCertChain, privateKey, 608 serverHello.certificate_type, 609 clientHello.random, serverHello.random, 610 serverHello.tackExt): 611 if result in (0,1): yield result 612 else: break 613 (premasterSecret, serverCertChain, clientCertChain, 614 tackExt) = result 615 616 #After having previously sent a ClientKeyExchange, the client now 617 #initiates an exchange of Finished messages. 618 for result in self._clientFinished(premasterSecret, 619 clientHello.random, 620 serverHello.random, 621 cipherSuite, settings.cipherImplementations, 622 nextProto): 623 if result in (0,1): yield result 624 else: break 625 masterSecret = result 626 627 self.clientRandom = clientHello.random 628 self.serverRandom = serverHello.random 629 630 # Create the session object which is used for resumptions 631 self.session = Session() 632 self.session.create(masterSecret, serverHello.session_id, cipherSuite, 633 srpUsername, clientCertChain, serverCertChain, 634 tackExt, serverHello.tackExt!=None, serverName) 635 self._handshakeDone(resumed=False) 636 637 638 def _clientSendClientHello(self, settings, session, srpUsername, 639 srpParams, certParams, anonParams, 640 serverName, nextProtos, reqTack): 641 #Initialize acceptable ciphersuites 642 cipherSuites = [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 643 if srpParams: 644 cipherSuites += CipherSuite.getSrpAllSuites(settings) 645 elif certParams: 646 # TODO: Client DHE_RSA not supported. 647 # cipherSuites += CipherSuite.getDheCertSuites(settings) 648 cipherSuites += CipherSuite.getCertSuites(settings) 649 elif anonParams: 650 cipherSuites += CipherSuite.getAnonSuites(settings) 651 else: 652 assert(False) 653 654 #Initialize acceptable certificate types 655 certificateTypes = settings._getCertificateTypes() 656 657 #Either send ClientHello (with a resumable session)... 658 if session and session.sessionID: 659 #If it's resumable, then its 660 #ciphersuite must be one of the acceptable ciphersuites 661 if session.cipherSuite not in cipherSuites: 662 raise ValueError("Session's cipher suite not consistent "\ 663 "with parameters") 664 else: 665 clientHello = ClientHello() 666 clientHello.create(settings.maxVersion, getRandomBytes(32), 667 session.sessionID, cipherSuites, 668 certificateTypes, 669 session.srpUsername, 670 reqTack, settings.alpnProtos, 671 nextProtos is not None, 672 session.serverName) 673 674 #Or send ClientHello (without) 675 else: 676 clientHello = ClientHello() 677 clientHello.create(settings.maxVersion, getRandomBytes(32), 678 bytearray(0), cipherSuites, 679 certificateTypes, 680 srpUsername, 681 reqTack, settings.alpnProtos, 682 nextProtos is not None, 683 serverName) 684 for result in self._sendMsg(clientHello): 685 yield result 686 yield clientHello 687 688 689 def _clientGetServerHello(self, settings, clientHello): 690 for result in self._getMsg(ContentType.handshake, 691 HandshakeType.server_hello): 692 if result in (0,1): yield result 693 else: break 694 serverHello = result 695 696 #Get the server version. Do this before anything else, so any 697 #error alerts will use the server's version 698 self.version = serverHello.server_version 699 700 #Future responses from server must use this version 701 self._versionCheck = True 702 703 #Check ServerHello 704 if serverHello.server_version < settings.minVersion: 705 for result in self._sendError(\ 706 AlertDescription.protocol_version, 707 "Too old version: %s" % str(serverHello.server_version)): 708 yield result 709 if serverHello.server_version > settings.maxVersion: 710 for result in self._sendError(\ 711 AlertDescription.protocol_version, 712 "Too new version: %s" % str(serverHello.server_version)): 713 yield result 714 if serverHello.cipher_suite not in clientHello.cipher_suites: 715 for result in self._sendError(\ 716 AlertDescription.illegal_parameter, 717 "Server responded with incorrect ciphersuite"): 718 yield result 719 if serverHello.certificate_type not in clientHello.certificate_types: 720 for result in self._sendError(\ 721 AlertDescription.illegal_parameter, 722 "Server responded with incorrect certificate type"): 723 yield result 724 if serverHello.compression_method != 0: 725 for result in self._sendError(\ 726 AlertDescription.illegal_parameter, 727 "Server responded with incorrect compression method"): 728 yield result 729 if serverHello.tackExt: 730 if not clientHello.tack: 731 for result in self._sendError(\ 732 AlertDescription.illegal_parameter, 733 "Server responded with unrequested Tack Extension"): 734 yield result 735 if serverHello.alpn_proto_selected and not clientHello.alpn_protos_advertised: 736 for result in self._sendError(\ 737 AlertDescription.illegal_parameter, 738 "Server responded with unrequested ALPN Extension"): 739 yield result 740 if serverHello.alpn_proto_selected and serverHello.next_protos: 741 for result in self._sendError(\ 742 AlertDescription.illegal_parameter, 743 "Server responded with both ALPN and NPN extension"): 744 yield result 745 if serverHello.next_protos and not clientHello.supports_npn: 746 for result in self._sendError(\ 747 AlertDescription.illegal_parameter, 748 "Server responded with unrequested NPN Extension"): 749 yield result 750 if not serverHello.tackExt.verifySignatures(): 751 for result in self._sendError(\ 752 AlertDescription.decrypt_error, 753 "TackExtension contains an invalid signature"): 754 yield result 755 yield serverHello 756 757 def _clientSelectNextProto(self, nextProtos, serverHello): 758 # nextProtos is None or non-empty list of strings 759 # serverHello.next_protos is None or possibly-empty list of strings 760 # 761 # !!! We assume the client may have specified nextProtos as a list of 762 # strings so we convert them to bytearrays (it's awkward to require 763 # the user to specify a list of bytearrays or "bytes", and in 764 # Python 2.6 bytes() is just an alias for str() anyways... 765 if nextProtos is not None and serverHello.next_protos is not None: 766 for p in nextProtos: 767 if bytearray(p) in serverHello.next_protos: 768 return bytearray(p) 769 else: 770 # If the client doesn't support any of server's protocols, 771 # or the server doesn't advertise any (next_protos == []) 772 # the client SHOULD select the first protocol it supports. 773 return bytearray(nextProtos[0]) 774 return None 775 776 def _clientResume(self, session, serverHello, clientRandom, 777 cipherImplementations, nextProto): 778 #If the server agrees to resume 779 if session and session.sessionID and \ 780 serverHello.session_id == session.sessionID: 781 782 if serverHello.cipher_suite != session.cipherSuite: 783 for result in self._sendError(\ 784 AlertDescription.illegal_parameter,\ 785 "Server's ciphersuite doesn't match session"): 786 yield result 787 788 #Calculate pending connection states 789 self._calcPendingStates(session.cipherSuite, 790 session.masterSecret, 791 clientRandom, serverHello.random, 792 cipherImplementations) 793 794 #Exchange ChangeCipherSpec and Finished messages 795 for result in self._getFinished(session.masterSecret): 796 yield result 797 for result in self._sendFinished(session.masterSecret, nextProto): 798 yield result 799 800 #Set the session for this connection 801 self.session = session 802 yield "resumed_and_finished" 803 804 def _clientSRPKeyExchange(self, settings, cipherSuite, certificateType, 805 srpUsername, password, 806 clientRandom, serverRandom, tackExt): 807 808 #If the server chose an SRP+RSA suite... 809 if cipherSuite in CipherSuite.srpCertSuites: 810 #Get Certificate, ServerKeyExchange, ServerHelloDone 811 for result in self._getMsg(ContentType.handshake, 812 HandshakeType.certificate, certificateType): 813 if result in (0,1): yield result 814 else: break 815 serverCertificate = result 816 else: 817 serverCertificate = None 818 819 for result in self._getMsg(ContentType.handshake, 820 HandshakeType.server_key_exchange, cipherSuite): 821 if result in (0,1): yield result 822 else: break 823 serverKeyExchange = result 824 825 for result in self._getMsg(ContentType.handshake, 826 HandshakeType.server_hello_done): 827 if result in (0,1): yield result 828 else: break 829 serverHelloDone = result 830 831 #Calculate SRP premaster secret 832 #Get and check the server's group parameters and B value 833 N = serverKeyExchange.srp_N 834 g = serverKeyExchange.srp_g 835 s = serverKeyExchange.srp_s 836 B = serverKeyExchange.srp_B 837 838 if (g,N) not in goodGroupParameters: 839 for result in self._sendError(\ 840 AlertDescription.insufficient_security, 841 "Unknown group parameters"): 842 yield result 843 if numBits(N) < settings.minKeySize: 844 for result in self._sendError(\ 845 AlertDescription.insufficient_security, 846 "N value is too small: %d" % numBits(N)): 847 yield result 848 if numBits(N) > settings.maxKeySize: 849 for result in self._sendError(\ 850 AlertDescription.insufficient_security, 851 "N value is too large: %d" % numBits(N)): 852 yield result 853 if B % N == 0: 854 for result in self._sendError(\ 855 AlertDescription.illegal_parameter, 856 "Suspicious B value"): 857 yield result 858 859 #Check the server's signature, if server chose an 860 #SRP+RSA suite 861 serverCertChain = None 862 if cipherSuite in CipherSuite.srpCertSuites: 863 #Hash ServerKeyExchange/ServerSRPParams 864 hashBytes = serverKeyExchange.hash(clientRandom, serverRandom) 865 866 #Extract signature bytes from ServerKeyExchange 867 sigBytes = serverKeyExchange.signature 868 if len(sigBytes) == 0: 869 for result in self._sendError(\ 870 AlertDescription.illegal_parameter, 871 "Server sent an SRP ServerKeyExchange "\ 872 "message without a signature"): 873 yield result 874 875 # Get server's public key from the Certificate message 876 # Also validate the chain against the ServerHello's TACKext (if any) 877 # If none, and a TACK cert is present, return its TACKext 878 for result in self._clientGetKeyFromChain(serverCertificate, 879 settings, tackExt): 880 if result in (0,1): yield result 881 else: break 882 publicKey, serverCertChain, tackExt = result 883 884 #Verify signature 885 if not publicKey.verify(sigBytes, hashBytes): 886 for result in self._sendError(\ 887 AlertDescription.decrypt_error, 888 "Signature failed to verify"): 889 yield result 890 891 #Calculate client's ephemeral DH values (a, A) 892 a = bytesToNumber(getRandomBytes(32)) 893 A = powMod(g, a, N) 894 895 #Calculate client's static DH values (x, v) 896 x = makeX(s, bytearray(srpUsername, "utf-8"), 897 bytearray(password, "utf-8")) 898 v = powMod(g, x, N) 899 900 #Calculate u 901 u = makeU(N, A, B) 902 903 #Calculate premaster secret 904 k = makeK(N, g) 905 S = powMod((B - (k*v)) % N, a+(u*x), N) 906 907 if self.fault == Fault.badA: 908 A = N 909 S = 0 910 911 premasterSecret = numberToByteArray(S) 912 913 #Send ClientKeyExchange 914 for result in self._sendMsg(\ 915 ClientKeyExchange(cipherSuite).createSRP(A)): 916 yield result 917 yield (premasterSecret, serverCertChain, tackExt) 918 919 920 def _clientRSAKeyExchange(self, settings, cipherSuite, 921 clientCertChain, privateKey, 922 certificateType, 923 clientRandom, serverRandom, 924 tackExt): 925 926 #Get Certificate[, CertificateRequest], ServerHelloDone 927 for result in self._getMsg(ContentType.handshake, 928 HandshakeType.certificate, certificateType): 929 if result in (0,1): yield result 930 else: break 931 serverCertificate = result 932 933 # Get CertificateRequest or ServerHelloDone 934 for result in self._getMsg(ContentType.handshake, 935 (HandshakeType.server_hello_done, 936 HandshakeType.certificate_request)): 937 if result in (0,1): yield result 938 else: break 939 msg = result 940 certificateRequest = None 941 if isinstance(msg, CertificateRequest): 942 certificateRequest = msg 943 # We got CertificateRequest, so this must be ServerHelloDone 944 for result in self._getMsg(ContentType.handshake, 945 HandshakeType.server_hello_done): 946 if result in (0,1): yield result 947 else: break 948 serverHelloDone = result 949 elif isinstance(msg, ServerHelloDone): 950 serverHelloDone = msg 951 952 # Get server's public key from the Certificate message 953 # Also validate the chain against the ServerHello's TACKext (if any) 954 # If none, and a TACK cert is present, return its TACKext 955 for result in self._clientGetKeyFromChain(serverCertificate, 956 settings, tackExt): 957 if result in (0,1): yield result 958 else: break 959 publicKey, serverCertChain, tackExt = result 960 961 #Calculate premaster secret 962 premasterSecret = getRandomBytes(48) 963 premasterSecret[0] = settings.maxVersion[0] 964 premasterSecret[1] = settings.maxVersion[1] 965 966 if self.fault == Fault.badPremasterPadding: 967 premasterSecret[0] = 5 968 if self.fault == Fault.shortPremasterSecret: 969 premasterSecret = premasterSecret[:-1] 970 971 #Encrypt premaster secret to server's public key 972 encryptedPreMasterSecret = publicKey.encrypt(premasterSecret) 973 974 #If client authentication was requested, send Certificate 975 #message, either with certificates or empty 976 if certificateRequest: 977 clientCertificate = Certificate(certificateType) 978 979 if clientCertChain: 980 #Check to make sure we have the same type of 981 #certificates the server requested 982 wrongType = False 983 if certificateType == CertificateType.x509: 984 if not isinstance(clientCertChain, X509CertChain): 985 wrongType = True 986 if wrongType: 987 for result in self._sendError(\ 988 AlertDescription.handshake_failure, 989 "Client certificate is of wrong type"): 990 yield result 991 992 clientCertificate.create(clientCertChain) 993 for result in self._sendMsg(clientCertificate): 994 yield result 995 else: 996 #The server didn't request client auth, so we 997 #zeroize these so the clientCertChain won't be 998 #stored in the session. 999 privateKey = None 1000 clientCertChain = None 1001 1002 #Send ClientKeyExchange 1003 clientKeyExchange = ClientKeyExchange(cipherSuite, 1004 self.version) 1005 clientKeyExchange.createRSA(encryptedPreMasterSecret) 1006 for result in self._sendMsg(clientKeyExchange): 1007 yield result 1008 1009 #If client authentication was requested and we have a 1010 #private key, send CertificateVerify 1011 if certificateRequest and privateKey: 1012 signatureAlgorithm = None 1013 if self.version == (3,0): 1014 masterSecret = calcMasterSecret(self.version, 1015 premasterSecret, 1016 clientRandom, 1017 serverRandom, 1018 b"", False) 1019 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"") 1020 elif self.version in ((3,1), (3,2)): 1021 verifyBytes = self._handshake_md5.digest() + \ 1022 self._handshake_sha.digest() 1023 elif self.version == (3,3): 1024 # TODO: Signature algorithm negotiation not supported. 1025 signatureAlgorithm = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) 1026 verifyBytes = self._handshake_sha.digest() 1027 verifyBytes = RSAKey.addPKCS1SHA1Prefix(verifyBytes) 1028 if self.fault == Fault.badVerifyMessage: 1029 verifyBytes[0] = ((verifyBytes[0]+1) % 256) 1030 signedBytes = privateKey.sign(verifyBytes) 1031 certificateVerify = CertificateVerify(self.version) 1032 certificateVerify.create(signatureAlgorithm, signedBytes) 1033 for result in self._sendMsg(certificateVerify): 1034 yield result 1035 yield (premasterSecret, serverCertChain, clientCertChain, tackExt) 1036 1037 def _clientAnonKeyExchange(self, settings, cipherSuite, clientRandom, 1038 serverRandom): 1039 for result in self._getMsg(ContentType.handshake, 1040 HandshakeType.server_key_exchange, cipherSuite): 1041 if result in (0,1): yield result 1042 else: break 1043 serverKeyExchange = result 1044 1045 for result in self._getMsg(ContentType.handshake, 1046 HandshakeType.server_hello_done): 1047 if result in (0,1): yield result 1048 else: break 1049 serverHelloDone = result 1050 1051 #calculate Yc 1052 dh_p = serverKeyExchange.dh_p 1053 dh_g = serverKeyExchange.dh_g 1054 dh_Xc = bytesToNumber(getRandomBytes(32)) 1055 dh_Ys = serverKeyExchange.dh_Ys 1056 dh_Yc = powMod(dh_g, dh_Xc, dh_p) 1057 1058 #Send ClientKeyExchange 1059 for result in self._sendMsg(\ 1060 ClientKeyExchange(cipherSuite, self.version).createDH(dh_Yc)): 1061 yield result 1062 1063 #Calculate premaster secret 1064 S = powMod(dh_Ys, dh_Xc, dh_p) 1065 premasterSecret = numberToByteArray(S) 1066 1067 yield (premasterSecret, None, None) 1068 1069 def _clientFinished(self, premasterSecret, clientRandom, serverRandom, 1070 cipherSuite, cipherImplementations, nextProto): 1071 1072 masterSecret = calcMasterSecret(self.version, premasterSecret, 1073 clientRandom, serverRandom, b"", False) 1074 self._calcPendingStates(cipherSuite, masterSecret, 1075 clientRandom, serverRandom, 1076 cipherImplementations) 1077 1078 #Exchange ChangeCipherSpec and Finished messages 1079 for result in self._sendFinished(masterSecret, nextProto): 1080 yield result 1081 for result in self._getFinished(masterSecret, nextProto=nextProto): 1082 yield result 1083 yield masterSecret 1084 1085 def _clientGetKeyFromChain(self, certificate, settings, tackExt=None): 1086 #Get and check cert chain from the Certificate message 1087 certChain = certificate.certChain 1088 if not certChain or certChain.getNumCerts() == 0: 1089 for result in self._sendError(AlertDescription.illegal_parameter, 1090 "Other party sent a Certificate message without "\ 1091 "certificates"): 1092 yield result 1093 1094 #Get and check public key from the cert chain 1095 publicKey = certChain.getEndEntityPublicKey() 1096 if len(publicKey) < settings.minKeySize: 1097 for result in self._sendError(AlertDescription.handshake_failure, 1098 "Other party's public key too small: %d" % len(publicKey)): 1099 yield result 1100 if len(publicKey) > settings.maxKeySize: 1101 for result in self._sendError(AlertDescription.handshake_failure, 1102 "Other party's public key too large: %d" % len(publicKey)): 1103 yield result 1104 1105 # If there's no TLS Extension, look for a TACK cert 1106 if tackpyLoaded: 1107 if not tackExt: 1108 tackExt = certChain.getTackExt() 1109 1110 # If there's a TACK (whether via TLS or TACK Cert), check that it 1111 # matches the cert chain 1112 if tackExt and tackExt.tacks: 1113 for tack in tackExt.tacks: 1114 if not certChain.checkTack(tack): 1115 for result in self._sendError( 1116 AlertDescription.illegal_parameter, 1117 "Other party's TACK doesn't match their public key"): 1118 yield result 1119 1120 yield publicKey, certChain, tackExt 1121 1122 1123 #********************************************************* 1124 # Server Handshake Functions 1125 #********************************************************* 1126 1127 1128 def handshakeServer(self, verifierDB=None, 1129 certChain=None, privateKey=None, reqCert=False, 1130 sessionCache=None, settings=None, checker=None, 1131 reqCAs = None, reqCertTypes = None, 1132 tacks=None, activationFlags=0, 1133 nextProtos=None, anon=False, 1134 signedCertTimestamps=None, 1135 fallbackSCSV=False, ocspResponse=None): 1136 """Perform a handshake in the role of server. 1137 1138 This function performs an SSL or TLS handshake. Depending on 1139 the arguments and the behavior of the client, this function can 1140 perform an SRP, or certificate-based handshake. It 1141 can also perform a combined SRP and server-certificate 1142 handshake. 1143 1144 Like any handshake function, this can be called on a closed 1145 TLS connection, or on a TLS connection that is already open. 1146 If called on an open connection it performs a re-handshake. 1147 This function does not send a Hello Request message before 1148 performing the handshake, so if re-handshaking is required, 1149 the server must signal the client to begin the re-handshake 1150 through some other means. 1151 1152 If the function completes without raising an exception, the 1153 TLS connection will be open and available for data transfer. 1154 1155 If an exception is raised, the connection will have been 1156 automatically closed (if it was ever open). 1157 1158 @type verifierDB: L{tlslite.verifierdb.VerifierDB} 1159 @param verifierDB: A database of SRP password verifiers 1160 associated with usernames. If the client performs an SRP 1161 handshake, the session's srpUsername attribute will be set. 1162 1163 @type certChain: L{tlslite.x509certchain.X509CertChain} 1164 @param certChain: The certificate chain to be used if the 1165 client requests server certificate authentication. 1166 1167 @type privateKey: L{tlslite.utils.rsakey.RSAKey} 1168 @param privateKey: The private key to be used if the client 1169 requests server certificate authentication. 1170 1171 @type reqCert: bool 1172 @param reqCert: Whether to request client certificate 1173 authentication. This only applies if the client chooses server 1174 certificate authentication; if the client chooses SRP 1175 authentication, this will be ignored. If the client 1176 performs a client certificate authentication, the sessions's 1177 clientCertChain attribute will be set. 1178 1179 @type sessionCache: L{tlslite.sessioncache.SessionCache} 1180 @param sessionCache: An in-memory cache of resumable sessions. 1181 The client can resume sessions from this cache. Alternatively, 1182 if the client performs a full handshake, a new session will be 1183 added to the cache. 1184 1185 @type settings: L{tlslite.handshakesettings.HandshakeSettings} 1186 @param settings: Various settings which can be used to control 1187 the ciphersuites and SSL/TLS version chosen by the server. 1188 1189 @type checker: L{tlslite.checker.Checker} 1190 @param checker: A Checker instance. This instance will be 1191 invoked to examine the other party's authentication 1192 credentials, if the handshake completes succesfully. 1193 1194 @type reqCAs: list of L{bytearray} of unsigned bytes 1195 @param reqCAs: A collection of DER-encoded DistinguishedNames that 1196 will be sent along with a certificate request. This does not affect 1197 verification. 1198 1199 @type reqCertTypes: list of int 1200 @param reqCertTypes: A list of certificate_type values to be sent 1201 along with a certificate request. This does not affect verification. 1202 1203 @type nextProtos: list of strings. 1204 @param nextProtos: A list of upper layer protocols to expose to the 1205 clients through the Next-Protocol Negotiation Extension, 1206 if they support it. 1207 1208 @type signedCertTimestamps: str 1209 @param signedCertTimestamps: A SignedCertificateTimestampList (as a 1210 binary 8-bit string) that will be sent as a TLS extension whenever 1211 the client announces support for the extension. 1212 1213 @type fallbackSCSV: bool 1214 @param fallbackSCSV: if true, the server will implement 1215 TLS_FALLBACK_SCSV and thus reject connections using less than the 1216 server's maximum TLS version that include this cipher suite. 1217 1218 @type ocspResponse: str 1219 @param ocspResponse: An OCSP response (as a binary 8-bit string) that 1220 will be sent stapled in the handshake whenever the client announces 1221 support for the status_request extension. 1222 Note that the response is sent independent of the ClientHello 1223 status_request extension contents, and is thus only meant for testing 1224 environments. Real OCSP stapling is more complicated as it requires 1225 choosing a suitable response based on the ClientHello status_request 1226 extension contents. 1227 1228 @raise socket.error: If a socket error occurs. 1229 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 1230 without a preceding alert. 1231 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 1232 @raise tlslite.errors.TLSAuthenticationError: If the checker 1233 doesn't like the other party's authentication credentials. 1234 """ 1235 for result in self.handshakeServerAsync(verifierDB, 1236 certChain, privateKey, reqCert, sessionCache, settings, 1237 checker, reqCAs, reqCertTypes, 1238 tacks=tacks, activationFlags=activationFlags, 1239 nextProtos=nextProtos, anon=anon, 1240 signedCertTimestamps=signedCertTimestamps, 1241 fallbackSCSV=fallbackSCSV, ocspResponse=ocspResponse): 1242 pass 1243 1244 1245 def handshakeServerAsync(self, verifierDB=None, 1246 certChain=None, privateKey=None, reqCert=False, 1247 sessionCache=None, settings=None, checker=None, 1248 reqCAs=None, reqCertTypes=None, 1249 tacks=None, activationFlags=0, 1250 nextProtos=None, anon=False, 1251 signedCertTimestamps=None, 1252 fallbackSCSV=False, 1253 ocspResponse=None 1254 ): 1255 """Start a server handshake operation on the TLS connection. 1256 1257 This function returns a generator which behaves similarly to 1258 handshakeServer(). Successive invocations of the generator 1259 will return 0 if it is waiting to read from the socket, 1 if it is 1260 waiting to write to the socket, or it will raise StopIteration 1261 if the handshake operation is complete. 1262 1263 @rtype: iterable 1264 @return: A generator; see above for details. 1265 """ 1266 handshaker = self._handshakeServerAsyncHelper(\ 1267 verifierDB=verifierDB, certChain=certChain, 1268 privateKey=privateKey, reqCert=reqCert, 1269 sessionCache=sessionCache, settings=settings, 1270 reqCAs=reqCAs, reqCertTypes=reqCertTypes, 1271 tacks=tacks, activationFlags=activationFlags, 1272 nextProtos=nextProtos, anon=anon, 1273 signedCertTimestamps=signedCertTimestamps, 1274 fallbackSCSV=fallbackSCSV, 1275 ocspResponse=ocspResponse) 1276 for result in self._handshakeWrapperAsync(handshaker, checker): 1277 yield result 1278 if settings and settings.alertAfterHandshake: 1279 for result in self._sendError(AlertDescription.internal_error, 1280 "Spurious alert"): 1281 yield result 1282 1283 1284 def _handshakeServerAsyncHelper(self, verifierDB, 1285 certChain, privateKey, reqCert, sessionCache, 1286 settings, reqCAs, reqCertTypes, 1287 tacks, activationFlags, 1288 nextProtos, anon, 1289 signedCertTimestamps, fallbackSCSV, 1290 ocspResponse): 1291 1292 self._handshakeStart(client=False) 1293 1294 if (not verifierDB) and (not certChain) and not anon: 1295 raise ValueError("Caller passed no authentication credentials") 1296 if certChain and not privateKey: 1297 raise ValueError("Caller passed a certChain but no privateKey") 1298 if privateKey and not certChain: 1299 raise ValueError("Caller passed a privateKey but no certChain") 1300 if reqCAs and not reqCert: 1301 raise ValueError("Caller passed reqCAs but not reqCert") 1302 if reqCertTypes and not reqCert: 1303 raise ValueError("Caller passed reqCertTypes but not reqCert") 1304 if certChain and not isinstance(certChain, X509CertChain): 1305 raise ValueError("Unrecognized certificate type") 1306 if activationFlags and not tacks: 1307 raise ValueError("Nonzero activationFlags requires tacks") 1308 if tacks: 1309 if not tackpyLoaded: 1310 raise ValueError("tackpy is not loaded") 1311 if not settings or not settings.useExperimentalTackExtension: 1312 raise ValueError("useExperimentalTackExtension not enabled") 1313 if signedCertTimestamps and not certChain: 1314 raise ValueError("Caller passed signedCertTimestamps but no " 1315 "certChain") 1316 1317 if not settings: 1318 settings = HandshakeSettings() 1319 settings = settings._filter() 1320 1321 # OK Start exchanging messages 1322 # ****************************** 1323 1324 # Handle ClientHello and resumption 1325 for result in self._serverGetClientHello(settings, certChain,\ 1326 verifierDB, sessionCache, 1327 anon, fallbackSCSV): 1328 if result in (0,1): yield result 1329 elif result == None: 1330 self._handshakeDone(resumed=True) 1331 return # Handshake was resumed, we're done 1332 else: break 1333 (clientHello, cipherSuite) = result 1334 1335 # Save the ClientHello for external code to query. 1336 self.clientHello = clientHello 1337 1338 #If not a resumption... 1339 1340 # Create the ServerHello message 1341 if sessionCache: 1342 sessionID = getRandomBytes(32) 1343 else: 1344 sessionID = bytearray(0) 1345 1346 alpn_proto_selected = None 1347 if (clientHello.alpn_protos_advertised is not None 1348 and settings.alpnProtos is not None): 1349 for proto in settings.alpnProtos: 1350 if proto in clientHello.alpn_protos_advertised: 1351 alpn_proto_selected = proto 1352 nextProtos = None 1353 break; 1354 1355 if not clientHello.supports_npn: 1356 nextProtos = None 1357 1358 # If not doing a certificate-based suite, discard the TACK 1359 if not cipherSuite in CipherSuite.certAllSuites: 1360 tacks = None 1361 1362 # Prepare a TACK Extension if requested 1363 if clientHello.tack: 1364 tackExt = TackExtension.create(tacks, activationFlags) 1365 else: 1366 tackExt = None 1367 serverRandom = getRandomBytes(32) 1368 # See https://tools.ietf.org/html/rfc8446#section-4.1.3 1369 if settings.simulateTLS13Downgrade: 1370 serverRandom = serverRandom[:24] + \ 1371 bytearray("\x44\x4f\x57\x4e\x47\x52\x44\x01") 1372 elif settings.simulateTLS12Downgrade: 1373 serverRandom = serverRandom[:24] + \ 1374 bytearray("\x44\x4f\x57\x4e\x47\x52\x44\x00") 1375 serverHello = ServerHello() 1376 serverHello.create(self.version, serverRandom, sessionID, \ 1377 cipherSuite, CertificateType.x509, tackExt, 1378 alpn_proto_selected, 1379 nextProtos) 1380 serverHello.channel_id = \ 1381 clientHello.channel_id and settings.enableChannelID 1382 serverHello.extended_master_secret = \ 1383 clientHello.extended_master_secret and \ 1384 settings.enableExtendedMasterSecret 1385 for param in clientHello.tb_client_params: 1386 if param in settings.supportedTokenBindingParams: 1387 serverHello.tb_params = param 1388 break 1389 if clientHello.support_signed_cert_timestamps: 1390 serverHello.signed_cert_timestamps = signedCertTimestamps 1391 if clientHello.status_request: 1392 serverHello.status_request = ocspResponse 1393 if clientHello.ri: 1394 serverHello.send_ri = True 1395 1396 # Perform the SRP key exchange 1397 clientCertChain = None 1398 if cipherSuite in CipherSuite.srpAllSuites: 1399 for result in self._serverSRPKeyExchange(clientHello, serverHello, 1400 verifierDB, cipherSuite, 1401 privateKey, certChain): 1402 if result in (0,1): yield result 1403 else: break 1404 premasterSecret = result 1405 1406 # Perform a certificate-based key exchange 1407 elif cipherSuite in CipherSuite.certAllSuites: 1408 if cipherSuite in CipherSuite.certSuites: 1409 keyExchange = RSAKeyExchange(cipherSuite, 1410 clientHello, 1411 serverHello, 1412 privateKey) 1413 elif cipherSuite in CipherSuite.dheCertSuites: 1414 keyExchange = DHE_RSAKeyExchange(cipherSuite, 1415 clientHello, 1416 serverHello, 1417 privateKey) 1418 elif cipherSuite in CipherSuite.ecdheCertSuites: 1419 keyExchange = ECDHE_RSAKeyExchange(cipherSuite, 1420 clientHello, 1421 serverHello, 1422 privateKey) 1423 else: 1424 assert(False) 1425 for result in self._serverCertKeyExchange(clientHello, serverHello, 1426 certChain, keyExchange, 1427 reqCert, reqCAs, reqCertTypes, cipherSuite, 1428 settings, ocspResponse): 1429 if result in (0,1): yield result 1430 else: break 1431 (premasterSecret, clientCertChain) = result 1432 1433 # Perform anonymous Diffie Hellman key exchange 1434 elif cipherSuite in CipherSuite.anonSuites: 1435 for result in self._serverAnonKeyExchange(clientHello, serverHello, 1436 cipherSuite, settings): 1437 if result in (0,1): yield result 1438 else: break 1439 premasterSecret = result 1440 1441 else: 1442 assert(False) 1443 1444 # Exchange Finished messages 1445 for result in self._serverFinished(premasterSecret, 1446 clientHello.random, serverHello.random, 1447 cipherSuite, settings.cipherImplementations, 1448 nextProtos, serverHello.channel_id, 1449 serverHello.extended_master_secret): 1450 if result in (0,1): yield result 1451 else: break 1452 masterSecret = result 1453 1454 self.clientRandom = clientHello.random 1455 self.serverRandom = serverHello.random 1456 1457 #Create the session object 1458 self.session = Session() 1459 if cipherSuite in CipherSuite.certAllSuites: 1460 serverCertChain = certChain 1461 else: 1462 serverCertChain = None 1463 srpUsername = None 1464 serverName = None 1465 if clientHello.srp_username: 1466 srpUsername = clientHello.srp_username.decode("utf-8") 1467 if clientHello.server_name: 1468 serverName = clientHello.server_name.decode("utf-8") 1469 self.session.create(masterSecret, serverHello.session_id, cipherSuite, 1470 srpUsername, clientCertChain, serverCertChain, 1471 tackExt, serverHello.tackExt!=None, serverName) 1472 1473 #Add the session object to the session cache 1474 if sessionCache and sessionID: 1475 sessionCache[sessionID] = self.session 1476 1477 self._handshakeDone(resumed=False) 1478 1479 1480 def _isIntolerant(self, settings, clientHello): 1481 if settings.tlsIntolerant is None: 1482 return False 1483 clientVersion = clientHello.client_version 1484 if clientHello.has_supported_versions: 1485 clientVersion = (3, 4) 1486 return clientVersion >= settings.tlsIntolerant 1487 1488 1489 def _serverGetClientHello(self, settings, certChain, verifierDB, 1490 sessionCache, anon, fallbackSCSV): 1491 #Tentatively set version to most-desirable version, so if an error 1492 #occurs parsing the ClientHello, this is what we'll use for the 1493 #error alert 1494 self.version = settings.maxVersion 1495 1496 #Get ClientHello 1497 for result in self._getMsg(ContentType.handshake, 1498 HandshakeType.client_hello): 1499 if result in (0,1): yield result 1500 else: break 1501 clientHello = result 1502 1503 #If client's version is too low, reject it 1504 if clientHello.client_version < settings.minVersion: 1505 self.version = settings.minVersion 1506 for result in self._sendError(\ 1507 AlertDescription.protocol_version, 1508 "Too old version: %s" % str(clientHello.client_version)): 1509 yield result 1510 1511 #If simulating TLS intolerance, reject certain TLS versions. 1512 elif self._isIntolerant(settings, clientHello): 1513 if settings.tlsIntoleranceType == "alert": 1514 for result in self._sendError(\ 1515 AlertDescription.handshake_failure): 1516 yield result 1517 elif settings.tlsIntoleranceType == "close": 1518 self._abruptClose() 1519 raise TLSUnsupportedError("Simulating version intolerance") 1520 elif settings.tlsIntoleranceType == "reset": 1521 self._abruptClose(reset=True) 1522 raise TLSUnsupportedError("Simulating version intolerance") 1523 else: 1524 raise ValueError("Unknown intolerance type: '%s'" % 1525 settings.tlsIntoleranceType) 1526 1527 #If client's version is too high, propose my highest version 1528 elif clientHello.client_version > settings.maxVersion: 1529 self.version = settings.maxVersion 1530 1531 #Detect if the client performed an inappropriate fallback. 1532 elif fallbackSCSV and clientHello.client_version < settings.maxVersion: 1533 self.version = clientHello.client_version 1534 if CipherSuite.TLS_FALLBACK_SCSV in clientHello.cipher_suites: 1535 for result in self._sendError(\ 1536 AlertDescription.inappropriate_fallback): 1537 yield result 1538 1539 else: 1540 #Set the version to the client's version 1541 self.version = clientHello.client_version 1542 1543 #Initialize acceptable cipher suites 1544 cipherSuites = [] 1545 if verifierDB: 1546 if certChain: 1547 cipherSuites += \ 1548 CipherSuite.getSrpCertSuites(settings, self.version) 1549 cipherSuites += CipherSuite.getSrpSuites(settings, self.version) 1550 elif certChain: 1551 cipherSuites += CipherSuite.getEcdheCertSuites(settings, self.version) 1552 cipherSuites += CipherSuite.getDheCertSuites(settings, self.version) 1553 cipherSuites += CipherSuite.getCertSuites(settings, self.version) 1554 elif anon: 1555 cipherSuites += CipherSuite.getAnonSuites(settings, self.version) 1556 else: 1557 assert(False) 1558 1559 alpn_proto_selected = None 1560 if (clientHello.alpn_protos_advertised is not None 1561 and settings.alpnProtos is not None): 1562 for proto in settings.alpnProtos: 1563 if proto in clientHello.alpn_protos_advertised: 1564 alpn_proto_selected = proto 1565 break; 1566 1567 #If resumption was requested and we have a session cache... 1568 if clientHello.session_id and sessionCache: 1569 session = None 1570 1571 #Check in the session cache 1572 if sessionCache and not session: 1573 try: 1574 session = sessionCache[clientHello.session_id] 1575 if not session.resumable: 1576 raise AssertionError() 1577 #Check for consistency with ClientHello 1578 if session.cipherSuite not in cipherSuites: 1579 for result in self._sendError(\ 1580 AlertDescription.handshake_failure): 1581 yield result 1582 if session.cipherSuite not in clientHello.cipher_suites: 1583 for result in self._sendError(\ 1584 AlertDescription.handshake_failure): 1585 yield result 1586 if clientHello.srp_username: 1587 if not session.srpUsername or \ 1588 clientHello.srp_username != bytearray(session.srpUsername, "utf-8"): 1589 for result in self._sendError(\ 1590 AlertDescription.handshake_failure): 1591 yield result 1592 if clientHello.server_name: 1593 if not session.serverName or \ 1594 clientHello.server_name != bytearray(session.serverName, "utf-8"): 1595 for result in self._sendError(\ 1596 AlertDescription.handshake_failure): 1597 yield result 1598 except KeyError: 1599 pass 1600 1601 #If a session is found.. 1602 if session: 1603 #Send ServerHello 1604 serverHello = ServerHello() 1605 serverHello.create(self.version, getRandomBytes(32), 1606 session.sessionID, session.cipherSuite, 1607 CertificateType.x509, None, 1608 alpn_proto_selected, None) 1609 serverHello.extended_master_secret = \ 1610 clientHello.extended_master_secret and \ 1611 settings.enableExtendedMasterSecret 1612 for param in clientHello.tb_client_params: 1613 if param in settings.supportedTokenBindingParams: 1614 serverHello.tb_params = param 1615 break 1616 if clientHello.ri: 1617 serverHello.send_ri = True 1618 for result in self._sendMsg(serverHello): 1619 yield result 1620 1621 #From here on, the client's messages must have right version 1622 self._versionCheck = True 1623 1624 #Calculate pending connection states 1625 self._calcPendingStates(session.cipherSuite, 1626 session.masterSecret, 1627 clientHello.random, 1628 serverHello.random, 1629 settings.cipherImplementations) 1630 1631 #Exchange ChangeCipherSpec and Finished messages 1632 for result in self._sendFinished(session.masterSecret): 1633 yield result 1634 for result in self._getFinished(session.masterSecret): 1635 yield result 1636 1637 #Set the session 1638 self.session = session 1639 1640 self.clientRandom = clientHello.random 1641 self.serverRandom = serverHello.random 1642 yield None # Handshake done! 1643 1644 #Calculate the first cipher suite intersection. 1645 #This is the 'privileged' ciphersuite. We'll use it if we're 1646 #doing a new negotiation. In fact, 1647 #the only time we won't use it is if we're resuming a 1648 #session, in which case we use the ciphersuite from the session. 1649 # 1650 #Given the current ciphersuite ordering, this means we prefer SRP 1651 #over non-SRP. 1652 for cipherSuite in cipherSuites: 1653 if cipherSuite in clientHello.cipher_suites: 1654 break 1655 else: 1656 for result in self._sendError(\ 1657 AlertDescription.handshake_failure, 1658 "No mutual ciphersuite"): 1659 yield result 1660 if cipherSuite in CipherSuite.srpAllSuites and \ 1661 not clientHello.srp_username: 1662 for result in self._sendError(\ 1663 AlertDescription.unknown_psk_identity, 1664 "Client sent a hello, but without the SRP username"): 1665 yield result 1666 1667 #If an RSA suite is chosen, check for certificate type intersection 1668 if cipherSuite in CipherSuite.certAllSuites and CertificateType.x509 \ 1669 not in clientHello.certificate_types: 1670 for result in self._sendError(\ 1671 AlertDescription.handshake_failure, 1672 "the client doesn't support my certificate type"): 1673 yield result 1674 1675 # If resumption was not requested, or 1676 # we have no session cache, or 1677 # the client's session_id was not found in cache: 1678 yield (clientHello, cipherSuite) 1679 1680 def _serverSRPKeyExchange(self, clientHello, serverHello, verifierDB, 1681 cipherSuite, privateKey, serverCertChain): 1682 1683 srpUsername = clientHello.srp_username.decode("utf-8") 1684 self.allegedSrpUsername = srpUsername 1685 #Get parameters from username 1686 try: 1687 entry = verifierDB[srpUsername] 1688 except KeyError: 1689 for result in self._sendError(\ 1690 AlertDescription.unknown_psk_identity): 1691 yield result 1692 (N, g, s, v) = entry 1693 1694 #Calculate server's ephemeral DH values (b, B) 1695 b = bytesToNumber(getRandomBytes(32)) 1696 k = makeK(N, g) 1697 B = (powMod(g, b, N) + (k*v)) % N 1698 1699 #Create ServerKeyExchange, signing it if necessary 1700 serverKeyExchange = ServerKeyExchange(cipherSuite, self.version) 1701 serverKeyExchange.createSRP(N, g, s, B) 1702 if cipherSuite in CipherSuite.srpCertSuites: 1703 hashBytes = serverKeyExchange.hash(clientHello.random, 1704 serverHello.random) 1705 serverKeyExchange.signature = privateKey.sign(hashBytes) 1706 1707 #Send ServerHello[, Certificate], ServerKeyExchange, 1708 #ServerHelloDone 1709 msgs = [] 1710 msgs.append(serverHello) 1711 if cipherSuite in CipherSuite.srpCertSuites: 1712 certificateMsg = Certificate(CertificateType.x509) 1713 certificateMsg.create(serverCertChain) 1714 msgs.append(certificateMsg) 1715 msgs.append(serverKeyExchange) 1716 msgs.append(ServerHelloDone()) 1717 for result in self._sendMsgs(msgs): 1718 yield result 1719 1720 #From here on, the client's messages must have the right version 1721 self._versionCheck = True 1722 1723 #Get and check ClientKeyExchange 1724 for result in self._getMsg(ContentType.handshake, 1725 HandshakeType.client_key_exchange, 1726 cipherSuite): 1727 if result in (0,1): yield result 1728 else: break 1729 clientKeyExchange = result 1730 A = clientKeyExchange.srp_A 1731 if A % N == 0: 1732 for result in self._sendError(AlertDescription.illegal_parameter, 1733 "Suspicious A value"): 1734 yield result 1735 assert(False) # Just to ensure we don't fall through somehow 1736 1737 #Calculate u 1738 u = makeU(N, A, B) 1739 1740 #Calculate premaster secret 1741 S = powMod((A * powMod(v,u,N)) % N, b, N) 1742 premasterSecret = numberToByteArray(S) 1743 1744 yield premasterSecret 1745 1746 1747 def _serverCertKeyExchange(self, clientHello, serverHello, 1748 serverCertChain, keyExchange, 1749 reqCert, reqCAs, reqCertTypes, cipherSuite, 1750 settings, ocspResponse): 1751 #Send ServerHello, Certificate[, ServerKeyExchange] 1752 #[, CertificateRequest], ServerHelloDone 1753 msgs = [] 1754 1755 # If we verify a client cert chain, return it 1756 clientCertChain = None 1757 1758 msgs.append(serverHello) 1759 msgs.append(Certificate(CertificateType.x509).create(serverCertChain)) 1760 if serverHello.status_request: 1761 msgs.append(CertificateStatus().create(ocspResponse)) 1762 serverKeyExchange = keyExchange.makeServerKeyExchange() 1763 if serverKeyExchange is not None: 1764 msgs.append(serverKeyExchange) 1765 if reqCert: 1766 reqCAs = reqCAs or [] 1767 #Apple's Secure Transport library rejects empty certificate_types, 1768 #so default to rsa_sign. 1769 reqCertTypes = reqCertTypes or [ClientCertificateType.rsa_sign] 1770 #Only SHA-1 + RSA is supported. 1771 sigAlgs = [(HashAlgorithm.sha1, SignatureAlgorithm.rsa)] 1772 msgs.append(CertificateRequest(self.version).create(reqCertTypes, 1773 reqCAs, 1774 sigAlgs)) 1775 msgs.append(ServerHelloDone()) 1776 for result in self._sendMsgs(msgs): 1777 yield result 1778 1779 #From here on, the client's messages must have the right version 1780 self._versionCheck = True 1781 1782 #Get [Certificate,] (if was requested) 1783 if reqCert: 1784 if self.version == (3,0): 1785 for result in self._getMsg((ContentType.handshake, 1786 ContentType.alert), 1787 HandshakeType.certificate, 1788 CertificateType.x509): 1789 if result in (0,1): yield result 1790 else: break 1791 msg = result 1792 1793 if isinstance(msg, Alert): 1794 #If it's not a no_certificate alert, re-raise 1795 alert = msg 1796 if alert.description != \ 1797 AlertDescription.no_certificate: 1798 self._shutdown(False) 1799 raise TLSRemoteAlert(alert) 1800 elif isinstance(msg, Certificate): 1801 clientCertificate = msg 1802 if clientCertificate.certChain and \ 1803 clientCertificate.certChain.getNumCerts()!=0: 1804 clientCertChain = clientCertificate.certChain 1805 else: 1806 raise AssertionError() 1807 elif self.version in ((3,1), (3,2), (3,3)): 1808 for result in self._getMsg(ContentType.handshake, 1809 HandshakeType.certificate, 1810 CertificateType.x509): 1811 if result in (0,1): yield result 1812 else: break 1813 clientCertificate = result 1814 if clientCertificate.certChain and \ 1815 clientCertificate.certChain.getNumCerts()!=0: 1816 clientCertChain = clientCertificate.certChain 1817 else: 1818 raise AssertionError() 1819 1820 #Get ClientKeyExchange 1821 for result in self._getMsg(ContentType.handshake, 1822 HandshakeType.client_key_exchange, 1823 cipherSuite): 1824 if result in (0,1): yield result 1825 else: break 1826 clientKeyExchange = result 1827 1828 #Process ClientKeyExchange 1829 try: 1830 premasterSecret = \ 1831 keyExchange.processClientKeyExchange(clientKeyExchange) 1832 except alert as TLSLocalAlert: 1833 for result in self._sendError(alert.description, alert.message): 1834 yield result 1835 1836 #Get and check CertificateVerify, if relevant 1837 if clientCertChain: 1838 if self.version == (3,0): 1839 masterSecret = calcMasterSecret(self.version, premasterSecret, 1840 clientHello.random, serverHello.random, 1841 b"", False) 1842 verifyBytes = self._calcSSLHandshakeHash(masterSecret, b"") 1843 elif self.version in ((3,1), (3,2)): 1844 verifyBytes = self._handshake_md5.digest() + \ 1845 self._handshake_sha.digest() 1846 elif self.version == (3,3): 1847 verifyBytes = self._handshake_sha.digest() 1848 verifyBytes = RSAKey.addPKCS1SHA1Prefix(verifyBytes) 1849 for result in self._getMsg(ContentType.handshake, 1850 HandshakeType.certificate_verify): 1851 if result in (0,1): yield result 1852 else: break 1853 certificateVerify = result 1854 publicKey = clientCertChain.getEndEntityPublicKey() 1855 if len(publicKey) < settings.minKeySize: 1856 for result in self._sendError(\ 1857 AlertDescription.handshake_failure, 1858 "Client's public key too small: %d" % len(publicKey)): 1859 yield result 1860 1861 if len(publicKey) > settings.maxKeySize: 1862 for result in self._sendError(\ 1863 AlertDescription.handshake_failure, 1864 "Client's public key too large: %d" % len(publicKey)): 1865 yield result 1866 1867 if not publicKey.verify(certificateVerify.signature, verifyBytes): 1868 for result in self._sendError(\ 1869 AlertDescription.decrypt_error, 1870 "Signature failed to verify"): 1871 yield result 1872 yield (premasterSecret, clientCertChain) 1873 1874 1875 def _serverAnonKeyExchange(self, clientHello, serverHello, cipherSuite, 1876 settings): 1877 # Calculate DH p, g, Xs, Ys 1878 dh_p = getRandomSafePrime(32, False) 1879 dh_g = getRandomNumber(2, dh_p) 1880 dh_Xs = bytesToNumber(getRandomBytes(32)) 1881 dh_Ys = powMod(dh_g, dh_Xs, dh_p) 1882 1883 #Create ServerKeyExchange 1884 serverKeyExchange = ServerKeyExchange(cipherSuite, self.version) 1885 serverKeyExchange.createDH(dh_p, dh_g, dh_Ys) 1886 1887 #Send ServerHello[, Certificate], ServerKeyExchange, 1888 #ServerHelloDone 1889 msgs = [] 1890 msgs.append(serverHello) 1891 msgs.append(serverKeyExchange) 1892 msgs.append(ServerHelloDone()) 1893 for result in self._sendMsgs(msgs): 1894 yield result 1895 1896 #From here on, the client's messages must have the right version 1897 self._versionCheck = True 1898 1899 #Get and check ClientKeyExchange 1900 for result in self._getMsg(ContentType.handshake, 1901 HandshakeType.client_key_exchange, 1902 cipherSuite): 1903 if result in (0,1): 1904 yield result 1905 else: 1906 break 1907 clientKeyExchange = result 1908 dh_Yc = clientKeyExchange.dh_Yc 1909 1910 if dh_Yc % dh_p == 0: 1911 for result in self._sendError(AlertDescription.illegal_parameter, 1912 "Suspicious dh_Yc value"): 1913 yield result 1914 assert(False) # Just to ensure we don't fall through somehow 1915 1916 #Calculate premaster secre 1917 S = powMod(dh_Yc,dh_Xs,dh_p) 1918 premasterSecret = numberToByteArray(S) 1919 1920 yield premasterSecret 1921 1922 1923 def _serverFinished(self, premasterSecret, clientRandom, serverRandom, 1924 cipherSuite, cipherImplementations, nextProtos, 1925 doingChannelID, useExtendedMasterSecret): 1926 masterSecret = calcMasterSecret(self.version, premasterSecret, 1927 clientRandom, serverRandom, 1928 self._ems_handshake_hash, 1929 useExtendedMasterSecret) 1930 1931 #Calculate pending connection states 1932 self._calcPendingStates(cipherSuite, masterSecret, 1933 clientRandom, serverRandom, 1934 cipherImplementations) 1935 1936 #Exchange ChangeCipherSpec and Finished messages 1937 for result in self._getFinished(masterSecret, 1938 expect_next_protocol=nextProtos is not None, 1939 expect_channel_id=doingChannelID): 1940 yield result 1941 1942 for result in self._sendFinished(masterSecret): 1943 yield result 1944 1945 yield masterSecret 1946 1947 1948 #********************************************************* 1949 # Shared Handshake Functions 1950 #********************************************************* 1951 1952 1953 def _sendFinished(self, masterSecret, nextProto=None): 1954 #Send ChangeCipherSpec 1955 for result in self._sendMsg(ChangeCipherSpec()): 1956 yield result 1957 1958 #Switch to pending write state 1959 self._changeWriteState() 1960 1961 if nextProto is not None: 1962 nextProtoMsg = NextProtocol().create(nextProto) 1963 for result in self._sendMsg(nextProtoMsg): 1964 yield result 1965 1966 #Calculate verification data 1967 verifyData = self._calcFinished(masterSecret, True) 1968 if self.fault == Fault.badFinished: 1969 verifyData[0] = (verifyData[0]+1)%256 1970 1971 #Send Finished message under new state 1972 finished = Finished(self.version).create(verifyData) 1973 for result in self._sendMsg(finished): 1974 yield result 1975 1976 def _getFinished(self, masterSecret, expect_next_protocol=False, nextProto=None, 1977 expect_channel_id=False): 1978 #Get and check ChangeCipherSpec 1979 for result in self._getMsg(ContentType.change_cipher_spec): 1980 if result in (0,1): 1981 yield result 1982 changeCipherSpec = result 1983 1984 if changeCipherSpec.type != 1: 1985 for result in self._sendError(AlertDescription.illegal_parameter, 1986 "ChangeCipherSpec type incorrect"): 1987 yield result 1988 1989 #Switch to pending read state 1990 self._changeReadState() 1991 1992 #Server Finish - Are we waiting for a next protocol echo? 1993 if expect_next_protocol: 1994 for result in self._getMsg(ContentType.handshake, HandshakeType.next_protocol): 1995 if result in (0,1): 1996 yield result 1997 if result is None: 1998 for result in self._sendError(AlertDescription.unexpected_message, 1999 "Didn't get NextProtocol message"): 2000 yield result 2001 2002 self.next_proto = result.next_proto 2003 else: 2004 self.next_proto = None 2005 2006 #Client Finish - Only set the next_protocol selected in the connection 2007 if nextProto: 2008 self.next_proto = nextProto 2009 2010 #Server Finish - Are we waiting for a EncryptedExtensions? 2011 if expect_channel_id: 2012 for result in self._getMsg(ContentType.handshake, HandshakeType.encrypted_extensions): 2013 if result in (0,1): 2014 yield result 2015 if result is None: 2016 for result in self._sendError(AlertDescription.unexpected_message, 2017 "Didn't get EncryptedExtensions message"): 2018 yield result 2019 encrypted_extensions = result 2020 self.channel_id = result.channel_id_key 2021 else: 2022 self.channel_id = None 2023 2024 #Calculate verification data 2025 verifyData = self._calcFinished(masterSecret, False) 2026 2027 #Get and check Finished message under new state 2028 for result in self._getMsg(ContentType.handshake, 2029 HandshakeType.finished): 2030 if result in (0,1): 2031 yield result 2032 finished = result 2033 if finished.verify_data != verifyData: 2034 for result in self._sendError(AlertDescription.decrypt_error, 2035 "Finished message is incorrect"): 2036 yield result 2037 2038 def _calcFinished(self, masterSecret, send=True): 2039 if self.version == (3,0): 2040 if (self._client and send) or (not self._client and not send): 2041 senderStr = b"\x43\x4C\x4E\x54" 2042 else: 2043 senderStr = b"\x53\x52\x56\x52" 2044 2045 verifyData = self._calcSSLHandshakeHash(masterSecret, senderStr) 2046 return verifyData 2047 2048 elif self.version in ((3,1), (3,2)): 2049 if (self._client and send) or (not self._client and not send): 2050 label = b"client finished" 2051 else: 2052 label = b"server finished" 2053 2054 handshakeHashes = self._handshake_md5.digest() + \ 2055 self._handshake_sha.digest() 2056 verifyData = PRF(masterSecret, label, handshakeHashes, 12) 2057 return verifyData 2058 elif self.version == (3,3): 2059 if (self._client and send) or (not self._client and not send): 2060 label = b"client finished" 2061 else: 2062 label = b"server finished" 2063 2064 handshakeHashes = self._handshake_sha256.digest() 2065 verifyData = PRF_1_2(masterSecret, label, handshakeHashes, 12) 2066 return verifyData 2067 else: 2068 raise AssertionError() 2069 2070 2071 def _handshakeWrapperAsync(self, handshaker, checker): 2072 if not self.fault: 2073 try: 2074 for result in handshaker: 2075 yield result 2076 if checker: 2077 try: 2078 checker(self) 2079 except TLSAuthenticationError: 2080 alert = Alert().create(AlertDescription.close_notify, 2081 AlertLevel.fatal) 2082 for result in self._sendMsg(alert): 2083 yield result 2084 raise 2085 except GeneratorExit: 2086 raise 2087 except TLSAlert as alert: 2088 if not self.fault: 2089 raise 2090 if alert.description not in Fault.faultAlerts[self.fault]: 2091 raise TLSFaultError(str(alert)) 2092 else: 2093 pass 2094 except: 2095 self._shutdown(False) 2096 raise 2097 2098 2099 def exportKeyingMaterial(self, label, context, use_context, length): 2100 """Returns the exported keying material as defined in RFC 5705.""" 2101 2102 seed = self.clientRandom + self.serverRandom 2103 if use_context: 2104 if len(context) > 65535: 2105 raise ValueError("Context is too long") 2106 seed += bytearray(2) 2107 seed[len(seed) - 2] = len(context) >> 8 2108 seed[len(seed) - 1] = len(context) & 0xFF 2109 seed += context 2110 if self.version in ((3,1), (3,2)): 2111 return PRF(self.session.masterSecret, label, seed, length) 2112 elif self.version == (3,3): 2113 return PRF_1_2(self.session.masterSecret, label, seed, length) 2114 else: 2115 raise AssertionError() 2116