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