168 lines
6.0 KiB
Python
168 lines
6.0 KiB
Python
# Copyright (c) Kuba Szczodrzyński 2022-06-10.
|
|
|
|
from typing import List, Tuple
|
|
|
|
from tools.util.bitint import BitInt, bitcatraw
|
|
|
|
|
|
def pn15(addr: int) -> int:
|
|
# wire [15:0] pn_tmp = {addr[6:0], addr[15:7]} ^ {16'h6371 & {4{addr[8:5]}}};
|
|
a = ((addr % 0x80) * 0x200) + ((addr // 0x80) % 0x200)
|
|
b = (addr // 0x20) % 0x10
|
|
c = 0x6371 & (b * 0x1111)
|
|
return a ^ c
|
|
|
|
|
|
def pn16(addr: int) -> int:
|
|
# wire [16:0] pn_tmp = {addr[9:0], addr[16:10]} ^ {17'h13659 & {addr[4],{4{addr[1],addr[5],addr[9],addr[13]}}}};
|
|
a = ((addr % 0x400) * 0x80) + ((addr // 0x400) % 0x80)
|
|
b = (addr // 0x2000) % 2
|
|
b += ((addr // 0x200) % 2) * 2
|
|
b += ((addr // 0x20) % 2) * 4
|
|
b += ((addr // 0x2) % 2) * 8
|
|
c = (addr // 0x10) % 2
|
|
d = 0x13659 & (c * 0x10000 + b * 0x1111)
|
|
return a ^ d
|
|
|
|
|
|
def pn32(addr: int) -> int:
|
|
# wire [31:0] pn_tmp = {addr[14:0], addr[31:15]} ^ {32'hE519A4F1 & {8{addr[5:2]}}};
|
|
a = ((addr % 0x8000) * 0x20000) + ((addr // 0x8000) % 0x20000)
|
|
b = (addr // 0x4) % 0x10
|
|
c = 0xE519A4F1 & (b * 0x11111111)
|
|
return a ^ c
|
|
|
|
|
|
class BekenCrypto:
|
|
# translated from https://github.com/ghsecuritylab/tysdk_for_bk7231/blob/master/toolchain/encrypt_crc/abc.c
|
|
coef0: BitInt
|
|
coef1_mix: int
|
|
coef1_hi16: int
|
|
bypass: bool = False
|
|
pn15_args: List[slice] = None
|
|
pn16_args: slice = None
|
|
pn32_args: Tuple[int, int] = None
|
|
random: int = 0
|
|
|
|
def __init__(self, coeffs: List[BitInt]) -> None:
|
|
(self.coef0, coef1, coef2, coef3) = coeffs
|
|
|
|
# wire g_bypass = (coef3[31:24] == 8'hFF) | (coef3[31:24] == 8'h00);
|
|
self.bypass = coef3[31:24] in [0x00, 0xFF]
|
|
if self.bypass:
|
|
return
|
|
|
|
# wire pn16_bit = coef3[4];
|
|
# wire[16:0] pn16_addr = pn16_A ^ {coef1[15:8], pn16_bit, coef1[7:0]};
|
|
self.coef1_mix = bitcatraw((coef1[15:8], 8), (coef3[4], 1), (coef1[7:0], 8))
|
|
self.coef1_hi16 = coef1[31:16]
|
|
|
|
# wire pn15_bps = g_bypass | coef3[0];
|
|
pn15_bps = coef3[0]
|
|
# wire pn16_bps = g_bypass | coef3[1];
|
|
pn16_bps = coef3[1]
|
|
# wire pn32_bps = g_bypass | coef3[2];
|
|
pn32_bps = coef3[2]
|
|
# wire rand_bps = g_bypass | coef3[3];
|
|
rand_bps = coef3[3]
|
|
|
|
if coef3[3:0] == 0xF:
|
|
self.bypass = True
|
|
return
|
|
|
|
if not pn15_bps:
|
|
# wire[1:0] pn15_sel = coef3[ 6: 5];
|
|
pn15_sel = coef3[6:5]
|
|
# wire[15:0] pn15_A = (pn15_sel == 0) ? ({addr[31:24], addr[23:16]} ^ {addr[15:8], addr[ 7:0]}) :
|
|
# (pn15_sel == 1) ? ({addr[31:24], addr[23:16]} ^ {addr[ 7:0], addr[15:8]}) :
|
|
# (pn15_sel == 2) ? ({addr[23:16], addr[31:24]} ^ {addr[15:8], addr[ 7:0]}) :
|
|
# ({addr[23:16], addr[31:24]} ^ {addr[ 7:0], addr[15:8]});
|
|
if pn15_sel == 0:
|
|
self.pn15_args = [
|
|
slice(31, 24),
|
|
slice(23, 16),
|
|
slice(15, 8),
|
|
slice(7, 0),
|
|
]
|
|
elif pn15_sel == 1:
|
|
self.pn15_args = [
|
|
slice(31, 24),
|
|
slice(23, 16),
|
|
slice(7, 0),
|
|
slice(15, 8),
|
|
]
|
|
elif pn15_sel == 2:
|
|
self.pn15_args = [
|
|
slice(23, 16),
|
|
slice(31, 24),
|
|
slice(15, 8),
|
|
slice(7, 0),
|
|
]
|
|
else:
|
|
self.pn15_args = [
|
|
slice(23, 16),
|
|
slice(31, 24),
|
|
slice(7, 0),
|
|
slice(15, 8),
|
|
]
|
|
|
|
if not pn16_bps:
|
|
# wire[1:0] pn16_sel = coef3[ 9: 8];
|
|
pn16_sel = coef3[9:8]
|
|
# wire[16:0] pn16_A = (pn16_sel == 0) ? addr[16:0] :
|
|
# (pn16_sel == 1) ? addr[17:1] :
|
|
# (pn16_sel == 2) ? addr[18:2] :
|
|
# addr[19:3];
|
|
self.pn16_args = slice(16 + pn16_sel, pn16_sel)
|
|
|
|
if not pn32_bps:
|
|
# wire[1:0] pn32_sel = coef3[12:11];
|
|
pn32_sel = coef3[12:11]
|
|
# wire[31:0] pn32_A = (pn32_sel == 0) ? addr[31:0] :
|
|
# (pn32_sel == 1) ? {addr[ 7:0], addr[31: 8]} :
|
|
# (pn32_sel == 2) ? {addr[15:0], addr[31:16]} :
|
|
# {addr[23:0], addr[31:24]};
|
|
PN32_SHIFTS = (
|
|
(0, 0),
|
|
(2**8, 2**24),
|
|
(2**16, 2**16),
|
|
(2**24, 2**8),
|
|
)
|
|
self.pn32_args = PN32_SHIFTS[pn32_sel]
|
|
|
|
# wire[31:0] random = rand_bps ? 32'h00000000 : coef2[31:0];
|
|
self.random = 0 if rand_bps else coef2
|
|
|
|
def encrypt_u32(self, addr: int, data: int) -> int:
|
|
if self.bypass:
|
|
return data
|
|
addr = BitInt(addr)
|
|
|
|
pn15_v = 0
|
|
pn16_v = 0
|
|
pn32_v = 0
|
|
|
|
if self.pn15_args:
|
|
pn15_a = (addr[self.pn15_args[0]] * 0x100) + addr[self.pn15_args[1]]
|
|
pn15_b = (addr[self.pn15_args[2]] * 0x100) + addr[self.pn15_args[3]]
|
|
pn15_A = pn15_a ^ pn15_b
|
|
# wire[15:0] pn15_addr = pn15_A ^ coef1[31:16];
|
|
pn15_addr = pn15_A ^ self.coef1_hi16
|
|
pn15_v = pn15(pn15_addr)
|
|
|
|
if self.pn16_args:
|
|
pn16_A = addr[self.pn16_args]
|
|
# wire[16:0] pn16_addr = pn16_A ^ {coef1[15:8], pn16_bit, coef1[7:0]};
|
|
pn16_addr = pn16_A ^ self.coef1_mix
|
|
pn16_v = pn16(pn16_addr)
|
|
|
|
if self.pn32_args:
|
|
pn32_A = (addr // self.pn32_args[0]) + (addr * self.pn32_args[1])
|
|
# wire[31:0] pn32_addr = pn32_A ^ coef0[31:0];
|
|
pn32_addr = pn32_A ^ self.coef0
|
|
pn32_v = pn32(pn32_addr)
|
|
|
|
# assign pnout = pn32[31:0] ^ {pn15[15:0], pn16[15:0]} ^ random[31:0];
|
|
pnout = pn32_v ^ ((pn15_v * 0x10000) + (pn16_v % 0x10000)) ^ self.random
|
|
return data ^ pnout
|