1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch# Author: Trevor Perrin
2a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch# See the LICENSE file for legal information regarding use of this file.
3a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Classes for reading/writing binary data (such as TLS records)."""
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom .compat import *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass Writer(object):
9a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    def __init__(self):
10a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        self.bytes = bytearray(0)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def add(self, x, length):
13a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        self.bytes += bytearray(length)
14a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        newIndex = len(self.bytes) - 1
15a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        for count in range(length):
16a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            self.bytes[newIndex] = x & 0xFF
17a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            x >>= 8
18a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            newIndex -= 1
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def addFixSeq(self, seq, length):
21a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        for e in seq:
22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            self.add(e, length)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def addVarSeq(self, seq, length, lengthLength):
25a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        self.add(len(seq)*length, lengthLength)
26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        for e in seq:
27a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            self.add(e, length)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass Parser(object):
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, bytes):
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.bytes = bytes
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.index = 0
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def get(self, length):
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.index + length > len(self.bytes):
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise SyntaxError()
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        x = 0
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for count in range(length):
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            x <<= 8
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            x |= self.bytes[self.index]
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.index += 1
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return x
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def getFixBytes(self, lengthBytes):
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bytes = self.bytes[self.index : self.index+lengthBytes]
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.index += lengthBytes
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return bytes
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def getVarBytes(self, lengthLength):
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lengthBytes = self.get(lengthLength)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self.getFixBytes(lengthBytes)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def getFixList(self, length, lengthList):
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        l = [0] * lengthList
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for x in range(lengthList):
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            l[x] = self.get(length)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return l
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def getVarList(self, length, lengthLength):
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lengthList = self.get(lengthLength)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if lengthList % length != 0:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise SyntaxError()
63a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        lengthList = lengthList // length
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        l = [0] * lengthList
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for x in range(lengthList):
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            l[x] = self.get(length)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return l
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def startLengthCheck(self, lengthLength):
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.lengthCheck = self.get(lengthLength)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.indexCheck = self.index
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def setLengthCheck(self, length):
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.lengthCheck = length
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.indexCheck = self.index
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def stopLengthCheck(self):
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (self.index - self.indexCheck) != self.lengthCheck:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise SyntaxError()
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def atLengthCheck(self):
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (self.index - self.indexCheck) < self.lengthCheck:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return False
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        elif (self.index - self.indexCheck) == self.lengthCheck:
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return True
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
87a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            raise SyntaxError()
88