Beispiel #1
0
    def _export_register(self, register_name: str, compute_inverses: bool) -> bytes:
        """Generate binary output for single register."""
        register = BitArray(length=32)
        user_config = self.user_config.get(register_name, dict())
        inverse_present = False
        for field in self._get_bitfields(register_name, exclude_computed=False):
            name = field.attrib["name"]
            offset = parse_int(field.attrib["offset"])
            width = parse_int(field.attrib["width"])
            # chcek whether there's a need to calculate inverse values
            inverse_present |= name == "INVERSE_VALUE"

            # The configuration allows to configure the whole register with single value
            if isinstance(user_config, str):
                temp_value = user_config
            else:
                temp_value = user_config.get(name) or field.attrib["reset_value"]
            value = parse_int(temp_value)
            # due to endianess we fill the bits from the end, therefore there's '-' in position
            # pos = 0 means offset = 0, means end of the BitArray
            register.overwrite(bs=BitArray(f"uint:{width}={value}"), pos=-(offset + width))
        if compute_inverses and inverse_present:
            # NOTE: For now we'll assume the INVERSES are 16b long and inverts bits[15:0]
            # should this change in the future a data model change is necessary
            # NOTE: invert method changes bits in-place, thus we need to call it on separate object
            # calling invert() after slicing doesn't work for BitArray
            b_lower = register[16:]
            b_lower.invert()
            register.overwrite(b_lower, 0)
        # swapping bytes from big endian into little
        register.byteswap()
        return register.bytes
Beispiel #2
0
def attach_crc32(config_string: BitArray) -> BitArray:

    # 1 + x + x2 + x4 + x5 +x7 + x8 + x10 + x11 + x12 + x16 + x22 + x23 + x26 + x32.
    polynomial = BitArray(bin='1110 1101 1011 1000 1000 0011 0010 0000 1')

    # enter corrected length with CRC32 packet
    current_length = config_string.length
    length_with_crc32 = current_length + DB_ADDRESS_BITWIDTH + DB_CHANNEL_BITWIDTH + DB_LENGTH_BITWIDTH + 32
    config_string.overwrite(
        BitArray(uint=length_with_crc32, length=DB_CONFIG_LENGTH_BITWIDTH),
        -DB_CONFIG_LENGTH_BITWIDTH)

    # attach DB_ADDRESS 0, Channel 0 for CRC32 receiver, length 32 of checksum
    config_string.prepend(
        BitArray(uint=0, length=DB_ADDRESS_BITWIDTH + DB_CHANNEL_BITWIDTH))
    config_string.prepend(BitArray(uint=32, length=DB_LENGTH_BITWIDTH))

    # actual CRC32 calculation
    divstring = config_string[:
                              -DB_CONFIG_LENGTH_BITWIDTH]  # without config length (doesn't leave db_config)
    divstring.prepend(BitArray(32))  # prepend empty CRC32
    divstring.append(
        BitArray(1))  # attach a 0 to make indexing from LSB side easier
    for j in range(1, divstring.length - 32):
        if divstring[-(j + 1)] == 1:
            divstring[-(j + 33):-j] ^= polynomial
    remainder = divstring[0:32]

    config_string.prepend(remainder)
    return config_string
Beispiel #3
0
def test_invert():
    ba = BitArray(f"uint:32={0x1111}")
    bl = ba[16:]
    bl.invert()
    assert bl.hex == 'eeee'
    ba.overwrite(bl, 0)
    assert ba.hex == 'eeee1111'
Beispiel #4
0
def test_invert():
    """Test of BitArray - Invert."""
    bit_array = BitArray(f"uint:32={0x1111}")
    bit_low = bit_array[16:]
    bit_low.invert()
    assert bit_low.hex == "eeee"
    bit_array.overwrite(bit_low, 0)
    assert bit_array.hex == "eeee1111"
Beispiel #5
0
class qubitString:

	def __init__(self,m):

		# size of qubit string
		self.size=m

		# floats can only be 32 or 64 bits
		self.canHaveFloat = True if self.size==32 or self.size==64 else False

		# create BitArray to hold value of qubit string
		self.arrayVal=BitArray(length=m)

		# initialization value for qubits
		initVal=1/np.sqrt(2)

		quString=list()
		for i in range(0,self.size):
			quString.append(qubit(initVal,initVal))

		self.quString=quString
		self.decVal=None
		self.binVal=None
		self.floatVal=None

	def collapse(self):
		self.bitString=list()
		for i in range(0,self.size):
			# observe and collapse qubit to a state
			self.quString[i].collapse()

			# save collapsed value to bit array
			if self.quString[i].value == 1:
				self.arrayVal.overwrite('0b1',i)
			else:
				self.arrayVal.overwrite('0b0',i)

		# update decimal value
		self.decVal=self.arrayVal.int
		self.binVal=self.arrayVal.bin
		if self.canHaveFloat : self.floatVal = self.arrayVal.float

	
	def rotation_gate(self,angle):
		for i,j in enumerate(quString):
			quString[i].rotation_gate(angle)


	def updateDec(self,num):
		# update array value
		self.arrayVal.int=num

		# update binary value
		self.binVal=self.arrayVal.bin

		# update qubits values
		for i in range(0,self.size):
			self.quString[i].value=int(self.binVal[i])
Beispiel #6
0
def guess_cbc_byte(
    pre,
    target_block,
    oracle,
    byte_pos,
    rem_plaintext,
    alphabet=[Bits(bytes=int_to_bytes(b)) for b in range(0, 256)],
):
    """
    Guesses the byte at the specified position of the target block in the
    ciphertext if the more significant remaining bytes of the block are given.
    Collects the blocks from a ciphertext or padded plaintext and returns a list of it
    :param pre: Preceding block the target block
    :param target_block: target ciphertext block
    :param oracle: Padding oracle
    :param byte_pos: Position of the byte in the block
    :param rem_plaintext: More significant bytes of the plaintext block
    :param alphabet: Alphabet of bytes to guesss from
    :return: Correct byte of target block at byte_pos
    """
    block_size = len(pre)
    pre = BitArray(bytes=pre)

    assert len(rem_plaintext) / 8 == (block_size - byte_pos) - 1

    # Generate the padding
    padding_byte = int_to_bytes(block_size - byte_pos)
    padding = padding_byte * (block_size - byte_pos)

    padding = BitArray(bytes=b"\x00" * byte_pos + padding)
    assert len(padding) == block_size * 8

    rem_plaintext = BitArray(bytes=(b"\x00" * (byte_pos + 1))) + rem_plaintext
    assert len(rem_plaintext) == block_size * 8

    for guess in alphabet:
        # Generate the guess
        guess_bytes = BitArray(length=block_size * 8)
        guess_bytes.overwrite(guess, byte_pos * 8)

        # TODO: Proof that this is sound or find a sound alternative
        # If we query for the last byte, we change the second to last byte to
        # fix a corner case
        if byte_pos == block_size - 1:
            guess_bytes.overwrite(Bits(bytes=b"\xff"), (byte_pos - 1) * 8)

        if guess_bytes == padding:
            continue

        guess_pre = padding ^ rem_plaintext ^ guess_bytes ^ pre

        # Something doesn't work here
        if oracle(guess_pre.tobytes(), target_block):
            return guess

    # We have hit the condition of guess_bytes == padding_bytes here
    return padding_byte
Beispiel #7
0
    def gen_frame_header(self, craft_id, virtual_channel_id,
                         virtual_channel_count, is_encrypt):
        # 输入类型检查
        # 范围检查, 首先定义了bit流的长度, 用overwrite函数时可保证长度(范围)安全
        h_craft_id = BitArray(8)
        h_virtual_channel_id = BitArray(6)
        h_virtual_channel_count = BitArray(24)
        h_is_encrypt = BitArray(1)

        h_craft_id.overwrite(craft_id, 0)
        h_virtual_channel_id.overwrite(
            BitArray(uint=virtual_channel_id, length=6), 0)
        h_virtual_channel_count.overwrite(
            BitArray(uint=virtual_channel_count, length=24), 0)
        h_is_encrypt.overwrite(is_encrypt, 0)
        header = BitArray()
        header.append('0b00')
        header.append(h_craft_id)
        header.append(h_virtual_channel_id)
        header.append(h_virtual_channel_count)
        header.append('0b00')
        header.append(h_is_encrypt)
        header.append('0b00000')
        if is_encrypt == '0b0':
            self.__is_encrypt = False
        else:
            self.__is_encrypt = True
        self.__frame_header = header.tobytes()
Beispiel #8
0
def edit_cbc_block(pre, position, from_value, to_value):
    """
    Changes the value at the specified position to the given value in the target ciphertext block.
    :param pre: Preceding block the target block
    :param position: Position of the changed value
    :param from_value: Actual value at position
    :param to_value: Target value at position
    :return: Edited preceding block
    """
    block_size = len(pre)
    pre = BitArray(bytes=pre)
    from_value = BitArray(bytes=from_value)
    to_value = BitArray(bytes=to_value)

    delta = BitArray(length=block_size * 8)
    delta.overwrite(from_value ^ to_value, position * 8)

    return (pre ^ delta).tobytes()
Beispiel #9
0
def start_activation(context, account=None):
    if account is None:
        account = context.random.getrandbits(10)
    elif not (0 <= account < (1 << 10)):
        raise ValueError('Invalid account number')
    id = caurus._random_bytes(16, context)
    key = caurus._random_bytes(16, context)

    payload = key + id + b'\0'
    barcode = build_barcode(1, account, payload, context.service_key,
                            context.service_mac, context)

    kres = caurus._derive(key, b'KRES', b'', 16, context)
    c = 2
    b_data = BitArray(bytes=barcode)
    b_data.overwrite(Bits(length=len(b_data) - 44), 44)
    b_data += Bits(uint=c, length=16)
    b = caurus._hmac(kres, b_data.bytes, context)
    code = _shuffle_code(_code(b'', b, 3, c, 7), 7)

    return account, id, key, code, encode_barcode(barcode)
Beispiel #10
0
def build_barcode(type, account, payload, encryption_key, mac_key, context):
    if isinstance(payload, Bits):
        if len(payload) > 476:
            raise Exception('Maximum payload length exceeded')
        payload = payload.tobytes()
    elif len(payload) > 59:  # last byte gets truncated
        raise Exception('Maximum payload length exceeded')
    payload += b'\0' * (60 - len(payload))
    encrypted = caurus._aes_ctr_encrypt(encryption_key, payload, context)

    message = BitArray()
    message += Bits(uint=caurus._VERSION, length=8)
    message += Bits(uint=type, length=4)
    message += Bits(uint=context.service_id, length=6)
    message += Bits(uint=account, length=25)
    message += Bits(bool=True)
    message += Bits(length=64)
    message += Bits(bytes=encrypted, length=604)

    mac = caurus._hmac(mac_key, message.bytes, context)[:8]
    message.overwrite(Bits(bytes=mac), 44)

    return message.bytes
Beispiel #11
0
import sys
#Addend1, addend2 and summary
Addend1 = BitArray(float=-3.75, length=32)
Addend2 = BitArray(float=3.50, length=32)
Sum = BitArray(float=0, length=32)
print(Addend1.bin, Addend2.bin, '(', Addend1.float, '+', Addend2.float, ')')

# check if Addend1 < Addend2 , if yes - change
if abs(Addend1.float) < abs(Addend2.float):
    Addend1, Addend2 = Addend2, Addend1
Addend1_one_m = BitArray('0b1' + str(Addend1[9:].bin))
Addend2_one_m = BitArray('0b1' + str(Addend2[9:].bin))
mantissa_sum = 0

#initial exponent
Sum.overwrite(Addend1[1:9], 1)

#exponent's difference
exp_diff = Addend1[1:9].uint - Addend2[1:9].uint
print('Exponent difference:', exp_diff, '(', Addend1[1:9].uint, '-',
      Addend2[1:9].uint, ')')
if exp_diff != 0:
    #align mantissa
    print('Not aligned mantissa:', Addend2_one_m.bin)
    Addend2_one_m >>= exp_diff
    print('aligned mantissa:    ', Addend2_one_m.bin)
#check if needs addition or subtraction
if Addend1[0:1].bin == Addend2[0:1].bin:
    Sum.overwrite(Addend1[0:1], 0)
    mantissa_sum = BitArray(uint=Addend1_one_m.uint + Addend2_one_m.uint,
                            length=Addend1_one_m.len + 1)
Beispiel #12
0
def main():

    if len(sys.argv) > 2:
        input_file_name = sys.argv[1]
        output_file_name = sys.argv[2]

        print("File Name:", input_file_name)
        input_file_length_in_bytes = os.path.getsize(sys.argv[1])
        print("File Size:", input_file_length_in_bytes, "Bytes\n")

        print("Reading File...")
        # Reading input file
        with open(sys.argv[1], "rb") as f:
            symbols = [None] * 256
            file_data = BitArray(bytes=f.read())

        for b in range(0, file_data.length, 8):
            byte = int(file_data[b:b + 8].uint)

            if symbols[byte] == None:
                symbols[byte] = Node(b)
            symbols[byte].frequency += 1

        # Getting list only with symbols
        symbols_fitered = list(filter(None, symbols.copy()))
        symbols_ordered = sorted(symbols_fitered,
                                 key=lambda x: x.frequency,
                                 reverse=True)

        # Build Huffman tree
        print("Building Huffman Tree...")
        s = symbols_ordered.copy()
        while len(s) > 1:
            root = EmptyNode(None)
            node_left = s[-1]
            node_right = s[-2]
            del s[-2:]
            root.left = node_left
            root.right = node_right
            root.frequency = root.left.frequency + root.right.frequency
            new_symbol = root
            s.append(new_symbol)
            s = sorted(s, key=lambda x: x.frequency, reverse=True)

        # Build codes from Huffman Tree
        code(root)

        # Get info from code
        max_code_length = symbols_ordered[-1].code_length
        max_code_bits = int(math.ceil(math.log(max_code_length + 1, 2)))

        # Adding padding bits to overhead
        overhead = BitArray(uint=max_code_length, length=8)
        overhead.append('0b000')

        # Adding symbols codes to overhead
        for symbol in symbols:
            if (symbol is None):
                overhead.append('0b0')
            else:
                overhead.append('0b1')
                overhead.append(
                    BitArray(uint=symbol.code_length, length=max_code_bits))
                overhead.append(symbol.code)

        # Count padding
        length_total = overhead.length
        for s in symbols_ordered:
            length_total += s.frequency * s.code_length

        # Overwrite padding quantity
        padding = 8 - length_total % 8
        if padding < 8:
            pad = BitArray(uint=padding, length=3)
            overhead.overwrite(pad, 8)

        # Apply padding
        if padding != 0:
            overhead.append(BitArray(uint=0, length=padding))
        overhead_len = overhead.length

        print("Writing File...")
        # Building final compressed data
        final_data = overhead
        for b in range(0, file_data.length, 8):
            byte_int = int(file_data[b:b + 8].uint)
            final_data.append(symbols[byte_int].code)
        final_data_len = final_data.length

        # Write compressed data to output file
        with open(output_file_name, "wb") as w:
            final_data.tofile(w)

        # Statistics from compression
        entropy = 0
        avg_code_len = final_data_len / input_file_length_in_bytes
        symbols_quantity = input_file_length_in_bytes
        for s in symbols_ordered:
            p = s.frequency / symbols_quantity
            entropy += p * math.log(p, 2)  # entropy
        entropy = -1 * entropy

        print("\n--------Statistics--------")
        print("Entropy:              %.3f Bits/symbol" % entropy)
        print("Average Code Length:  %.3f Bits/symbol" % avg_code_len)
        print("Compressed data size:", (final_data_len - overhead_len) / 8,
              "Bytes")
        print("Overhead:            ", overhead_len / 8, "Bytes")

        print("\nFile Name:           ", output_file_name)
        print("Compressed file size:", int(final_data_len / 8), "Bytes")
    else:
        print("Enter input and output file names")
Beispiel #13
0
 def testOverwrite(self):
     s = BitArray('0b01110')
     s.overwrite('0b000', 1)
     self.assertEqual(s, '0b00000')
Beispiel #14
0
 def testOverwrite(self):
     a = BitArray('0x00000000')
     a.overwrite('0xdead', 4)
     self.assertEqual(a, '0x000dead0')
Beispiel #15
0
def img_dct(img, q_table, data, lsb_qty=1):
    assert q_table.shape == (8, 8), "q_table parameter should be a 8x8 matrix"

    # Center values around 0
    img = np.subtract(img.astype(int), 128)

    # We will work on 8x8 blocks of the image
    # Thus, we will pad the image so it is divisible by 8 in both dimensions
    m, n = img.shape[:2]
    n_channels = img.shape[2] if len(img.shape) > 2 else 1

    # Padding image so we can work with a divisible 8x8 image
    h_pad = 8 - (m % 8)
    v_pad = 8 - (n % 8)
    padding = ((0, v_pad),
               (0, h_pad)) if n_channels == 1 else ((0, v_pad), (0, h_pad),
                                                    (0, 0))
    pad_img = np.pad(img, padding, "constant", constant_values=0)

    m, n = pad_img.shape[:2]

    # preparing data to be embed
    data = list(Bits(data).bin)
    data.reverse()

    G = np.zeros(pad_img.shape)

    for ch in range(n_channels):
        cur_channel = pad_img if n_channels == 1 else pad_img[:, :, ch]

        for i in range(0, m, 8):
            for j in range(0, n, 8):
                # apply DCT for every 8x8 block
                b = cur_channel[i:i + 8, j:j + 8]

                b_dct = dctn(b, norm='ortho')

                # Quantize using the quantization table provided, rounding values to integers
                b_qntz = np.round(np.divide(b_dct, q_table)).astype(int)

                # Embeding data
                # `data` is a bitarray
                if len(data) > 0:
                    for s, row in enumerate(b_qntz):
                        if len(data) <= 0: break
                        for t, c in enumerate(row):
                            if len(data) <= 0: break
                            else:
                                if c != 0 and c != 1:
                                    c_bin = BitArray(int=c, length=8)

                                    lsb = []
                                    for _ in range(lsb_qty):
                                        if len(data) == 0: break
                                        lsb.append(data.pop())
                                    lsb = ''.join(lsb)

                                    c_bin.overwrite(f'0b{lsb}', 8 - len(lsb))

                                    b_qntz[s, t] = c_bin.int

                if n_channels == 1:
                    G[i:i + 8, j:j + 8] = b_qntz
                else:
                    G[i:i + 8, j:j + 8, ch] = b_qntz

    return G.astype(int)
Beispiel #16
0
Quotient = BitArray('0b' + '0' * REGSIZE)
Divisor = BitArray('0b' + '0' * (REGSIZE - isor.length) + str(isor.bin))
print('place Dividend in Remainder and do left shift:\n',
      Rem.bin,
      '-',
      Quotient.bin,
      '-',
      Divisor.bin,
      sep="")

for counter in range(REGSIZE):
    #Subtract the Divisor register from the left half of the Remainder register, & place in the left half of the Remainder register
    overflow = BitArray(int=Rem[:REGSIZE].int - Divisor.int,
                        length=REGSIZE + 1)
    del overflow[0:1]
    Rem.overwrite(overflow, 0)
    print(
        'Subtract the Divisor register from the left half of the Remainder register:\n',
        Rem.bin,
        '-',
        Quotient.bin,
        '-',
        Divisor.bin,
        sep="")

    #Condition: test reminder
    if Rem.int < 0:
        print('Remainder is < 0:')

        #Restore original value
        overflow = BitArray(int=Rem[:REGSIZE].int + Divisor.int,
 def testOverwrite(self):
     s = BitArray("0b01110")
     s.overwrite("0b000", 1)
     self.assertEqual(s, "0b00000")
Beispiel #18
0
class Ps2Iso:
    def __init__(self, filename):
        self._set_logger()
        self.log.info(f"Loading {filename}, this may take a while...")
        #self.data = Bits(filename=filename)
        self.data = BitArray(filename=filename)
        self.pvd = PVD(self.data)
        self.block_size = self.pvd.logical_block_size

        if self.pvd.system_identifier != "PLAYSTATION":
            self.log.warning(
                (f"system_identifier: '{self.pvd.system_identifier}', "
                 "should be 'PLAYSTATION'"))
            self.log.warning(f"{filename} may not be a PS2 ISO file")
        if self.block_size != 2048:
            self.log.warning((f"logical_block_size: {self.block_size}, "
                              "should be 2048"))
            self.log.warning(f"{filename} may not be a PS2 ISO file")

        self.path_tables = PathTables(self.data, self.pvd)
        self.tree = self.path_tables.get_path_tree()

    def get_object(self, path):
        paths = path.split("/")
        if paths[0] == "":
            paths.pop(0)
        mark = self.tree
        for p in paths:
            mark = mark.get_child(p)
        return mark

    def get_blocks_allocated(self, path):
        obj = self.get_object(path)
        lba_list = self.get_lba_list()
        obj_idx = next(idx for idx, i in enumerate(lba_list) if i[1] == path)
        lba = lba_list[obj_idx][0]
        next_lba = lba_list[obj_idx + 1][0]
        return next_lba - lba

    def get_lba(self, path):
        return self.get_object(path).lba

    def replace_files(self, replacements, allow_move=False):
        paths = [path for path, _ in replacements]
        bins = [b for _, b in replacements]
        sizes = [len(b) // 8 for b in bins]
        blocks_required = [ceil(len(b) / 8 / self.block_size) for b in bins]
        curr_lba = [self.get_lba(p) for p in paths]
        curr_blocks_allocated = [self.get_blocks_allocated(p) for p in paths]

        items = [{
            "path": p,
            "bin": b,
            "size": s,
            "blocks_required": br,
            "curr_lba": cl,
            "curr_blocks_allocated": cb
        } for p, b, s, br, cl, cb in zip(paths, bins, sizes, blocks_required,
                                         curr_lba, curr_blocks_allocated)]

        overflows = []
        for i in items:
            if i["blocks_required"] > i["curr_blocks_allocated"]:
                overflows.append(i)
        for o in overflows:
            self.log.warning((f"{o['path']} (size: {o['size']} "
                              f"requires {o['blocks_required']} blocks, "
                              f"{o['curr_blocks_allocated']} available"))

        if overflows and not allow_move:
            raise ValueError("allow_move must be true to increase file sizes")

        for i in items:
            lba = i["curr_lba"]
            num_blocks = i["curr_blocks_allocated"]
            self.clear_blocks(lba, num_blocks)
        if not allow_move:
            for i in items:
                i["new_lba"] = i["curr_lba"]
                b = i["bin"]
                offset = i["curr_lba"] * self.block_size * 8
                self.data.overwrite(b, offset)
        else:
            raise NotImplementedError("Moving files is not supported yet")

        for i in items:
            self.update_toc(i["path"], i["new_lba"], i["size"])

    def update_toc(self, path, lba, size):
        self.get_object(path).update_toc(lba, size)

    def write(self, filename):
        with open(filename, "wb") as f:
            self.data.tofile(f)

    def clear_blocks(self, start_block, num_blocks):
        start_addr = start_block * self.block_size * 8
        end_addr = start_addr + num_blocks * self.block_size * 8
        self.data.set(0, range(start_addr, end_addr))

    def get_lba_list(self):
        root = self.tree
        lba_list = self._get_lba_list(root)
        lba_list = list(set(lba_list))
        return sorted(lba_list, key=lambda x: x[0])

    def _get_lba_list(self, item, lba_list=None):
        if lba_list is None:
            lba_list = []
        lba = item.lba
        path = item.path
        lba_list.append((lba, path))
        if isinstance(item, TreeFolder):
            for c in item.children:
                self._get_lba_list(c, lba_list=lba_list)
        return lba_list

    def _get_blocks(self, lba, blocks=None, size=None):
        if blocks and size is None:
            size = blocks * self.block_size
        if size is None:
            raise ValueError("blocks/size must be set")

    def _set_logger(self):
        self.log = logging.getLogger("Ps2Iso")
        handler = logging.StreamHandler()
        formatter = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
        handler.setFormatter(formatter)
        self.log.addHandler(handler)
        self.log.setLevel(logging.INFO)
 def testOverwriteParameters(self):
     s = BitArray('0b0000')
     with self.assertRaises(TypeError):
         s.overwrite('0b111')
Beispiel #20
0
    def get_payload(self):
        payload_bits = BitArray(length=8 * 8)  # 8 Byte Message

        field_index = 0
        for fieldConfig in sorted(self.field_config['Fields'],
                                  key=lambda f: f['Order']):
            logger.debug(fieldConfig)
            length = fieldConfig['BitLength']
            offset = fieldConfig['BitOffset']
            signed = fieldConfig['Signed']
            start = fieldConfig['BitStart']

            if fieldConfig['BitStart'] == 0:
                if length < 8:
                    position = offset + 8 - length
                else:
                    position = offset
            else:
                position = offset - start

            logger.debug("Field {name} starts at: {position}".format(
                name=fieldConfig['Name'], position=position))
            logger.debug("Field {name} length is: {length}".format(
                name=fieldConfig['Name'], length=length))

            try:
                resolution = fieldConfig['Resolution']
            except KeyError:
                resolution = None

            value = self.field_data[field_index]
            logger.debug("Value before conversion is: %s" % value)

            if value is not None:
                if resolution is not None:
                    value = int(float(value) / float(resolution))

                if not signed:
                    logger.debug("Field {name} is unsigned".format(
                        name=fieldConfig['Name']))
                    value = Bits(uint=value, length=length)
                else:
                    logger.debug("Field {name} is signed".format(
                        name=fieldConfig['Name']))
                    value = Bits(int=value, length=length)
            else:
                value = BitArray(length=length)
                value.invert()
                if signed:
                    value[0] = False
                value = Bits(value)

            logger.debug("Field {name} value post conversion: {value}".format(
                name=fieldConfig['Name'], value=value))

            if length % 8 == 0:
                value = Bits(bytes=reversed(value.bytes))
            payload_bits.overwrite(value, position)

            field_index += 1

        pad = 8 * 8 - len(payload_bits)
        if (pad > 0):
            payload_bits.append(Bits(length=pad))
        data = list(payload_bits.bytes)

        logger.debug("Payload data is: %s" % data)
        return data
Beispiel #21
0
 def testOverwrite(self):
     s = BitArray('0b01110')
     s.overwrite('0b000', 1)
     self.assertEqual(s, '0b00000')
Beispiel #22
0
        # TODO support JSON load

        # generate all components' config bits and concatenate
        for config_component in config_data['db_components']:
            # get template data with matching BLOCK_PATH
            for i in block_list:
                if i["BLOCK_PATH"] == config_component["BLOCK_PATH"]:
                    block_component: dict = i
                    break
            configbits.prepend(
                DiveBits.generate_config_bitstring(config_component,
                                                   block_component))

        # insert length into lower end of bitstring
        configbits.overwrite(
            BitArray(uint=configbits.length, length=DB_CONFIG_LENGTH_BITWIDTH),
            -DB_CONFIG_LENGTH_BITWIDTH)

        if excomp_data["db_config_block"]["DB_DAISY_CHAIN_CRC_CHECK"]:
            print("CRC check activated")
            configbits = attach_crc32(configbits)

        # extend bitstring to multiple of 8
        if (configbits.length % 8) != 0:
            missing_bits = 8 - (configbits.length % 8)
            configbits.prepend(BitArray(missing_bits))

        # generate mem output file
        memfile = open(mem_files_path + file + ".mem", "w")
        memfile.write("// \n")
        memfile.write("// " + file + ".mem\n")
class DiveBits_configstring:

    configbits: BitArray
    config_data: dict
    config_file: str
    config_name: str
    components: list
    block_configs: list

    def __init__(self, config_file: str, components: list):

        self.configbits = BitArray(0)
        self.config_file = os.path.basename(config_file)
        self.components = components
        self.config_name = os.path.basename(config_file[:-5])

        # open configuration file based on template
        if config_file[-4:].lower() == "yaml":
            self.config_data = yaml.safe_load(open(config_file))
        if config_file[-4:].lower() == "json":
            self.config_data = json.load(open(config_file))

        self.block_configs = self.config_data['db_components']

    def generate_configstring(self):

        # iterate of blocks
        for comp in self.components:
            self.configbits.prepend(
                comp.generate_config_bitstring(self.block_configs))

        # insert length into lower end of bitstring
        self.configbits.append(
            BitArray(uint=self.configbits.length,
                     length=db_bitwidths["CONFIG_LENGTH"]))

    def add_crc32(self):

        # 1 + x + x2 + x4 + x5 +x7 + x8 + x10 + x11 + x12 + x16 + x22 + x23 + x26 + x32.
        polynomial = BitArray(bin='1110 1101 1011 1000 1000 0011 0010 0000 1')

        # enter corrected length with CRC32 packet
        current_length = self.configbits.length
        len_w_crc32 = current_length + db_bitwidths["ADDRESS"] + db_bitwidths[
            "CHANNEL"] + db_bitwidths["LENGTH"] + 32
        self.configbits.overwrite(
            BitArray(uint=len_w_crc32, length=db_bitwidths["CONFIG_LENGTH"]),
            -db_bitwidths["CONFIG_LENGTH"])

        # attach DB_ADDRESS 0, Channel 0 for CRC32 receiver, length 32 of checksum
        self.configbits.prepend(
            BitArray(uint=0,
                     length=db_bitwidths["ADDRESS"] + db_bitwidths["CHANNEL"]))
        self.configbits.prepend(
            BitArray(uint=32, length=db_bitwidths["LENGTH"]))

        # actual CRC32 calculation
        divstring = self.configbits[:-db_bitwidths[
            "CONFIG_LENGTH"]]  # without config length (doesn't leave db_config)
        divstring.prepend(BitArray(32))  # prepend empty CRC32
        divstring.append(
            BitArray(1))  # attach a 0 to make indexing from LSB side easier
        for j in range(1, divstring.length - 32):
            if divstring[-(j + 1)] == 1:
                divstring[-(j + 33):-j] ^= polynomial
        remainder = divstring[0:32]

        self.configbits.prepend(remainder)

    def write_memfile(self, mem_files_path: str):

        # extend bitstring to multiple of 8
        if (self.configbits.length % 8) != 0:
            missing_bits = 8 - (self.configbits.length % 8)
            self.configbits.prepend(BitArray(missing_bits))

        # generate mem output file
        memfile = open(mem_files_path + self.config_name + ".mem", "w")
        memfile.write("// \n")
        memfile.write("// " + self.config_name + ".mem\n")
        memfile.write("// generated " +
                      datetime.now().strftime("%b %d, %Y - %H:%M:%S") + "\n")
        memfile.write("// from DiveBits configuration data in " +
                      self.config_file + "\n")
        memfile.write("// required to make bitstream " + self.config_name +
                      ".bit\n")
        memfile.write("// \n")
        memfile.write("@0000\n")

        xpos = 0
        while self.configbits.length > 0:
            memfile.write(self.configbits[-8:].hex.upper() + " ")
            del self.configbits[-8:]
            xpos = (xpos + 1) % 16
            if xpos == 0:
                memfile.write("\n")
        memfile.write("\n")
        memfile.close()
        # configbits is empty after this!

    # STATIC METHODS
    @staticmethod
    def calculate_configlength(components: list, crc: bool,
                               bram_tcl_file: str):

        bitcount = db_bitwidths["CONFIG_LENGTH"]
        for comp in components:
            bitcount += comp.num_configbits()

        if crc:
            bitcount += (db_bitwidths["ADDRESS"] + db_bitwidths["CHANNEL"] +
                         db_bitwidths["LENGTH"] + 32)

        bram32cnt = bitcount // 32768  # integer division (floor)
        if (bitcount % 32768) != 0:
            bram32cnt += 1  # ceiling

        print("DiveBits component extraction:")
        print("  Complete number of DB config bits:", bitcount)
        print("  Number of RAMB36 required:", bram32cnt)

        # Generate Tcl command to set required number of BRAMs
        tcl_file = open(bram_tcl_file, 'w')
        tcl_file.write("global REQUIRED_BRAMS\n")
        tcl_file.write("set REQUIRED_BRAMS " + str(bram32cnt) + "\n")
        tcl_file.close()
Beispiel #24
0
class DUKPT:
    """Base DUKPT class with common functions of both client and server"""
    _pin_mask      = BitArray(hex="0x00000000000000FF00000000000000FF")
    _mac_req_mask  = BitArray(hex="0x000000000000FF00000000000000FF00")
    _mac_resp_mask = BitArray(hex="0x00000000FF00000000000000FF000000")
    _mac_data_req  = BitArray(hex="0x0000000000FF00000000000000FF0000")
    _mac_data_resp = BitArray(hex="0x000000FF00000000000000FF00000000")
    _ipek          = None
    _tdes_key      = None
    _cur_key       = None
    _ksn           = None
    BDK_LEN        = 16
    KSN_LEN        = 10

    def __init__(self, bdk=None, ksn=None, ipek=None):
        """Initialization
        Keyword arguments:
        bdk (raw or BitArray)  -- Base Derivation Key (16 bytes)
        ksn (raw or BitArray)  -- Key Serial Number (10 bytes)
        ipek (raw or BitArray) -- Initial Pin Encryption Key (16 bytes)
        """
        if ipek:
            if isinstance(ipek, BitArray):
                self._ipek = ipek
            else:
                self._ipek = BitArray(bytes=ipek)
            if isinstance(ksn, BitArray):
                self._ksn = ksn
            else:
                self._ksn  = BitArray(bytes=ksn)
        else:
            if not bdk:
                raise InvalidDUKPTArguments("Must have either ipek or bdk")
            if len(bdk) != self.BDK_LEN:
                raise InvalidDUKPTArguments("BDK must have a length of %d" % self.BDK_LEN)
            self._bdk = BitArray(bytes=bdk)
        
    def derive_key(self, ipek, ksn):
        """Derive a unique key given the ipek and ksn

        Keyword arguments:
        ipek (BitArray) -- Initial Pin Encryption Key
        ksn (BitArray)  -- Key Serial Number
        """
        c_mask       = BitArray(hex='0xc0c0c0c000000000c0c0c0c000000000')
        ksn_offset   = 2
        ctr_offset   = -3
        right_offset = 8

        # Registers taken from documentation
        curkey = ipek
        ksnr   = BitArray(bytes=ksn.bytes[ksn_offset:])
        r3     = self.copy_counter(ksnr)
        r8     = self.reset_counter(ksnr.bytes)
        sr     = BitArray(hex='0x100000')
       
        while (sr.bytes[0] != '\x00') or (sr.bytes[1] != '\x00') or (sr.bytes[2] != '\x00'):
            tmp = self.copy_counter(sr)
            tmp = tmp & r3
            if (tmp.bytes[0] != '\x00') or (tmp.bytes[1] != '\x00') or (tmp.bytes[2] != '\x00'): 
                # Step 2
                n_ctr = BitArray(bytes=r8.bytes[ctr_offset:]) | sr
                r8    = BitArray(bytes=r8.bytes[:ctr_offset]+n_ctr.bytes)
                
                # Step 3
                r8a   = r8 ^ BitArray(bytes=curkey.bytes[right_offset:])
                
                # Step 4
                cipher = DES.new(curkey.bytes[:DES.key_size], DES.MODE_ECB)
                r8a    = BitArray(bytes=cipher.encrypt(r8a.bytes))
                
                # Step 5
                r8a = BitArray(bytes=curkey.bytes[right_offset:]) ^ r8a

                # Step 6
                curkey = curkey ^ c_mask
                
                # Step 7
                r8b = BitArray(bytes=curkey.bytes[right_offset:]) ^ r8
                
                # Step 8
                cipher = DES.new(curkey.bytes[:DES.key_size], DES.MODE_ECB)
                r8b    = BitArray(bytes=cipher.encrypt(r8b.bytes))
                
                # Step 9
                r8b = BitArray(bytes=curkey.bytes[right_offset:]) ^ r8b

                # Step 10 / 11
                curkey = BitArray(bytes=r8b.bytes+r8a.bytes)

            sr >>= 1
        self._cur_key = curkey
        return curkey

    def reset_counter(self, data):
        """Reset the counter to zero

        Keyword arguments:
        data (raw or BitArray) -- Must be at least 3 bytes
        
        Return:
        BitArray of the data passed in
        """
        if isinstance(data, BitArray):
            data = data.bytes
        if len(data) < 3:
            return None
        mask = BitArray(hex='0xe00000')
        ctr  = BitArray(bytes=data[len(data)-3:])
        return BitArray(bytes=data[:-3] + (mask & ctr).bytes)

    def copy_counter(self, data):
        """Copy only the counter bytes from a given string or BitArray

        Keyword arguments:
        data (raw or BitArray) -- Must be at least 3 bytes

        Return:
        BitArray of only the counter bytes
        """
        mask = BitArray(hex='0x1fffff')
        if len(data.bytes) > 3:
            ctr = BitArray(bytes=data.bytes[-3:])
        else:
            ctr = data

        return mask & ctr

    def increase_counter(self):
        """Increase the counter bytes of the stored ksn by one"""
        ctr = self._ksn.cut(21, start=59).next().int + 1
        self._ksn.overwrite('0b'+BitArray(int=ctr, length=21).bin, 59)