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

Source Code for Module tlslite.tlsrecordlayer

   1  # Authors:  
   2  #   Trevor Perrin 
   3  #   Google (adapted by Sam Rushing) - NPN support 
   4  #   Martin von Loewis - python 3 port 
   5  # 
   6  # See the LICENSE file for legal information regarding use of this file. 
   7   
   8  """Helper class for TLSConnection.""" 
   9  from __future__ import generators 
  10   
  11  from .utils.compat import * 
  12  from .utils.cryptomath import * 
  13  from .utils.cipherfactory import createAES, createRC4, createTripleDES 
  14  from .utils.codec import * 
  15  from .errors import * 
  16  from .messages import * 
  17  from .mathtls import * 
  18  from .constants import * 
  19  from .utils.cryptomath import getRandomBytes 
  20   
  21  import socket 
  22  import errno 
  23  import traceback 
  24   
25 -class _ConnectionState(object):
26 - def __init__(self):
27 self.macContext = None 28 self.encContext = None 29 self.seqnum = 0
30
31 - def getSeqNumBytes(self):
32 w = Writer() 33 w.add(self.seqnum, 8) 34 self.seqnum += 1 35 return w.bytes
36 37
38 -class TLSRecordLayer(object):
39 """ 40 This class handles data transmission for a TLS connection. 41 42 Its only subclass is L{tlslite.TLSConnection.TLSConnection}. We've 43 separated the code in this class from TLSConnection to make things 44 more readable. 45 46 47 @type sock: socket.socket 48 @ivar sock: The underlying socket object. 49 50 @type session: L{tlslite.Session.Session} 51 @ivar session: The session corresponding to this connection. 52 53 Due to TLS session resumption, multiple connections can correspond 54 to the same underlying session. 55 56 @type version: tuple 57 @ivar version: The TLS version being used for this connection. 58 59 (3,0) means SSL 3.0, and (3,1) means TLS 1.0. 60 61 @type closed: bool 62 @ivar closed: If this connection is closed. 63 64 @type resumed: bool 65 @ivar resumed: If this connection is based on a resumed session. 66 67 @type allegedSrpUsername: str or None 68 @ivar allegedSrpUsername: This is set to the SRP username 69 asserted by the client, whether the handshake succeeded or not. 70 If the handshake fails, this can be inspected to determine 71 if a guessing attack is in progress against a particular user 72 account. 73 74 @type closeSocket: bool 75 @ivar closeSocket: If the socket should be closed when the 76 connection is closed, defaults to True (writable). 77 78 If you set this to True, TLS Lite will assume the responsibility of 79 closing the socket when the TLS Connection is shutdown (either 80 through an error or through the user calling close()). The default 81 is False. 82 83 @type ignoreAbruptClose: bool 84 @ivar ignoreAbruptClose: If an abrupt close of the socket should 85 raise an error (writable). 86 87 If you set this to True, TLS Lite will not raise a 88 L{tlslite.errors.TLSAbruptCloseError} exception if the underlying 89 socket is unexpectedly closed. Such an unexpected closure could be 90 caused by an attacker. However, it also occurs with some incorrect 91 TLS implementations. 92 93 You should set this to True only if you're not worried about an 94 attacker truncating the connection, and only if necessary to avoid 95 spurious errors. The default is False. 96 97 @sort: __init__, read, readAsync, write, writeAsync, close, closeAsync, 98 getCipherImplementation, getCipherName 99 """ 100
101 - def __init__(self, sock):
102 self.sock = sock 103 104 #My session object (Session instance; read-only) 105 self.session = None 106 107 #Am I a client or server? 108 self._client = None 109 110 #Buffers for processing messages 111 self._handshakeBuffer = [] 112 self.clearReadBuffer() 113 self.clearWriteBuffer() 114 115 #Handshake digests 116 self._handshake_md5 = hashlib.md5() 117 self._handshake_sha = hashlib.sha1() 118 self._handshake_sha256 = hashlib.sha256() 119 120 #TLS Protocol Version 121 self.version = (0,0) #read-only 122 self._versionCheck = False #Once we choose a version, this is True 123 124 #Current and Pending connection states 125 self._writeState = _ConnectionState() 126 self._readState = _ConnectionState() 127 self._pendingWriteState = _ConnectionState() 128 self._pendingReadState = _ConnectionState() 129 130 #Is the connection open? 131 self.closed = True #read-only 132 self._refCount = 0 #Used to trigger closure 133 134 #Is this a resumed session? 135 self.resumed = False #read-only 136 137 #What username did the client claim in his handshake? 138 self.allegedSrpUsername = None 139 140 #On a call to close(), do we close the socket? (writeable) 141 self.closeSocket = True 142 143 #If the socket is abruptly closed, do we ignore it 144 #and pretend the connection was shut down properly? (writeable) 145 self.ignoreAbruptClose = False 146 147 #Fault we will induce, for testing purposes 148 self.fault = None
149
150 - def clearReadBuffer(self):
151 self._readBuffer = b''
152
153 - def clearWriteBuffer(self):
154 self._send_writer = None
155 156 157 #********************************************************* 158 # Public Functions START 159 #********************************************************* 160
161 - def read(self, max=None, min=1):
162 """Read some data from the TLS connection. 163 164 This function will block until at least 'min' bytes are 165 available (or the connection is closed). 166 167 If an exception is raised, the connection will have been 168 automatically closed. 169 170 @type max: int 171 @param max: The maximum number of bytes to return. 172 173 @type min: int 174 @param min: The minimum number of bytes to return 175 176 @rtype: str 177 @return: A string of no more than 'max' bytes, and no fewer 178 than 'min' (unless the connection has been closed, in which 179 case fewer than 'min' bytes may be returned). 180 181 @raise socket.error: If a socket error occurs. 182 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 183 without a preceding alert. 184 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 185 """ 186 for result in self.readAsync(max, min): 187 pass 188 return result
189
190 - def readAsync(self, max=None, min=1):
191 """Start a read operation on the TLS connection. 192 193 This function returns a generator which behaves similarly to 194 read(). Successive invocations of the generator will return 0 195 if it is waiting to read from the socket, 1 if it is waiting 196 to write to the socket, or a string if the read operation has 197 completed. 198 199 @rtype: iterable 200 @return: A generator; see above for details. 201 """ 202 try: 203 while len(self._readBuffer)<min and not self.closed: 204 try: 205 for result in self._getMsg(ContentType.application_data): 206 if result in (0,1): 207 yield result 208 applicationData = result 209 self._readBuffer += applicationData.write() 210 except TLSRemoteAlert as alert: 211 if alert.description != AlertDescription.close_notify: 212 raise 213 except TLSAbruptCloseError: 214 if not self.ignoreAbruptClose: 215 raise 216 else: 217 self._shutdown(True) 218 219 if max == None: 220 max = len(self._readBuffer) 221 222 returnBytes = self._readBuffer[:max] 223 self._readBuffer = self._readBuffer[max:] 224 yield bytes(returnBytes) 225 except GeneratorExit: 226 raise 227 except: 228 self._shutdown(False) 229 raise
230
231 - def unread(self, b):
232 """Add bytes to the front of the socket read buffer for future 233 reading. Be careful using this in the context of select(...): if you 234 unread the last data from a socket, that won't wake up selected waiters, 235 and those waiters may hang forever. 236 """ 237 self._readBuffer = b + self._readBuffer
238
239 - def write(self, s):
240 """Write some data to the TLS connection. 241 242 This function will block until all the data has been sent. 243 244 If an exception is raised, the connection will have been 245 automatically closed. 246 247 @type s: str 248 @param s: The data to transmit to the other party. 249 250 @raise socket.error: If a socket error occurs. 251 """ 252 for result in self.writeAsync(s): 253 pass
254
255 - def writeAsync(self, s):
256 """Start a write operation on the TLS connection. 257 258 This function returns a generator which behaves similarly to 259 write(). Successive invocations of the generator will return 260 1 if it is waiting to write to the socket, or will raise 261 StopIteration if the write operation has completed. 262 263 @rtype: iterable 264 @return: A generator; see above for details. 265 """ 266 try: 267 if self.closed: 268 raise TLSClosedConnectionError("attempt to write to closed connection") 269 270 index = 0 271 blockSize = 16384 272 randomizeFirstBlock = True 273 while 1: 274 startIndex = index * blockSize 275 endIndex = startIndex + blockSize 276 if startIndex >= len(s): 277 break 278 if endIndex > len(s): 279 endIndex = len(s) 280 block = bytearray(s[startIndex : endIndex]) 281 applicationData = ApplicationData().create(block) 282 for result in self._sendMsg(applicationData, \ 283 randomizeFirstBlock): 284 yield result 285 randomizeFirstBlock = False #only on 1st message 286 index += 1 287 except GeneratorExit: 288 raise 289 except Exception: 290 self._shutdown(False) 291 raise
292
293 - def close(self):
294 """Close the TLS connection. 295 296 This function will block until it has exchanged close_notify 297 alerts with the other party. After doing so, it will shut down the 298 TLS connection. Further attempts to read through this connection 299 will return "". Further attempts to write through this connection 300 will raise ValueError. 301 302 If makefile() has been called on this connection, the connection 303 will be not be closed until the connection object and all file 304 objects have been closed. 305 306 Even if an exception is raised, the connection will have been 307 closed. 308 309 @raise socket.error: If a socket error occurs. 310 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 311 without a preceding alert. 312 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 313 """ 314 if not self.closed: 315 for result in self._decrefAsync(): 316 pass
317 318 # Python 3 callback 319 _decref_socketios = close 320
321 - def closeAsync(self):
322 """Start a close operation on the TLS connection. 323 324 This function returns a generator which behaves similarly to 325 close(). Successive invocations of the generator will return 0 326 if it is waiting to read from the socket, 1 if it is waiting 327 to write to the socket, or will raise StopIteration if the 328 close operation has completed. 329 330 @rtype: iterable 331 @return: A generator; see above for details. 332 """ 333 if not self.closed: 334 for result in self._decrefAsync(): 335 yield result
336
337 - def _decrefAsync(self):
338 self._refCount -= 1 339 if self._refCount == 0 and not self.closed: 340 try: 341 for result in self._sendMsg(Alert().create(\ 342 AlertDescription.close_notify, AlertLevel.warning)): 343 yield result 344 alert = None 345 # By default close the socket, since it's been observed 346 # that some other libraries will not respond to the 347 # close_notify alert, thus leaving us hanging if we're 348 # expecting it 349 if self.closeSocket: 350 self._shutdown(True) 351 else: 352 while not alert: 353 for result in self._getMsg((ContentType.alert, \ 354 ContentType.application_data)): 355 if result in (0,1): 356 yield result 357 if result.contentType == ContentType.alert: 358 alert = result 359 if alert.description == AlertDescription.close_notify: 360 self._shutdown(True) 361 else: 362 raise TLSRemoteAlert(alert) 363 except (socket.error, TLSAbruptCloseError): 364 #If the other side closes the socket, that's okay 365 self._shutdown(True) 366 except GeneratorExit: 367 raise 368 except: 369 self._shutdown(False) 370 raise
371
372 - def getVersionName(self):
373 """Get the name of this TLS version. 374 375 @rtype: str 376 @return: The name of the TLS version used with this connection. 377 Either None, 'SSL 3.0', 'TLS 1.0', 'TLS 1.1', or 'TLS 1.2'. 378 """ 379 if self.version == (3,0): 380 return "SSL 3.0" 381 elif self.version == (3,1): 382 return "TLS 1.0" 383 elif self.version == (3,2): 384 return "TLS 1.1" 385 elif self.version == (3,3): 386 return "TLS 1.2" 387 else: 388 return None
389
390 - def getCipherName(self):
391 """Get the name of the cipher used with this connection. 392 393 @rtype: str 394 @return: The name of the cipher used with this connection. 395 Either 'aes128', 'aes256', 'rc4', or '3des'. 396 """ 397 if not self._writeState.encContext: 398 return None 399 return self._writeState.encContext.name
400
401 - def getCipherImplementation(self):
402 """Get the name of the cipher implementation used with 403 this connection. 404 405 @rtype: str 406 @return: The name of the cipher implementation used with 407 this connection. Either 'python', 'openssl', or 'pycrypto'. 408 """ 409 if not self._writeState.encContext: 410 return None 411 return self._writeState.encContext.implementation
412 413 414 415 #Emulate a socket, somewhat -
416 - def send(self, s):
417 """Send data to the TLS connection (socket emulation). 418 419 @raise socket.error: If a socket error occurs. 420 """ 421 self.write(s) 422 return len(s)
423
424 - def sendall(self, s):
425 """Send data to the TLS connection (socket emulation). 426 427 @raise socket.error: If a socket error occurs. 428 """ 429 self.write(s)
430
431 - def recv(self, bufsize):
432 """Get some data from the TLS connection (socket emulation). 433 434 @raise socket.error: If a socket error occurs. 435 @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed 436 without a preceding alert. 437 @raise tlslite.errors.TLSAlert: If a TLS alert is signalled. 438 """ 439 return self.read(bufsize)
440
441 - def recv_into(self, b):
442 # XXX doc string 443 data = self.read(len(b)) 444 if not data: 445 return None 446 b[:len(data)] = data 447 return len(data)
448
449 - def makefile(self, mode='r', bufsize=-1):
450 """Create a file object for the TLS connection (socket emulation). 451 452 @rtype: L{socket._fileobject} 453 """ 454 self._refCount += 1 455 # So, it is pretty fragile to be using Python internal objects 456 # like this, but it is probably the best/easiest way to provide 457 # matching behavior for socket emulation purposes. The 'close' 458 # argument is nice, its apparently a recent addition to this 459 # class, so that when fileobject.close() gets called, it will 460 # close() us, causing the refcount to be decremented (decrefAsync). 461 # 462 # If this is the last close() on the outstanding fileobjects / 463 # TLSConnection, then the "actual" close alerts will be sent, 464 # socket closed, etc. 465 if sys.version_info < (3,): 466 return socket._fileobject(self, mode, bufsize, close=True) 467 else: 468 # XXX need to wrap this further if buffering is requested 469 return socket.SocketIO(self, mode)
470
471 - def getsockname(self):
472 """Return the socket's own address (socket emulation).""" 473 return self.sock.getsockname()
474
475 - def getpeername(self):
476 """Return the remote address to which the socket is connected 477 (socket emulation).""" 478 return self.sock.getpeername()
479
480 - def settimeout(self, value):
481 """Set a timeout on blocking socket operations (socket emulation).""" 482 return self.sock.settimeout(value)
483
484 - def gettimeout(self):
485 """Return the timeout associated with socket operations (socket 486 emulation).""" 487 return self.sock.gettimeout()
488
489 - def setsockopt(self, level, optname, value):
490 """Set the value of the given socket option (socket emulation).""" 491 return self.sock.setsockopt(level, optname, value)
492
493 - def shutdown(self, how):
494 """Shutdown the underlying socket.""" 495 return self.sock.shutdown(how)
496
497 - def fileno(self):
498 """Not implement in TLS Lite.""" 499 raise NotImplementedError()
500 501 502 #********************************************************* 503 # Public Functions END 504 #********************************************************* 505
506 - def _shutdown(self, resumable):
507 self._writeState = _ConnectionState() 508 self._readState = _ConnectionState() 509 self.version = (0,0) 510 self._versionCheck = False 511 self.closed = True 512 if self.closeSocket: 513 self.sock.close() 514 515 #Even if resumable is False, we'll never toggle this on 516 if not resumable and self.session: 517 self.session.resumable = False
518 519
520 - def _sendError(self, alertDescription, errorStr=None):
521 alert = Alert().create(alertDescription, AlertLevel.fatal) 522 for result in self._sendMsg(alert): 523 yield result 524 self._shutdown(False) 525 raise TLSLocalAlert(alert, errorStr)
526
527 - def _sendMsgs(self, msgs):
528 randomizeFirstBlock = True 529 for msg in msgs: 530 for result in self._sendMsg(msg, randomizeFirstBlock): 531 yield result 532 randomizeFirstBlock = True
533
534 - def _sendMsg(self, msg, randomizeFirstBlock = True):
535 #Whenever we're connected and asked to send an app data message, 536 #we first send the first byte of the message. This prevents 537 #an attacker from launching a chosen-plaintext attack based on 538 #knowing the next IV (a la BEAST). 539 if not self.closed and randomizeFirstBlock and self.version <= (3,1) \ 540 and self._writeState.encContext \ 541 and self._writeState.encContext.isBlockCipher \ 542 and isinstance(msg, ApplicationData): 543 msgFirstByte = msg.splitFirstByte() 544 for result in self._sendMsg(msgFirstByte, 545 randomizeFirstBlock = False): 546 yield result 547 548 b = msg.write() 549 550 # If a 1-byte message was passed in, and we "split" the 551 # first(only) byte off above, we may have a 0-length msg: 552 if len(b) == 0: 553 return 554 555 contentType = msg.contentType 556 557 #Update handshake hashes 558 if contentType == ContentType.handshake: 559 self._handshake_md5.update(compat26Str(b)) 560 self._handshake_sha.update(compat26Str(b)) 561 self._handshake_sha256.update(compat26Str(b)) 562 563 #Calculate MAC 564 if self._writeState.macContext: 565 seqnumBytes = self._writeState.getSeqNumBytes() 566 mac = self._writeState.macContext.copy() 567 mac.update(compatHMAC(seqnumBytes)) 568 mac.update(compatHMAC(bytearray([contentType]))) 569 if self.version == (3,0): 570 mac.update( compatHMAC( bytearray([len(b)//256] ))) 571 mac.update( compatHMAC( bytearray([len(b)%256] ))) 572 elif self.version in ((3,1), (3,2), (3,3)): 573 mac.update(compatHMAC( bytearray([self.version[0]] ))) 574 mac.update(compatHMAC( bytearray([self.version[1]] ))) 575 mac.update( compatHMAC( bytearray([len(b)//256] ))) 576 mac.update( compatHMAC( bytearray([len(b)%256] ))) 577 else: 578 raise AssertionError() 579 mac.update(compatHMAC(b)) 580 macBytes = bytearray(mac.digest()) 581 if self.fault == Fault.badMAC: 582 macBytes[0] = (macBytes[0]+1) % 256 583 584 #Encrypt for Block or Stream Cipher 585 if self._writeState.encContext: 586 #Add padding and encrypt (for Block Cipher): 587 if self._writeState.encContext.isBlockCipher: 588 589 #Add TLS 1.1 fixed block 590 if self.version >= (3,2): 591 b = self.fixedIVBlock + b 592 593 #Add padding: b = b+ (macBytes + paddingBytes) 594 currentLength = len(b) + len(macBytes) + 1 595 blockLength = self._writeState.encContext.block_size 596 paddingLength = blockLength-(currentLength % blockLength) 597 598 paddingBytes = bytearray([paddingLength] * (paddingLength+1)) 599 if self.fault == Fault.badPadding: 600 paddingBytes[0] = (paddingBytes[0]+1) % 256 601 endBytes = macBytes + paddingBytes 602 b += endBytes 603 #Encrypt 604 b = self._writeState.encContext.encrypt(b) 605 606 #Encrypt (for Stream Cipher) 607 else: 608 b += macBytes 609 b = self._writeState.encContext.encrypt(b) 610 611 #Add record header and send 612 r = RecordHeader3().create(self.version, contentType, len(b)) 613 s = r.write() + b 614 while 1: 615 try: 616 bytesSent = self.sock.send(s) #Might raise socket.error 617 except socket.error as why: 618 if why.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN): 619 yield 1 620 continue 621 else: 622 # The socket was unexpectedly closed. The tricky part 623 # is that there may be an alert sent by the other party 624 # sitting in the read buffer. So, if we get here after 625 # handshaking, we will just raise the error and let the 626 # caller read more data if it would like, thus stumbling 627 # upon the error. 628 # 629 # However, if we get here DURING handshaking, we take 630 # it upon ourselves to see if the next message is an 631 # Alert. 632 if contentType == ContentType.handshake: 633 634 # See if there's an alert record 635 # Could raise socket.error or TLSAbruptCloseError 636 for result in self._getNextRecord(): 637 if result in (0,1): 638 yield result 639 640 # Closes the socket 641 self._shutdown(False) 642 643 # If we got an alert, raise it 644 recordHeader, p = result 645 if recordHeader.type == ContentType.alert: 646 alert = Alert().parse(p) 647 raise TLSRemoteAlert(alert) 648 else: 649 # If we got some other message who know what 650 # the remote side is doing, just go ahead and 651 # raise the socket.error 652 raise 653 if bytesSent == len(s): 654 return 655 s = s[bytesSent:] 656 yield 1
657 658
659 - def _getMsg(self, expectedType, secondaryType=None, constructorType=None):
660 try: 661 if not isinstance(expectedType, tuple): 662 expectedType = (expectedType,) 663 664 #Spin in a loop, until we've got a non-empty record of a type we 665 #expect. The loop will be repeated if: 666 # - we receive a renegotiation attempt; we send no_renegotiation, 667 # then try again 668 # - we receive an empty application-data fragment; we try again 669 while 1: 670 for result in self._getNextRecord(): 671 if result in (0,1): 672 yield result 673 recordHeader, p = result 674 675 #If this is an empty application-data fragment, try again 676 if recordHeader.type == ContentType.application_data: 677 if p.index == len(p.bytes): 678 continue 679 680 #If we received an unexpected record type... 681 if recordHeader.type not in expectedType: 682 683 #If we received an alert... 684 if recordHeader.type == ContentType.alert: 685 alert = Alert().parse(p) 686 687 #We either received a fatal error, a warning, or a 688 #close_notify. In any case, we're going to close the 689 #connection. In the latter two cases we respond with 690 #a close_notify, but ignore any socket errors, since 691 #the other side might have already closed the socket. 692 if alert.level == AlertLevel.warning or \ 693 alert.description == AlertDescription.close_notify: 694 695 #If the sendMsg() call fails because the socket has 696 #already been closed, we will be forgiving and not 697 #report the error nor invalidate the "resumability" 698 #of the session. 699 try: 700 alertMsg = Alert() 701 alertMsg.create(AlertDescription.close_notify, 702 AlertLevel.warning) 703 for result in self._sendMsg(alertMsg): 704 yield result 705 except socket.error: 706 pass 707 708 if alert.description == \ 709 AlertDescription.close_notify: 710 self._shutdown(True) 711 elif alert.level == AlertLevel.warning: 712 self._shutdown(False) 713 714 else: #Fatal alert: 715 self._shutdown(False) 716 717 #Raise the alert as an exception 718 raise TLSRemoteAlert(alert) 719 720 #If we received a renegotiation attempt... 721 if recordHeader.type == ContentType.handshake: 722 subType = p.get(1) 723 reneg = False 724 if self._client: 725 if subType == HandshakeType.hello_request: 726 reneg = True 727 else: 728 if subType == HandshakeType.client_hello: 729 reneg = True 730 #Send no_renegotiation, then try again 731 if reneg: 732 alertMsg = Alert() 733 alertMsg.create(AlertDescription.no_renegotiation, 734 AlertLevel.warning) 735 for result in self._sendMsg(alertMsg): 736 yield result 737 continue 738 739 #Otherwise: this is an unexpected record, but neither an 740 #alert nor renegotiation 741 for result in self._sendError(\ 742 AlertDescription.unexpected_message, 743 "received type=%d" % recordHeader.type): 744 yield result 745 746 break 747 748 #Parse based on content_type 749 if recordHeader.type == ContentType.change_cipher_spec: 750 yield ChangeCipherSpec().parse(p) 751 elif recordHeader.type == ContentType.alert: 752 yield Alert().parse(p) 753 elif recordHeader.type == ContentType.application_data: 754 yield ApplicationData().parse(p) 755 elif recordHeader.type == ContentType.handshake: 756 #Convert secondaryType to tuple, if it isn't already 757 if not isinstance(secondaryType, tuple): 758 secondaryType = (secondaryType,) 759 760 #If it's a handshake message, check handshake header 761 if recordHeader.ssl2: 762 subType = p.get(1) 763 if subType != HandshakeType.client_hello: 764 for result in self._sendError(\ 765 AlertDescription.unexpected_message, 766 "Can only handle SSLv2 ClientHello messages"): 767 yield result 768 if HandshakeType.client_hello not in secondaryType: 769 for result in self._sendError(\ 770 AlertDescription.unexpected_message): 771 yield result 772 subType = HandshakeType.client_hello 773 else: 774 subType = p.get(1) 775 if subType not in secondaryType: 776 for result in self._sendError(\ 777 AlertDescription.unexpected_message, 778 "Expecting %s, got %s" % (str(secondaryType), subType)): 779 yield result 780 781 #Update handshake hashes 782 self._handshake_md5.update(compat26Str(p.bytes)) 783 self._handshake_sha.update(compat26Str(p.bytes)) 784 self._handshake_sha256.update(compat26Str(p.bytes)) 785 786 #Parse based on handshake type 787 if subType == HandshakeType.client_hello: 788 yield ClientHello(recordHeader.ssl2).parse(p) 789 elif subType == HandshakeType.server_hello: 790 yield ServerHello().parse(p) 791 elif subType == HandshakeType.certificate: 792 yield Certificate(constructorType).parse(p) 793 elif subType == HandshakeType.certificate_request: 794 yield CertificateRequest(self.version).parse(p) 795 elif subType == HandshakeType.certificate_verify: 796 yield CertificateVerify().parse(p) 797 elif subType == HandshakeType.server_key_exchange: 798 yield ServerKeyExchange(constructorType).parse(p) 799 elif subType == HandshakeType.server_hello_done: 800 yield ServerHelloDone().parse(p) 801 elif subType == HandshakeType.client_key_exchange: 802 yield ClientKeyExchange(constructorType, \ 803 self.version).parse(p) 804 elif subType == HandshakeType.finished: 805 yield Finished(self.version).parse(p) 806 elif subType == HandshakeType.next_protocol: 807 yield NextProtocol().parse(p) 808 else: 809 raise AssertionError() 810 811 #If an exception was raised by a Parser or Message instance: 812 except SyntaxError as e: 813 for result in self._sendError(AlertDescription.decode_error, 814 formatExceptionTrace(e)): 815 yield result
816 817 818 #Returns next record or next handshake message
819 - def _getNextRecord(self):
820 821 #If there's a handshake message waiting, return it 822 if self._handshakeBuffer: 823 recordHeader, b = self._handshakeBuffer[0] 824 self._handshakeBuffer = self._handshakeBuffer[1:] 825 yield (recordHeader, Parser(b)) 826 return 827 828 #Otherwise... 829 #Read the next record header 830 b = bytearray(0) 831 recordHeaderLength = 1 832 ssl2 = False 833 while 1: 834 try: 835 s = self.sock.recv(recordHeaderLength-len(b)) 836 except socket.error as why: 837 if why.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN): 838 yield 0 839 continue 840 else: 841 raise 842 843 #If the connection was abruptly closed, raise an error 844 if len(s)==0: 845 raise TLSAbruptCloseError() 846 847 b += bytearray(s) 848 if len(b)==1: 849 if b[0] in ContentType.all: 850 ssl2 = False 851 recordHeaderLength = 5 852 elif b[0] == 128: 853 ssl2 = True 854 recordHeaderLength = 2 855 else: 856 raise SyntaxError() 857 if len(b) == recordHeaderLength: 858 break 859 860 #Parse the record header 861 if ssl2: 862 r = RecordHeader2().parse(Parser(b)) 863 else: 864 r = RecordHeader3().parse(Parser(b)) 865 866 #Check the record header fields 867 if r.length > 18432: 868 for result in self._sendError(AlertDescription.record_overflow): 869 yield result 870 871 #Read the record contents 872 b = bytearray(0) 873 while 1: 874 try: 875 s = self.sock.recv(r.length - len(b)) 876 except socket.error as why: 877 if why.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN): 878 yield 0 879 continue 880 else: 881 raise 882 883 #If the connection is closed, raise a socket error 884 if len(s)==0: 885 raise TLSAbruptCloseError() 886 887 b += bytearray(s) 888 if len(b) == r.length: 889 break 890 891 #Check the record header fields (2) 892 #We do this after reading the contents from the socket, so that 893 #if there's an error, we at least don't leave extra bytes in the 894 #socket.. 895 # 896 # THIS CHECK HAS NO SECURITY RELEVANCE (?), BUT COULD HURT INTEROP. 897 # SO WE LEAVE IT OUT FOR NOW. 898 # 899 #if self._versionCheck and r.version != self.version: 900 # for result in self._sendError(AlertDescription.protocol_version, 901 # "Version in header field: %s, should be %s" % (str(r.version), 902 # str(self.version))): 903 # yield result 904 905 #Decrypt the record 906 for result in self._decryptRecord(r.type, b): 907 if result in (0,1): yield result 908 else: break 909 b = result 910 p = Parser(b) 911 912 #If it doesn't contain handshake messages, we can just return it 913 if r.type != ContentType.handshake: 914 yield (r, p) 915 #If it's an SSLv2 ClientHello, we can return it as well 916 elif r.ssl2: 917 yield (r, p) 918 else: 919 #Otherwise, we loop through and add the handshake messages to the 920 #handshake buffer 921 while 1: 922 if p.index == len(b): #If we're at the end 923 if not self._handshakeBuffer: 924 for result in self._sendError(\ 925 AlertDescription.decode_error, \ 926 "Received empty handshake record"): 927 yield result 928 break 929 #There needs to be at least 4 bytes to get a header 930 if p.index+4 > len(b): 931 for result in self._sendError(\ 932 AlertDescription.decode_error, 933 "A record has a partial handshake message (1)"): 934 yield result 935 p.get(1) # skip handshake type 936 msgLength = p.get(3) 937 if p.index+msgLength > len(b): 938 for result in self._sendError(\ 939 AlertDescription.decode_error, 940 "A record has a partial handshake message (2)"): 941 yield result 942 943 handshakePair = (r, b[p.index-4 : p.index+msgLength]) 944 self._handshakeBuffer.append(handshakePair) 945 p.index += msgLength 946 947 #We've moved at least one handshake message into the 948 #handshakeBuffer, return the first one 949 recordHeader, b = self._handshakeBuffer[0] 950 self._handshakeBuffer = self._handshakeBuffer[1:] 951 yield (recordHeader, Parser(b))
952 953
954 - def _decryptRecord(self, recordType, b):
955 if self._readState.encContext: 956 957 #Decrypt if it's a block cipher 958 if self._readState.encContext.isBlockCipher: 959 blockLength = self._readState.encContext.block_size 960 if len(b) % blockLength != 0: 961 for result in self._sendError(\ 962 AlertDescription.decryption_failed, 963 "Encrypted data not a multiple of blocksize"): 964 yield result 965 b = self._readState.encContext.decrypt(b) 966 if self.version >= (3,2): #For TLS 1.1, remove explicit IV 967 b = b[self._readState.encContext.block_size : ] 968 969 #Check padding 970 paddingGood = True 971 paddingLength = b[-1] 972 if (paddingLength+1) > len(b): 973 paddingGood=False 974 totalPaddingLength = 0 975 else: 976 if self.version == (3,0): 977 totalPaddingLength = paddingLength+1 978 elif self.version in ((3,1), (3,2), (3,3)): 979 totalPaddingLength = paddingLength+1 980 paddingBytes = b[-totalPaddingLength:-1] 981 for byte in paddingBytes: 982 if byte != paddingLength: 983 paddingGood = False 984 totalPaddingLength = 0 985 else: 986 raise AssertionError() 987 988 #Decrypt if it's a stream cipher 989 else: 990 paddingGood = True 991 b = self._readState.encContext.decrypt(b) 992 totalPaddingLength = 0 993 994 #Check MAC 995 macGood = True 996 macLength = self._readState.macContext.digest_size 997 endLength = macLength + totalPaddingLength 998 if endLength > len(b): 999 macGood = False 1000 else: 1001 #Read MAC 1002 startIndex = len(b) - endLength 1003 endIndex = startIndex + macLength 1004 checkBytes = b[startIndex : endIndex] 1005 1006 #Calculate MAC 1007 seqnumBytes = self._readState.getSeqNumBytes() 1008 b = b[:-endLength] 1009 mac = self._readState.macContext.copy() 1010 mac.update(compatHMAC(seqnumBytes)) 1011 mac.update(compatHMAC(bytearray([recordType]))) 1012 if self.version == (3,0): 1013 mac.update( compatHMAC(bytearray( [len(b)//256] ) )) 1014 mac.update( compatHMAC(bytearray( [len(b)%256] ) )) 1015 elif self.version in ((3,1), (3,2), (3,3)): 1016 mac.update(compatHMAC(bytearray( [self.version[0]] ) )) 1017 mac.update(compatHMAC(bytearray( [self.version[1]] ) )) 1018 mac.update(compatHMAC(bytearray( [len(b)//256] ) )) 1019 mac.update(compatHMAC(bytearray( [len(b)%256] ) )) 1020 else: 1021 raise AssertionError() 1022 mac.update(compatHMAC(b)) 1023 macBytes = bytearray(mac.digest()) 1024 1025 #Compare MACs 1026 if macBytes != checkBytes: 1027 macGood = False 1028 1029 if not (paddingGood and macGood): 1030 for result in self._sendError(AlertDescription.bad_record_mac, 1031 "MAC failure (or padding failure)"): 1032 yield result 1033 1034 yield b
1035
1036 - def _handshakeStart(self, client):
1037 if not self.closed: 1038 raise ValueError("Renegotiation disallowed for security reasons") 1039 self._client = client 1040 self._handshake_md5 = hashlib.md5() 1041 self._handshake_sha = hashlib.sha1() 1042 self._handshake_sha256 = hashlib.sha256() 1043 self._handshakeBuffer = [] 1044 self.allegedSrpUsername = None 1045 self._refCount = 1
1046
1047 - def _handshakeDone(self, resumed):
1048 self.resumed = resumed 1049 self.closed = False
1050
1051 - def _calcPendingStates(self, cipherSuite, masterSecret, 1052 clientRandom, serverRandom, implementations):
1053 if cipherSuite in CipherSuite.aes128Suites: 1054 keyLength = 16 1055 ivLength = 16 1056 createCipherFunc = createAES 1057 elif cipherSuite in CipherSuite.aes256Suites: 1058 keyLength = 32 1059 ivLength = 16 1060 createCipherFunc = createAES 1061 elif cipherSuite in CipherSuite.rc4Suites: 1062 keyLength = 16 1063 ivLength = 0 1064 createCipherFunc = createRC4 1065 elif cipherSuite in CipherSuite.tripleDESSuites: 1066 keyLength = 24 1067 ivLength = 8 1068 createCipherFunc = createTripleDES 1069 else: 1070 raise AssertionError() 1071 1072 if cipherSuite in CipherSuite.shaSuites: 1073 macLength = 20 1074 digestmod = hashlib.sha1 1075 elif cipherSuite in CipherSuite.sha256Suites: 1076 macLength = 32 1077 digestmod = hashlib.sha256 1078 elif cipherSuite in CipherSuite.md5Suites: 1079 macLength = 16 1080 digestmod = hashlib.md5 1081 1082 if self.version == (3,0): 1083 createMACFunc = createMAC_SSL 1084 elif self.version in ((3,1), (3,2), (3,3)): 1085 createMACFunc = createHMAC 1086 1087 outputLength = (macLength*2) + (keyLength*2) + (ivLength*2) 1088 1089 #Calculate Keying Material from Master Secret 1090 if self.version == (3,0): 1091 keyBlock = PRF_SSL(masterSecret, 1092 serverRandom + clientRandom, 1093 outputLength) 1094 elif self.version in ((3,1), (3,2)): 1095 keyBlock = PRF(masterSecret, 1096 b"key expansion", 1097 serverRandom + clientRandom, 1098 outputLength) 1099 elif self.version == (3,3): 1100 keyBlock = PRF_1_2(masterSecret, 1101 b"key expansion", 1102 serverRandom + clientRandom, 1103 outputLength) 1104 else: 1105 raise AssertionError() 1106 1107 #Slice up Keying Material 1108 clientPendingState = _ConnectionState() 1109 serverPendingState = _ConnectionState() 1110 p = Parser(keyBlock) 1111 clientMACBlock = p.getFixBytes(macLength) 1112 serverMACBlock = p.getFixBytes(macLength) 1113 clientKeyBlock = p.getFixBytes(keyLength) 1114 serverKeyBlock = p.getFixBytes(keyLength) 1115 clientIVBlock = p.getFixBytes(ivLength) 1116 serverIVBlock = p.getFixBytes(ivLength) 1117 clientPendingState.macContext = createMACFunc( 1118 compatHMAC(clientMACBlock), digestmod=digestmod) 1119 serverPendingState.macContext = createMACFunc( 1120 compatHMAC(serverMACBlock), digestmod=digestmod) 1121 clientPendingState.encContext = createCipherFunc(clientKeyBlock, 1122 clientIVBlock, 1123 implementations) 1124 serverPendingState.encContext = createCipherFunc(serverKeyBlock, 1125 serverIVBlock, 1126 implementations) 1127 1128 #Assign new connection states to pending states 1129 if self._client: 1130 self._pendingWriteState = clientPendingState 1131 self._pendingReadState = serverPendingState 1132 else: 1133 self._pendingWriteState = serverPendingState 1134 self._pendingReadState = clientPendingState 1135 1136 if self.version >= (3,2) and ivLength: 1137 #Choose fixedIVBlock for TLS 1.1 (this is encrypted with the CBC 1138 #residue to create the IV for each sent block) 1139 self.fixedIVBlock = getRandomBytes(ivLength)
1140
1141 - def _changeWriteState(self):
1142 self._writeState = self._pendingWriteState 1143 self._pendingWriteState = _ConnectionState()
1144
1145 - def _changeReadState(self):
1146 self._readState = self._pendingReadState 1147 self._pendingReadState = _ConnectionState()
1148 1149 #Used for Finished messages and CertificateVerify messages in SSL v3
1150 - def _calcSSLHandshakeHash(self, masterSecret, label):
1151 imac_md5 = self._handshake_md5.copy() 1152 imac_sha = self._handshake_sha.copy() 1153 1154 imac_md5.update(compatHMAC(label + masterSecret + bytearray([0x36]*48))) 1155 imac_sha.update(compatHMAC(label + masterSecret + bytearray([0x36]*40))) 1156 1157 md5Bytes = MD5(masterSecret + bytearray([0x5c]*48) + \ 1158 bytearray(imac_md5.digest())) 1159 shaBytes = SHA1(masterSecret + bytearray([0x5c]*40) + \ 1160 bytearray(imac_sha.digest())) 1161 1162 return md5Bytes + shaBytes
1163