import struct
from twisted.python import context
from twisted.python import components
class IEncodable(components.Interface):
def encode(self):
pass
class TLSRecordLayer:
CHANGE_CIPHER_SPEC = 20
ALERT = 21
HANDSHAKE = 22
APPLICATION_DATA = 23
# Two 8 bit unsigned integers indicating the protocol version
version = (3, 1)
maxFragmentSize = 2 ** 14
# The data associated with this record
fragment = None
def __init__(self, record):
self.type = record.type
self.version = record.version
self.fragment = record.fragment
class TLSRecordLayerPacket:
def __init__(self, type, version, fragment):
self.type = type
self.version = version
self.fragment = fragment
def encode(self):
v1, v2 = self.version
hdr = struct.pack('>BBBH', self.type, v1, v2, len(self.fragment))
return hdr + self.fragment
class _PlaintextIterator:
TLSRecordLayerPacketType = TLSRecordLayerPacket
def __init__(self, record):
self.type = record.type
self.version = record.version
self.bytes = record.fragment
self.maxChunkSize = record.maxFragmentSize
def next(self):
if not self.bytes:
raise StopIteration
bytes = self.bytes[:self.maxChunkSize]
self.bytes = self.bytes[self.maxChunkSize:]
return self.TLSRecordLayerPacketType(self.type, self.version, bytes)
class TLSPlaintext(TLSRecordLayer):
"""A packet of information on the TLS Record Layer
"""
IteratorType = _PlaintextIterator
def __iter__(self):
return self.IteratorType(self)
class NullCompressionMethod(TLSRecordLayer):
"""A packet of uncompressed compressed information on the TLS Record Layer
"""
class TLSRecordLayerNullCipherPacket(TLSRecordLayerPacket):
def encode(self):
f = self.fragment
sp = context.get('SecurityParameters')
mac = sp.macAlgorithm(sp.writeSecret, sp.seqNum(), self.type, self.version, f)
hdr = struct.pack('>BBBH', self.type, v1, v2, len(f) + len(mac))
return hdr + f + mac
class _CiphertextIterator:
TLSRecordLayerPacketType = TLSRecordLayerNullCipherPacket
class NullCipherMethod(TLSRecordLayer):
IteratorType = _CiphertextIterator
class GenericCipher:
def __init__(self, secParams, writeSecret, seqNum, contentType, version, fragment):
self.mac = HMAC_hash(secParams.macAlgorithm, writeSecret, seqNum, contentType, version, fragment)
class StandardStreamCipher(GenericCipher):
def __init__(self, secParams, writeSecret, seqNum, contentType, version, fragment):
GenericCipher.__init__(self, secParams, writeSecret, seqNum, contentType, version, fragment)
self.content = fragment
class GenericBlockCipher:
blockSize = None
def __init__(self, secParams, writeSecret, seqNum, contentType, version, fragment, padding=None):
GenericCipher.__init__(self, secParams, writeSecret, seqNum, contentType, version, fragment)
toEncode = self.mac + fragment
if padding is None:
padding = self.blockSize - (len(toEncode) % self.blockSize)
if padding == self.blockSize:
padding = 0
self.content = cipher(toEncode + (chr(padding) * (padding + 1)))
class SecurityParameters:
"""Describes the security parameters for a TLS Connection read or write state
@ivar connectionEnd: Either SERVER_END or CLIENT_END - indicates which end of the
TLS connection this side is considered.
"""
SERVER_END = "server"
CLIENT_END = "client"
connectionEnd = None
bulkEncryptionAlgorithm = NullCipherMethod
macAlgorithm = HMAC_NULL
compressionAlgorithm = NullCompressionMethod
# 48 bytes of cryptographically secure goodness
masterSecret = None
# 32 byte value provided by the client
clientRandom = None
# 32 byte value provided by the server
serverRandom = None
# Groan
exportable = None
compressionState = None
cipherState = None
macSecret = None
sequenceNumber = -1
def seqNum(self):
self.sequenceNumber += 1
return self.sequenceNumber
class TLSHandshake(TLSRecordLayer):
sessionIdentifier = None
peerCertificate = None
compressionMethod = None
cipherSpec = None
masterSecret = None
isResumable = None
class CipherChange(TLSRecordLayer):
CHANGE_CIPHER_SPEC = 1
class Alert(TLSRecordLayer):
WARNING = 1
FATAL = 2
alertLevel = None
CLOSE_NOTIFY = 0
UNEXPECTED_MESSAGE = 10
BAD_RECORD_MAC = 20
DECRYPTION_FAILED = 21
RECORD_OVERFLOW = 22
DECOMPRESSION_FAILURE = 30
HANDSHAKE_FAILURE = 40
BAD_CERTIFICATE = 42
UNSUPPORTED_CERTIFICATE = 32
CERTIFICATE_REVOKED = 44
CERTIFICATE_EXPIRED = 45
CERTIFICATE_UNKNOWN = 46
ILLEGAL_PARAMETER = 47
UNKNOWN_CA = 48
ACCESS_DENIED = 49
DECODE_ERROR = 50
DECRYPT_ERROR = 51
EXPORT_RESTRICTION = 60
PROTOCOL_VERSION = 70
INSUFFICIENT_SECURITY = 71
INTERNAL_ERROR = 80
USER_CANCELED = 90 # SIC
NO_RENEGOTIATION = 100
alertDescription = None
syntax highlighted by Code2HTML, v. 0.9.1