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