mirror of
https://github.com/bkerler/mtkclient.git
synced 2024-11-14 03:04:54 -05:00
Restructure src folder, improve v5 payload, fix preloader crash bug, add vbmeta patcher
This commit is contained in:
parent
34f1341da9
commit
5a3b9399a9
211 changed files with 2752 additions and 3270 deletions
|
@ -237,9 +237,10 @@ mv [displayed magisk patched boot filename here] boot.patched
|
|||
|
||||
7. Do the steps needed in section "Unlock bootloader below"
|
||||
|
||||
8. Flash magisk-patched boot and empty vbmeta
|
||||
8. Flash magisk-patched boot and disable verity + verification on vbmeta
|
||||
```
|
||||
python mtk.py w boot,vbmeta boot.patched,vbmeta.img.empty
|
||||
python mtk.py da vbmeta 3
|
||||
python mtk.py w boot boot.patched
|
||||
```
|
||||
|
||||
9. Reboot the phone
|
||||
|
|
16
mtk.py
16
mtk.py
|
@ -37,7 +37,7 @@ cmds = {
|
|||
"stage": "Run stage2 payload via boot rom mode (kamakiri)",
|
||||
"plstage": "Run stage2 payload via preloader mode (send_da)",
|
||||
"da": "Run da xflash/legacy special commands",
|
||||
"script": "Run multiple commands using text script"
|
||||
"script": "Run multiple commands using text script",
|
||||
}
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -99,28 +99,38 @@ if __name__ == '__main__':
|
|||
da_meta.add_argument('--preloader', help='Set the preloader filename for dram config')
|
||||
da_meta.add_argument("metamode", type=str, help="metamode to use [off,usb,uart]")
|
||||
|
||||
da_vbmeta = da_cmds.add_parser("vbmeta", help="Patch vbmeta partition")
|
||||
da_vbmeta.add_argument('--preloader', help='Set the preloader filename for dram config')
|
||||
da_vbmeta.add_argument("vbmode", type=str, help="vbmeta mode (0=locked, 1=disable_verity, 2=disable_verification, 3=disable verity+verification)")
|
||||
|
||||
da_rpmb = da_cmds.add_parser("rpmb", help="RPMB Tools")
|
||||
|
||||
da_rpmb_cmds = da_rpmb.add_subparsers(dest='rpmb_subcmd', help='Commands: r w')
|
||||
da_rpmb_r = da_rpmb_cmds.add_parser("r", help="Read rpmb")
|
||||
da_rpmb_r.add_argument('--filename', type=str, help="Filename to write data into")
|
||||
da_rpmb_r.add_argument('filename', type=str, help="Filename to write data into", default="rpmb.bin", nargs="?")
|
||||
da_rpmb_r.add_argument('--preloader', help='Set the preloader filename for dram config')
|
||||
da_rpmb_r.add_argument('--loader', type=str, help='Use specific loader, disable autodetection')
|
||||
da_rpmb_r.add_argument('--auth', type=str, help="Use auth file (auth_sv5.auth)")
|
||||
da_rpmb_r.add_argument('--cert', type=str, help="Use cert file")
|
||||
da_rpmb_r.add_argument('--sector', help='Start sector (offset/0x100 bytes)')
|
||||
da_rpmb_r.add_argument('--sectors', help='Sector count')
|
||||
|
||||
da_rpmb_w = da_rpmb_cmds.add_parser("w", help="Write rpmb")
|
||||
da_rpmb_w.add_argument('filename', type=str, help="Filename to write from")
|
||||
da_rpmb_w.add_argument('filename', type=str, help="Filename to write from", default="rpmb.bin", nargs="?")
|
||||
da_rpmb_w.add_argument('--preloader', help='Set the preloader filename for dram config')
|
||||
da_rpmb_w.add_argument('--auth', type=str, help="Use auth file (auth_sv5.auth)")
|
||||
da_rpmb_w.add_argument('--cert', type=str, help="Use cert file")
|
||||
da_rpmb_w.add_argument('--loader', type=str, help='Use specific loader, disable autodetection')
|
||||
da_rpmb_w.add_argument('--sector', help='Start sector (offset/0x100 bytes)')
|
||||
da_rpmb_w.add_argument('--sectors', help='Sector count')
|
||||
|
||||
da_rpmb_e = da_rpmb_cmds.add_parser("e", help="Erase rpmb")
|
||||
da_rpmb_e.add_argument('--preloader', help='Set the preloader filename for dram config')
|
||||
da_rpmb_e.add_argument('--auth', type=str, help="Use auth file (auth_sv5.auth)")
|
||||
da_rpmb_e.add_argument('--cert', type=str, help="Use cert file")
|
||||
da_rpmb_e.add_argument('--loader', type=str, help='Use specific loader, disable autodetection')
|
||||
da_rpmb_e.add_argument('--sector', help='Start sector (offset/0x100 bytes)')
|
||||
da_rpmb_e.add_argument('--sectors', help='Sector count')
|
||||
|
||||
da_peek = da_cmds.add_parser("peek", help="Read memory")
|
||||
da_peek.add_argument('--preloader', help='Set the preloader filename for dram config')
|
||||
|
|
|
@ -946,7 +946,7 @@ class DALegacy(metaclass=LogBase):
|
|||
return True
|
||||
return True
|
||||
|
||||
def writeflash(self, addr, length, filename, offset=0, parttype=None, wdata=None, display=True):
|
||||
def writeflash(self, addr, length, filename: str = "", offset=0, parttype=None, wdata=None, display=True):
|
||||
self.mtk.daloader.progress.clear()
|
||||
return self.sdmmc_write_data(addr=addr, length=length, filename=filename, offset=offset, parttype=parttype,
|
||||
wdata=wdata, display=display)
|
||||
|
|
|
@ -164,6 +164,48 @@ class DaHandler(metaclass=LogBase):
|
|||
mtk.daloader.writestate()
|
||||
return mtk
|
||||
|
||||
def patch_vbmeta(self, vbmeta:bytes, vbmode:int):
|
||||
vbmeta = bytearray(vbmeta)
|
||||
DISABLE_VERITY = 1
|
||||
DISABLE_VERIFICATION = 2
|
||||
if vbmode == DISABLE_VERIFICATION:
|
||||
self.info("Patching verification")
|
||||
elif vbmode == DISABLE_VERITY:
|
||||
self.info("Patching verity")
|
||||
elif vbmode == DISABLE_VERIFICATION|DISABLE_VERITY:
|
||||
self.info("Patching verification + verity")
|
||||
elif vbmode == 0:
|
||||
self.info("Enable verification + verity")
|
||||
else:
|
||||
self.error(f"Invalid mode: {vbmode}")
|
||||
return None
|
||||
vbmeta[0x78:0x78+4] = int.to_bytes(vbmode, 4, 'big')
|
||||
return vbmeta
|
||||
|
||||
def da_vbmeta(self, vbmode:int=3):
|
||||
gpttable = self.mtk.daloader.get_partition_data(parttype="user")
|
||||
for partition in ["vbmeta","vbmeta_a"]:
|
||||
rpartition = None
|
||||
for gptentry in gpttable:
|
||||
if gptentry.name.lower() == partition.lower():
|
||||
rpartition = gptentry
|
||||
break
|
||||
if rpartition is not None:
|
||||
self.info(f'Dumping partition "{rpartition.name}"')
|
||||
vbmeta=self.mtk.daloader.readflash(addr=rpartition.sector * self.config.pagesize,
|
||||
length=rpartition.sectors * self.config.pagesize,
|
||||
filename="", parttype="user")
|
||||
if vbmeta!=b"":
|
||||
self.info(f'Patching vbmeta"')
|
||||
patched_vbmeta = self.patch_vbmeta(vbmeta,vbmode)
|
||||
self.info(f'Writing partition "{rpartition.name}"')
|
||||
if self.mtk.daloader.writeflash(addr=rpartition.sector * self.config.pagesize,
|
||||
length=rpartition.sectors * self.config.pagesize,
|
||||
wdata=patched_vbmeta, parttype="user"):
|
||||
self.info("Successfully patched vbmeta :)")
|
||||
else:
|
||||
self.error("Error on patching vbmeta :(")
|
||||
|
||||
def da_gpt(self, directory: str):
|
||||
if directory is None:
|
||||
directory = ""
|
||||
|
@ -647,6 +689,7 @@ class DaHandler(metaclass=LogBase):
|
|||
if self.mtk.daloader.poke(addr=addr, data=data):
|
||||
self.info(f"Successfully wrote data to {hex(addr)}, length {hex(len(data))}")
|
||||
|
||||
|
||||
def handle_da_cmds(self, mtk, cmd: str, args):
|
||||
if mtk is None or mtk.daloader is None:
|
||||
self.error("Error on running da, aborting :(")
|
||||
|
@ -780,7 +823,7 @@ class DaHandler(metaclass=LogBase):
|
|||
elif cmd == "da":
|
||||
subcmd = args.subcmd
|
||||
if subcmd is None:
|
||||
print("Available da cmds are: [peek, poke, generatekeys, seccfg, rpmb, meta, memdump, efuse, dumpbrom]")
|
||||
print("Available da cmds are: [peek, poke, generatekeys, seccfg, rpmb, meta, memdump, efuse, dumpbrom, vbmeta]")
|
||||
return
|
||||
if subcmd == "peek":
|
||||
addr = getint(args.address)
|
||||
|
@ -841,14 +884,17 @@ class DaHandler(metaclass=LogBase):
|
|||
if rpmb_subcmd is None:
|
||||
print('Available da xflash rpmb cmds are: [r w]')
|
||||
if rpmb_subcmd == "r":
|
||||
mtk.daloader.read_rpmb(args.filename)
|
||||
mtk.daloader.read_rpmb(args.filename, args.sector, args.sectors)
|
||||
elif rpmb_subcmd == "w":
|
||||
mtk.daloader.write_rpmb(args.filename)
|
||||
mtk.daloader.write_rpmb(args.filename, args.sector, args.sectors)
|
||||
elif rpmb_subcmd == "e":
|
||||
mtk.daloader.erase_rpmb()
|
||||
mtk.daloader.erase_rpmb(args.sector, args.sectors)
|
||||
elif subcmd == "meta":
|
||||
metamode = args.metamode
|
||||
if metamode is None:
|
||||
print("metamode is needed [usb,uart,off]!")
|
||||
else:
|
||||
mtk.daloader.setmetamode(metamode)
|
||||
elif subcmd == "vbmeta":
|
||||
vbmode = int(args.vbmode)
|
||||
self.da_vbmeta(vbmode=vbmode)
|
||||
|
|
|
@ -301,7 +301,7 @@ class DAloader(metaclass=LogBase):
|
|||
return True
|
||||
return False
|
||||
|
||||
def writeflash(self, addr, length, filename, offset=0, parttype=None, wdata=None, display=True):
|
||||
def writeflash(self, addr, length, filename: str = "", offset=0, parttype=None, wdata=None, display=True):
|
||||
return self.da.writeflash(addr=addr, length=length, filename=filename, offset=offset,
|
||||
parttype=parttype, wdata=wdata, display=display)
|
||||
|
||||
|
@ -395,26 +395,42 @@ class DAloader(metaclass=LogBase):
|
|||
elif self.flashmode == DAmodes.XML:
|
||||
return self.xmlft.seccfg(lockflag)
|
||||
|
||||
def read_rpmb(self, filename=None):
|
||||
def str_to_int(self, arg):
|
||||
if arg is not None:
|
||||
if "0x" in arg:
|
||||
value = int(arg,16)
|
||||
else:
|
||||
value = int(arg, 10)
|
||||
else:
|
||||
value = 0
|
||||
return value
|
||||
|
||||
def read_rpmb(self, filename=None, sector: str = None, sectors: str = None):
|
||||
sector = self.str_to_int(sector)
|
||||
sectors = self.str_to_int(sectors)
|
||||
if self.flashmode == DAmodes.XFLASH:
|
||||
return self.xft.read_rpmb(filename)
|
||||
return self.xft.read_rpmb(filename, sector, sectors)
|
||||
elif self.flashmode == DAmodes.XML:
|
||||
return self.xmlft.read_rpmb(filename)
|
||||
return self.xmlft.read_rpmb(filename, sector, sectors)
|
||||
self.error("Device is not in xflash/xml mode, cannot run read rpmb cmd.")
|
||||
return False
|
||||
|
||||
def write_rpmb(self, filename=None):
|
||||
def write_rpmb(self, filename=None, sector: int = 0, sectors: int = None):
|
||||
sector = self.str_to_int(sector)
|
||||
sectors = self.str_to_int(sectors)
|
||||
if self.flashmode == DAmodes.XFLASH:
|
||||
return self.xft.write_rpmb(filename)
|
||||
return self.xft.write_rpmb(filename, sector, sectors)
|
||||
elif self.flashmode == DAmodes.XML:
|
||||
return self.xmlft.write_rpmb(filename)
|
||||
return self.xmlft.write_rpmb(filename, sector, sectors)
|
||||
self.error("Device is not in xflash/xml mode, cannot run write rpmb cmd.")
|
||||
return False
|
||||
|
||||
def erase_rpmb(self):
|
||||
def erase_rpmb(self, sector: int = 0, sectors: int = None):
|
||||
sector = self.str_to_int(sector)
|
||||
sectors = self.str_to_int(sectors)
|
||||
if self.flashmode == DAmodes.XFLASH:
|
||||
return self.xft.erase_rpmb()
|
||||
return self.xft.erase_rpmb(sector, sectors)
|
||||
if self.flashmode == DAmodes.XML:
|
||||
return self.xmlft.erase_rpmb()
|
||||
return self.xmlft.erase_rpmb(sector, sectors)
|
||||
self.error("Device is not in xflash/xml mode, cannot run erase rpmb cmd.")
|
||||
return False
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import hashlib
|
||||
import hmac
|
||||
import os
|
||||
import sys
|
||||
from struct import unpack, pack
|
||||
|
||||
from mtkclient.config.payloads import PathConfig
|
||||
|
@ -13,17 +16,15 @@ import json
|
|||
|
||||
class XCmd:
|
||||
CUSTOM_ACK = 0x0F0000
|
||||
CUSTOM_READ = 0x0F0001
|
||||
CUSTOM_READMEM = 0x0F0001
|
||||
CUSTOM_READREGISTER = 0x0F0002
|
||||
CUSTOM_WRITE = 0x0F0003
|
||||
CUSTOM_WRITEMEM = 0x0F0003
|
||||
CUSTOM_WRITEREGISTER = 0x0F0004
|
||||
CUSTOM_INIT_RPMB = 0x0F0005
|
||||
CUSTOM_READ_RPMB = 0x0F0006
|
||||
CUSTOM_WRITE_RPMB = 0x0F0007
|
||||
CUSTOM_INIT_UFS_RPMB = 0x0F0008
|
||||
CUSTOM_READ_UFS_RPMB = 0x0F0009
|
||||
CUSTOM_WRITE_UFS_RPMB = 0x0F000A
|
||||
CUSTOM_SET_RPMB_KEY = 0x0F000B
|
||||
CUSTOM_SET_STORAGE = 0x0F0005
|
||||
CUSTOM_RPMB_SET_KEY = 0x0F0006
|
||||
CUSTOM_RPMB_INIT = 0x0F0008
|
||||
CUSTOM_RPMB_READ = 0x0F0009
|
||||
CUSTOM_RPMB_WRITE = 0x0F000A
|
||||
|
||||
|
||||
rpmb_error = [
|
||||
|
@ -171,7 +172,7 @@ class XFlashExt(metaclass=LogBase):
|
|||
daextdata[ufshcd_queuecommand_ptr:ufshcd_queuecommand_ptr + 4] = pack("<I", ufshcd_queuecommand)
|
||||
daextdata[ptr_g_ufs_hba_ptr:ptr_g_ufs_hba_ptr + 4] = pack("<I", g_ufs_hba)
|
||||
if efuse_addr_ptr!=-1:
|
||||
daextdata[efuse_addr_ptr:efuse_addr_ptr+4]=pack("<I", efuse_addr)
|
||||
daextdata[efuse_addr_ptr:efuse_addr_ptr + 4] = pack("<I", efuse_addr)
|
||||
|
||||
# print(hexlify(daextdata).decode('utf-8'))
|
||||
# open("daext.bin","wb").write(daextdata)
|
||||
|
@ -321,7 +322,7 @@ class XFlashExt(metaclass=LogBase):
|
|||
data = bytearray()
|
||||
pos = 0
|
||||
while pos < length:
|
||||
if self.cmd(XCmd.CUSTOM_READ):
|
||||
if self.cmd(XCmd.CUSTOM_READMEM):
|
||||
self.xsend(data=addr + pos, is64bit=True)
|
||||
sz = min(length, 0x10000)
|
||||
self.xsend(sz)
|
||||
|
@ -333,6 +334,18 @@ class XFlashExt(metaclass=LogBase):
|
|||
break
|
||||
return data[:length]
|
||||
|
||||
def custom_set_storage(self, ufs: bool = False):
|
||||
if self.cmd(XCmd.CUSTOM_SET_STORAGE):
|
||||
if ufs:
|
||||
self.xsend(int.to_bytes(1, 4, 'little'))
|
||||
else:
|
||||
# EMMC
|
||||
self.xsend(int.to_bytes(0, 4, 'little'))
|
||||
status = self.status()
|
||||
if status == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def custom_readregister(self, addr):
|
||||
if self.cmd(XCmd.CUSTOM_READREGISTER):
|
||||
self.xsend(addr)
|
||||
|
@ -343,7 +356,7 @@ class XFlashExt(metaclass=LogBase):
|
|||
return b""
|
||||
|
||||
def custom_write(self, addr, data):
|
||||
if self.cmd(XCmd.CUSTOM_WRITE):
|
||||
if self.cmd(XCmd.CUSTOM_WRITEMEM):
|
||||
self.xsend(data=addr, is64bit=True)
|
||||
self.xsend(len(data))
|
||||
self.xsend(data)
|
||||
|
@ -403,41 +416,51 @@ class XFlashExt(metaclass=LogBase):
|
|||
self.writeregister(addr + i, unpack("<I", value))
|
||||
return True
|
||||
|
||||
def custom_rpmb_read(self, sector, ufs=False):
|
||||
cmd = XCmd.CUSTOM_READ_RPMB
|
||||
if ufs:
|
||||
cmd = XCmd.CUSTOM_READ_UFS_RPMB
|
||||
def custom_rpmb_read(self, sector, sectors):
|
||||
data = bytearray()
|
||||
cmd = XCmd.CUSTOM_RPMB_READ
|
||||
if self.cmd(cmd):
|
||||
self.xsend(sector)
|
||||
resp = unpack("<H", self.xread())[0]
|
||||
if resp == 0x0:
|
||||
data = self.xread()
|
||||
status = self.status()
|
||||
if status == 0:
|
||||
return data
|
||||
else:
|
||||
self.error(rpmb_error[resp])
|
||||
status = self.status()
|
||||
return b''
|
||||
self.xsend(sectors)
|
||||
for i in range(sectors):
|
||||
tmp = self.xread()
|
||||
if len(tmp) != 0x100:
|
||||
resp = int.from_bytes(tmp, 'little')
|
||||
if resp in rpmb_error:
|
||||
msg = rpmb_error[resp]
|
||||
else:
|
||||
msg = f"Error: {hex(resp)}"
|
||||
self.error(f"Error on sector {hex(sector)}: {msg})")
|
||||
return b""
|
||||
else:
|
||||
data.extend(tmp)
|
||||
status = self.status()
|
||||
if status == 0:
|
||||
return data
|
||||
else:
|
||||
return b""
|
||||
|
||||
def custom_rpmb_write(self, sector, data: bytes, ufs=False):
|
||||
if len(data) != 0x100:
|
||||
def custom_rpmb_write(self, sector, sectors, data: bytes):
|
||||
if len(data)%0x100!=0:
|
||||
self.error("Incorrect rpmb frame length. Aborting")
|
||||
return False
|
||||
cmd = XCmd.CUSTOM_WRITE_RPMB
|
||||
if ufs:
|
||||
cmd = XCmd.CUSTOM_WRITE_UFS_RPMB
|
||||
cmd = XCmd.CUSTOM_RPMB_WRITE
|
||||
if self.cmd(cmd):
|
||||
self.xsend(sector)
|
||||
self.xsend(data[:0x100])
|
||||
resp = unpack("<H", self.xread())[0]
|
||||
if resp != 0:
|
||||
self.error(rpmb_error[resp])
|
||||
status = self.status()
|
||||
return False
|
||||
self.xsend(sectors)
|
||||
for i in range(sectors):
|
||||
self.xsend(data[i * 0x100:(i * 0x100) + 0x100])
|
||||
resp = unpack("<H", self.xflash.get_response(raw=True))[0]
|
||||
if resp != 0:
|
||||
if resp in rpmb_error:
|
||||
self.error(rpmb_error[resp])
|
||||
status = self.status()
|
||||
return False
|
||||
status = self.status()
|
||||
if status == 0:
|
||||
return resp
|
||||
return True
|
||||
|
||||
status = self.status()
|
||||
return False
|
||||
|
||||
def custom_rpmb_init(self):
|
||||
|
@ -448,32 +471,27 @@ class XFlashExt(metaclass=LogBase):
|
|||
if meid != b"\x00" * 16:
|
||||
# self.config.set_meid(meid)
|
||||
self.info("Generating sej rpmbkey...")
|
||||
#rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp)
|
||||
rpmbkey = hwc.aes_hwcrypt(btype="dxcc", mode="rpmb")
|
||||
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp)
|
||||
if rpmbkey is not None:
|
||||
if self.cmd(XCmd.CUSTOM_SET_RPMB_KEY):
|
||||
if self.cmd(XCmd.CUSTOM_RPMB_SET_KEY):
|
||||
self.xsend(rpmbkey)
|
||||
read_key = self.xread()
|
||||
if self.status() == 0x0:
|
||||
if rpmbkey == read_key:
|
||||
self.info("Setting rpmbkey: ok")
|
||||
ufs = False
|
||||
if self.xflash.emmc.rpmb_size != 0:
|
||||
ufs = False
|
||||
elif self.xflash.ufs.block_size != 0:
|
||||
ufs = True
|
||||
cmd = XCmd.CUSTOM_INIT_RPMB
|
||||
if ufs:
|
||||
cmd = XCmd.CUSTOM_INIT_UFS_RPMB
|
||||
cmd = XCmd.CUSTOM_RPMB_INIT
|
||||
if self.cmd(cmd):
|
||||
derivedrpmb = self.xread()
|
||||
# rpmb_frame = self.xread()
|
||||
# hash = self.xread()
|
||||
if int.from_bytes(derivedrpmb[:4], 'little') != 0xff:
|
||||
status = self.status()
|
||||
status = self.status()
|
||||
if status == 0:
|
||||
derivedrpmb = self.xread()
|
||||
self.status()
|
||||
if status == 0:
|
||||
self.info("Derived rpmb key:" + derivedrpmb.hex())
|
||||
self.info("Derived rpmb key: " + derivedrpmb.hex())
|
||||
return True
|
||||
else:
|
||||
if status in rpmb_error:
|
||||
print(rpmb_error[status])
|
||||
return False
|
||||
self.error("Failed to derive a valid rpmb key.")
|
||||
return False
|
||||
|
||||
|
@ -487,34 +505,40 @@ class XFlashExt(metaclass=LogBase):
|
|||
otp = 32 * b"\x00"
|
||||
hwc.sej.sej_set_otp(otp)
|
||||
|
||||
def read_rpmb(self, filename=None, display=True):
|
||||
def read_rpmb(self, filename=None, sector: int = None, sectors: int = None, display=True):
|
||||
progressbar = Progress(1, self.mtk.config.guiprogress)
|
||||
sectors = 0
|
||||
# val = self.custom_rpmb_init()
|
||||
ufs = False
|
||||
if self.xflash.emmc.rpmb_size != 0:
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
ufs = False
|
||||
elif self.xflash.ufs.block_size != 0:
|
||||
sectors = (512 * 256)
|
||||
ufs = True
|
||||
if sector is None:
|
||||
sector = 0
|
||||
if sectors==0:
|
||||
if self.mtk.daloader.daconfig.flashtype == "emmc":
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
elif self.mtk.daloader.daconfig.flashtype == "ufs":
|
||||
sectors = (512 * 256)
|
||||
if filename is None:
|
||||
filename = "rpmb.bin"
|
||||
if sectors > 0:
|
||||
with open(filename, "wb") as wf:
|
||||
for sector in range(sectors):
|
||||
pos = 0
|
||||
toread = sectors
|
||||
while toread > 0:
|
||||
if display:
|
||||
progressbar.show_progress("RPMB read", sector * 0x100, sectors * 0x100, display)
|
||||
data = self.custom_rpmb_read(sector=sector, ufs=ufs)
|
||||
progressbar.show_progress("RPMB read", pos * 0x100, sectors * 0x100, display)
|
||||
sz = min(sectors - pos, 0x10)
|
||||
data = self.custom_rpmb_read(sector=sector + pos, sectors=sz)
|
||||
if data == b"":
|
||||
self.error("Couldn't read rpmb.")
|
||||
return False
|
||||
wf.write(data)
|
||||
pos += sz
|
||||
toread -= sz
|
||||
if display:
|
||||
progressbar.show_progress("RPMB read", sectors * 0x100, sectors * 0x100, display)
|
||||
self.info(f"Done reading rpmb to {filename}")
|
||||
return True
|
||||
return False
|
||||
|
||||
def write_rpmb(self, filename=None, display=True):
|
||||
def write_rpmb(self, filename=None, sector: int = None, sectors: int = None, display=True):
|
||||
progressbar = Progress(1, self.mtk.config.guiprogress)
|
||||
if filename is None:
|
||||
self.error("Filename has to be given for writing to rpmb")
|
||||
|
@ -522,41 +546,59 @@ class XFlashExt(metaclass=LogBase):
|
|||
if not os.path.exists(filename):
|
||||
self.error(f"Couldn't find {filename} for writing to rpmb.")
|
||||
return False
|
||||
ufs = False
|
||||
sectors = 0
|
||||
if self.xflash.emmc.rpmb_size != 0:
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
elif self.xflash.ufs.block_size != 0:
|
||||
sectors = (512 * 256)
|
||||
if sectors == 0:
|
||||
max_sector_size = (512 * 256)
|
||||
if self.xflash.emmc is not None:
|
||||
max_sector_size = self.xflash.emmc.rpmb_size // 0x100
|
||||
else:
|
||||
max_sector_size = sectors
|
||||
filesize = os.path.getsize(filename)
|
||||
sectors = min(filesize // 256, max_sector_size)
|
||||
if self.custom_rpmb_init():
|
||||
if sectors > 0:
|
||||
with open(filename, "rb") as rf:
|
||||
for sector in range(sectors):
|
||||
pos = 0
|
||||
towrite = sectors
|
||||
while towrite > 0:
|
||||
if display:
|
||||
progressbar.show_progress("RPMB written", sector * 0x100, sectors * 0x100, display)
|
||||
if not self.custom_rpmb_write(sector=sector, data=rf.read(0x100), ufs=ufs):
|
||||
self.error(f"Couldn't write rpmb at sector {sector}.")
|
||||
progressbar.show_progress("RPMB written", pos * 0x100, sectors * 0x100, display)
|
||||
sz = min(sectors - pos, 0x10)
|
||||
if not self.custom_rpmb_write(sector=sector+pos, sectors=sz, data=rf.read(0x100*sz)):
|
||||
self.error(f"Couldn't write rpmb at sector {sector+pos}.")
|
||||
return False
|
||||
pos += sz
|
||||
towrite -= sz
|
||||
if display:
|
||||
progressbar.show_progress("RPMB written", sectors * 0x100, sectors * 0x100, display)
|
||||
self.info(f"Done reading writing {filename} to rpmb")
|
||||
return True
|
||||
return False
|
||||
|
||||
def erase_rpmb(self, display=True):
|
||||
def erase_rpmb(self, sector: int = None, sectors: int = None, display=True):
|
||||
progressbar = Progress(1, self.mtk.config.guiprogress)
|
||||
ufs = False
|
||||
sectors = 0
|
||||
if self.xflash.emmc.rpmb_size != 0:
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
elif self.xflash.ufs.block_size != 0:
|
||||
sectors = (512 * 256)
|
||||
if sector is None:
|
||||
sector = 0
|
||||
if sectors is None:
|
||||
if self.xflash.emmc is not None:
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
else:
|
||||
sectors = (512 * 256)
|
||||
if self.custom_rpmb_init():
|
||||
if sectors > 0:
|
||||
for sector in range(sectors):
|
||||
pos = 0
|
||||
towrite = sectors
|
||||
while towrite > 0:
|
||||
sz = min(sectors - pos, 0x10)
|
||||
if display:
|
||||
progressbar.show_progress("RPMB erased", sector * 0x100, sectors * 0x100, display)
|
||||
if not self.custom_rpmb_write(sector=sector, data=b"\x00" * 0x100, ufs=ufs):
|
||||
self.error(f"Couldn't erase rpmb at sector {sector}.")
|
||||
progressbar.show_progress("RPMB erased", pos * 0x100, sectors * 0x100, display)
|
||||
if not self.custom_rpmb_write(sector=sector+pos, sectors=sz, data=b"\x00" * 0x100 * sz):
|
||||
self.error(f"Couldn't erase rpmb at sector {sector+pos}.")
|
||||
return False
|
||||
pos += sz
|
||||
towrite -= sz
|
||||
if display:
|
||||
progressbar.show_progress("RPMB erased", sectors * 0x100, sectors * 0x100, display)
|
||||
self.info("Done erasing rpmb")
|
||||
return True
|
||||
return False
|
||||
|
|
|
@ -882,7 +882,7 @@ class DAXFlash(metaclass=LogBase):
|
|||
if display:
|
||||
self.mtk.daloader.progress.show_progress("Read", total, total, display)
|
||||
return buffer
|
||||
if not filename:
|
||||
if filename != b"":
|
||||
return b""
|
||||
return False
|
||||
|
||||
|
@ -930,11 +930,11 @@ class DAXFlash(metaclass=LogBase):
|
|||
part_info = self.partitiontype_and_size(storage, parttype, length)
|
||||
return part_info
|
||||
|
||||
def writeflash(self, addr, length, filename, offset=0, parttype=None, wdata=None, display=True):
|
||||
def writeflash(self, addr, length, filename: str = "", offset=0, parttype=None, wdata=None, display=True):
|
||||
self.mtk.daloader.progress.clear()
|
||||
fh = None
|
||||
fill = 0
|
||||
if filename is not None:
|
||||
if filename != "":
|
||||
if os.path.exists(filename):
|
||||
fsize = os.stat(filename).st_size
|
||||
length = min(fsize, length)
|
||||
|
@ -1245,6 +1245,7 @@ class DAXFlash(metaclass=LogBase):
|
|||
if status == 0x0 and unpack("<I", ret)[0] == 0xA1A2A3A4:
|
||||
self.info("DA Extensions successfully added")
|
||||
self.daext = True
|
||||
self.xft.custom_set_storage(ufs=self.daconfig.flashtype == "ufs")
|
||||
if not self.daext:
|
||||
self.warning("DA Extensions failed to enable")
|
||||
|
||||
|
|
|
@ -296,8 +296,27 @@ class XmlFlashExt(metaclass=LogBase):
|
|||
# "wb").write(da2patched)
|
||||
return da2patched
|
||||
|
||||
def custom_set_storage(self, ufs: bool = False):
|
||||
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMSTORAGE")
|
||||
if self.xsend(xmlcmd):
|
||||
result = self.xflash.get_response()
|
||||
if result == "OK":
|
||||
if ufs:
|
||||
self.xsend(int.to_bytes(1, 4, 'little'))
|
||||
else:
|
||||
# EMMC
|
||||
self.xsend(int.to_bytes(0, 4, 'little'))
|
||||
# CMD:END
|
||||
result = self.xflash.get_response()
|
||||
self.xflash.ack()
|
||||
# CMD:START
|
||||
result = self.xflash.get_response()
|
||||
self.xflash.ack()
|
||||
return True
|
||||
return False
|
||||
|
||||
def custom_rpmb_read(self, sector, ufs=False):
|
||||
data = b''
|
||||
data = bytearray()
|
||||
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMRPMBR")
|
||||
if ufs:
|
||||
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMURPMBR")
|
||||
|
@ -318,11 +337,15 @@ class XmlFlashExt(metaclass=LogBase):
|
|||
self.xflash.ack()
|
||||
return data
|
||||
|
||||
def custom_rpmb_write(self, sector, data: bytes, ufs=False):
|
||||
if len(data) != 0x100:
|
||||
def custom_rpmb_write(self, sector, data: bytes):
|
||||
if len(data) % 0x100 != 0:
|
||||
self.error("Incorrect rpmb frame length. Aborting")
|
||||
return False
|
||||
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMRPMBW")
|
||||
if self.xflash.emmc is not None:
|
||||
ufs = False
|
||||
else:
|
||||
ufs = True
|
||||
if ufs:
|
||||
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMURPMBW")
|
||||
if self.xsend(xmlcmd):
|
||||
|
@ -347,12 +370,12 @@ class XmlFlashExt(metaclass=LogBase):
|
|||
result = self.xflash.get_response()
|
||||
self.xflash.ack()
|
||||
return True
|
||||
# CMD:END
|
||||
result = self.xflash.get_response()
|
||||
self.xflash.ack()
|
||||
# CMD:START
|
||||
result = self.xflash.get_response()
|
||||
self.xflash.ack()
|
||||
# CMD:END
|
||||
result = self.xflash.get_response()
|
||||
self.xflash.ack()
|
||||
# CMD:START
|
||||
result = self.xflash.get_response()
|
||||
self.xflash.ack()
|
||||
return False
|
||||
|
||||
def custom_rpmb_init(self):
|
||||
|
@ -363,8 +386,7 @@ class XmlFlashExt(metaclass=LogBase):
|
|||
if meid != b"\x00" * 16:
|
||||
# self.config.set_meid(meid)
|
||||
self.info("Generating sej rpmbkey...")
|
||||
rpmbkey = hwc.aes_hwcrypt(btype="dxcc", mode="rpmb")
|
||||
#rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp)
|
||||
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp)
|
||||
if rpmbkey is not None:
|
||||
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMRPMBKEY")
|
||||
if self.xsend(xmlcmd):
|
||||
|
@ -418,34 +440,43 @@ class XmlFlashExt(metaclass=LogBase):
|
|||
otp = 32 * b"\x00"
|
||||
hwc.sej.sej_set_otp(otp)
|
||||
|
||||
def read_rpmb(self, filename=None, display=True):
|
||||
def read_rpmb(self, filename=None, sector: int = None, sectors: int = None, display=True):
|
||||
# self.custom_rpmb_prog(b"vutsrqponmlkjihgfedcba9876543210")
|
||||
# self.custom_rpmb_init()
|
||||
progressbar = Progress(1, self.mtk.config.guiprogress)
|
||||
sectors = 0
|
||||
# val = self.custom_rpmb_init()
|
||||
ufs = False
|
||||
if self.xflash.emmc is not None:
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
ufs = False
|
||||
elif self.xflash.ufs.lu1_size != 0:
|
||||
sectors = (512 * 256)
|
||||
else:
|
||||
ufs = True
|
||||
if sectors == 0:
|
||||
if not ufs:
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
elif self.xflash.ufs.lu1_size != 0:
|
||||
sectors = (512 * 256)
|
||||
if filename is None:
|
||||
filename = "rpmb.bin"
|
||||
if sectors > 0:
|
||||
with open(filename, "wb") as wf:
|
||||
for sector in range(sectors):
|
||||
pos = 0
|
||||
toread = sectors
|
||||
while toread > 0:
|
||||
if display:
|
||||
progressbar.show_progress("RPMB read", sector * 0x100, sectors * 0x100, display)
|
||||
data = self.custom_rpmb_read(sector=sector, ufs=ufs)
|
||||
progressbar.show_progress("RPMB read", pos * 0x100, sectors * 0x100, display)
|
||||
data = self.custom_rpmb_read(sector=sector + pos, ufs=ufs)
|
||||
if data == b"":
|
||||
self.error("Couldn't read rpmb.")
|
||||
return False
|
||||
wf.write(data)
|
||||
pos += 0x1
|
||||
toread -= 0x1
|
||||
if display:
|
||||
progressbar.show_progress("RPMB read", sectors * 0x100, sectors * 0x100, display)
|
||||
self.info(f"Done reading rpmb to {filename}")
|
||||
return True
|
||||
return False
|
||||
|
||||
def write_rpmb(self, filename=None, display=True):
|
||||
def write_rpmb(self, filename=None, sector: int = None, sectors: int = None, display=True):
|
||||
progressbar = Progress(1, self.mtk.config.guiprogress)
|
||||
if filename is None:
|
||||
self.error("Filename has to be given for writing to rpmb")
|
||||
|
@ -453,41 +484,57 @@ class XmlFlashExt(metaclass=LogBase):
|
|||
if not os.path.exists(filename):
|
||||
self.error(f"Couldn't find {filename} for writing to rpmb.")
|
||||
return False
|
||||
ufs = False
|
||||
sectors = 0
|
||||
if self.xflash.emmc.rpmb_size != 0:
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
elif self.xflash.ufs.block_size != 0:
|
||||
sectors = (512 * 256)
|
||||
if sectors == 0:
|
||||
max_sector_size = (512 * 256)
|
||||
if self.xflash.emmc is not None:
|
||||
max_sector_size = self.xflash.emmc.rpmb_size // 0x100
|
||||
else:
|
||||
max_sector_size = sectors
|
||||
filesize = os.path.getsize(filename)
|
||||
sectors = min(filesize // 256, max_sector_size)
|
||||
if self.custom_rpmb_init():
|
||||
if sectors > 0:
|
||||
with open(filename, "rb") as rf:
|
||||
for sector in range(sectors):
|
||||
pos = 0
|
||||
towrite = sectors
|
||||
while towrite > 0:
|
||||
if display:
|
||||
progressbar.show_progress("RPMB written", sector * 0x100, sectors * 0x100, display)
|
||||
if not self.custom_rpmb_write(sector=sector, data=rf.read(0x100), ufs=ufs):
|
||||
self.error(f"Couldn't write rpmb at sector {sector}.")
|
||||
progressbar.show_progress("RPMB written", pos * 0x100, sectors * 0x100, display)
|
||||
if not self.custom_rpmb_write(sector=pos + sector, data=rf.read(0x100)):
|
||||
self.error(f"Couldn't write rpmb at sector {sector + pos}.")
|
||||
return False
|
||||
pos += 0x1
|
||||
towrite -= 0x1
|
||||
if display:
|
||||
progressbar.show_progress("RPMB written", sectors * 0x100, sectors * 0x100, display)
|
||||
self.info(f"Done reading writing {filename} to rpmb")
|
||||
return True
|
||||
return False
|
||||
|
||||
def erase_rpmb(self, display=True):
|
||||
def erase_rpmb(self, sector: int = None, sectors: int = None, display=True):
|
||||
progressbar = Progress(1, self.mtk.config.guiprogress)
|
||||
ufs = False
|
||||
sectors = 0
|
||||
if self.xflash.emmc.rpmb_size != 0:
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
elif self.xflash.ufs.block_size != 0:
|
||||
sectors = (512 * 256)
|
||||
if sector is None:
|
||||
sector = 0
|
||||
if sectors is None:
|
||||
if self.xflash.emmc is not None:
|
||||
sectors = self.xflash.emmc.rpmb_size // 0x100
|
||||
elif self.xflash.ufs.block_size != 0:
|
||||
sectors = (512 * 256)
|
||||
|
||||
if self.custom_rpmb_init():
|
||||
if sectors > 0:
|
||||
for sector in range(sectors):
|
||||
pos = 0
|
||||
towrite = sectors
|
||||
while towrite > 0:
|
||||
if display:
|
||||
progressbar.show_progress("RPMB erased", sector * 0x100, sectors * 0x100, display)
|
||||
if not self.custom_rpmb_write(sector=sector, data=b"\x00" * 0x100, ufs=ufs):
|
||||
self.error(f"Couldn't erase rpmb at sector {sector}.")
|
||||
progressbar.show_progress("RPMB erased", pos * 0x100, sectors * 0x100, display)
|
||||
if not self.custom_rpmb_write(sector=pos + sector, data=b"\x00" * 0x100):
|
||||
self.error(f"Couldn't erase rpmb at sector {sector + pos}.")
|
||||
return False
|
||||
pos += 0x1
|
||||
towrite -= 0x1
|
||||
if display:
|
||||
progressbar.show_progress("RPMB erased", sectors * 0x100, sectors * 0x100, display)
|
||||
self.info("Done erasing rpmb")
|
||||
return True
|
||||
return False
|
||||
|
|
|
@ -632,6 +632,8 @@ class DAXML(metaclass=LogBase):
|
|||
sla_signature = generate_da_sla_signature(data=self.dev_info["rnd"], key=rsakey.key)
|
||||
if not self.handle_sla(data=sla_signature):
|
||||
print("SLA Key wasn't accepted.")
|
||||
self.reinit(True)
|
||||
self.check_lifecycle()
|
||||
if self.patch:
|
||||
xmlcmd = self.Cmd.create_cmd("CUSTOM")
|
||||
if self.xsend(xmlcmd):
|
||||
|
@ -654,14 +656,13 @@ class DAXML(metaclass=LogBase):
|
|||
if self.xmlft.ack():
|
||||
self.info("DA XML Extensions successfully loaded.")
|
||||
self.daext = True
|
||||
# self.xmlft.custom_set_storage(ufs=self.daconfig.flashtype == "ufs")
|
||||
else:
|
||||
self.error("DA XML Extensions failed.")
|
||||
self.daext = False
|
||||
else:
|
||||
self.error("DA XML Extensions failed.")
|
||||
self.daext = False
|
||||
self.reinit(True)
|
||||
self.check_lifecycle()
|
||||
# parttbl = self.read_partition_table()
|
||||
self.config.hwparam.writesetting("hwcode", hex(self.config.hwcode))
|
||||
return True
|
||||
|
@ -926,8 +927,7 @@ class DAXML(metaclass=LogBase):
|
|||
def writeflash(self, addr, length, filename, offset=0, parttype=None, wdata=None, display=True):
|
||||
self.mtk.daloader.progress.clear()
|
||||
fh = None
|
||||
fill = 0
|
||||
if filename is not None:
|
||||
if filename != "":
|
||||
if os.path.exists(filename):
|
||||
fsize = os.stat(filename).st_size
|
||||
length = min(fsize, length)
|
||||
|
|
|
@ -143,11 +143,11 @@ class Exploitation(metaclass=LogBase):
|
|||
def crash(self, mode=0):
|
||||
self.info("Crashing da...")
|
||||
try:
|
||||
if mode == 1:
|
||||
if mode == 0:
|
||||
self.mtk.preloader.send_da(0, 0x100, 0x100, b'\x00' * 0x100)
|
||||
elif mode == 2:
|
||||
elif mode == 1:
|
||||
self.mtk.preloader.read32(0, 0x100)
|
||||
elif mode == 0:
|
||||
elif mode == 2:
|
||||
payload = b'\x00\x01\x9F\xE5\x10\xFF\x2F\xE1' + b'\x00' * 0x110
|
||||
self.mtk.preloader.send_da(0x0, len(payload), 0x0, payload)
|
||||
self.mtk.preloader.jump_da(0x0)
|
||||
|
|
|
@ -186,9 +186,9 @@ class Progress:
|
|||
if self.guiprogress is not None:
|
||||
self.guiprogress(pos // self.pagesize)
|
||||
print_progress(prog, 100, prefix='Done',
|
||||
suffix=prefix + ' (Sector 0x%X of 0x%X) %0.2f MB/s' % (pos // self.pagesize,
|
||||
suffix=prefix + ' (0x%X/0x%X) %0.2f MB/s' % (pos // self.pagesize,
|
||||
total // self.pagesize,
|
||||
0), bar_length=50)
|
||||
0), bar_length=10)
|
||||
|
||||
if prog > self.prog:
|
||||
if self.guiprogress is not None:
|
||||
|
@ -221,10 +221,10 @@ class Progress:
|
|||
hinfo = "%02ds left" % sec
|
||||
|
||||
print_progress(prog, 100, prefix='Progress:',
|
||||
suffix=prefix + f' (Sector 0x%X of 0x%X, {hinfo}) %0.2f MB/s' % (pos // self.pagesize,
|
||||
suffix=prefix + f' (0x%X/0x%X, {hinfo}) %0.2f MB/s' % (pos // self.pagesize,
|
||||
total // self.pagesize,
|
||||
throughput),
|
||||
bar_length=50)
|
||||
bar_length=10)
|
||||
self.prog = prog
|
||||
self.progpos = pos
|
||||
self.progtime = t0
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,170 +0,0 @@
|
|||
.syntax unified
|
||||
|
||||
.code 32
|
||||
|
||||
.global start
|
||||
.section .text.start
|
||||
start:
|
||||
add r3, pc, #1
|
||||
bx r3
|
||||
|
||||
.global apmcu_dcache_clean_invalidate
|
||||
.section .text
|
||||
.type apmcu_dcache_clean_invalidate,%function
|
||||
apmcu_dcache_clean_invalidate:
|
||||
push {r4,r5,r7,r9,r10,r11}
|
||||
dmb /* ensure ordering with previous memory accesses */
|
||||
mrc p15, 1, r0, c0, c0, 1 /* read clidr */
|
||||
ands r3, r0, #0x7000000 /* extract loc from clidr */
|
||||
mov r3, r3, lsr #23 /* left align loc bit field */
|
||||
beq ci_finished /* if loc is 0, then no need to clean */
|
||||
mov r10, #0 /* start clean at cache level 0 */
|
||||
ci_loop1:
|
||||
add r2, r10, r10, lsr #1 /* work out 3x current cache level */
|
||||
mov r1, r0, lsr r2 /* extract cache type bits from clidr */
|
||||
and r1, r1, #7 /* mask of the bits for current cache only */
|
||||
cmp r1, #2 /* see what cache we have at this level */
|
||||
blt ci_skip /* skip if no cache, or just i-cache */
|
||||
mcr p15, 2, r10, c0, c0, 0 /* select current cache level in cssr */
|
||||
isb /* isb to sych the new cssr&csidr */
|
||||
mrc p15, 1, r1, c0, c0, 0 /* read the new csidr */
|
||||
and r2, r1, #7 /* extract the length of the cache lines */
|
||||
add r2, r2, #4 /* add 4 (line length offset) */
|
||||
ldr r4, =0x3ff
|
||||
ands r4, r4, r1, lsr #3 /* find maximum number on the way size */
|
||||
clz r5, r4 /* find bit position of way size increment */
|
||||
ldr r7, =0x7fff
|
||||
ands r7, r7, r1, lsr #13 /* extract max number of the index size */
|
||||
ci_loop2:
|
||||
mov r9, r4 /* create working copy of max way size */
|
||||
ci_loop3:
|
||||
orr r11, r10, r9, lsl r5 /* factor way and cache number into r11 */
|
||||
orr r11, r11, r7, lsl r2 /* factor index number into r11 */
|
||||
mcr p15, 0, r11, c7, c14, 2 /* clean & invalidate by set/way */
|
||||
subs r9, r9, #1 /* decrement the way */
|
||||
bge ci_loop3
|
||||
subs r7, r7, #1 /* decrement the index */
|
||||
bge ci_loop2
|
||||
ci_skip:
|
||||
add r10, r10, #2 /* increment cache number */
|
||||
cmp r3, r10
|
||||
bgt ci_loop1
|
||||
ci_finished:
|
||||
mov r10, #0 /* swith back to cache level 0 */
|
||||
mcr p15, 2, r10, c0, c0, 0 /* select current cache level in cssr */
|
||||
dsb
|
||||
isb
|
||||
pop {r4,r5,r7,r9,r10,r11}
|
||||
bx lr
|
||||
|
||||
|
||||
.global apmcu_dcache_invalidate
|
||||
.section .text
|
||||
.type apmcu_dcache_invalidate,%function
|
||||
apmcu_dcache_invalidate:
|
||||
push {r4,r5,r7,r9,r10,r11}
|
||||
dmb /* ensure ordering with previous memory accesses */
|
||||
mrc p15, 1, r0, c0, c0, 1 /* read clidr */
|
||||
ands r3, r0, #0x7000000 /* extract loc from clidr */
|
||||
mov r3, r3, lsr #23 /* left align loc bit field */
|
||||
beq cii_finished /* if loc is 0, then no need to clean */
|
||||
mov r10, #0 /* start clean at cache level 0 */
|
||||
cii_loop1:
|
||||
add r2, r10, r10, lsr #1 /* work out 3x current cache level */
|
||||
mov r1, r0, lsr r2 /* extract cache type bits from clidr */
|
||||
and r1, r1, #7 /* mask of the bits for current cache only */
|
||||
cmp r1, #2 /* see what cache we have at this level */
|
||||
blt cii_skip /* skip if no cache, or just i-cache */
|
||||
mcr p15, 2, r10, c0, c0, 0 /* select current cache level in cssr */
|
||||
isb /* isb to sych the new cssr&csidr */
|
||||
mrc p15, 1, r1, c0, c0, 0 /* read the new csidr */
|
||||
and r2, r1, #7 /* extract the length of the cache lines */
|
||||
add r2, r2, #4 /* add 4 (line length offset) */
|
||||
ldr r4, =0x3ff
|
||||
ands r4, r4, r1, lsr #3 /* find maximum number on the way size */
|
||||
clz r5, r4 /* find bit position of way size increment */
|
||||
ldr r7, =0x7fff
|
||||
ands r7, r7, r1, lsr #13 /* extract max number of the index size */
|
||||
cii_loop2:
|
||||
mov r9, r4 /* create working copy of max way size */
|
||||
cii_loop3:
|
||||
orr r11, r10, r9, lsl r5 /* factor way and cache number into r11 */
|
||||
orr r11, r11, r7, lsl r2 /* factor index number into r11 */
|
||||
mcr p15, 0, r11, c7, c6, 2 /* invalidate by set/way */
|
||||
subs r9, r9, #1 /* decrement the way */
|
||||
bge cii_loop3
|
||||
subs r7, r7, #1 /* decrement the index */
|
||||
bge cii_loop2
|
||||
cii_skip:
|
||||
add r10, r10, #2 /* increment cache number */
|
||||
cmp r3, r10
|
||||
bgt cii_loop1
|
||||
cii_finished:
|
||||
mov r10, #0 /* swith back to cache level 0 */
|
||||
mcr p15, 2, r10, c0, c0, 0 /* select current cache level in cssr */
|
||||
dsb
|
||||
isb
|
||||
pop {r4,r5,r7,r9,r10,r11}
|
||||
bx lr
|
||||
|
||||
|
||||
.global cache_init
|
||||
.section .text
|
||||
.type cache_init,%function
|
||||
cache_init:
|
||||
PUSH {R4-R11,LR}
|
||||
MOV R7, R0
|
||||
MRS R12, CPSR
|
||||
CPSID AIF
|
||||
TST R7, #2
|
||||
BEQ mmt
|
||||
MRC p15, 0, R0,c1,c0, 0
|
||||
TST R0, #4
|
||||
BEQ mma
|
||||
BIC R0, R0, #4
|
||||
MCR p15, 0, R0,c1,c0, 0
|
||||
BL apmcu_dcache_clean_invalidate
|
||||
B mmt
|
||||
mma:
|
||||
BL apmcu_dcache_invalidate
|
||||
mmt:
|
||||
TST R7, #1
|
||||
BEQ mml
|
||||
MRC p15, 0, R0,c1,c0, 0
|
||||
BIC R0, R0, #0x1000
|
||||
MCR p15, 0, R0,c1,c0, 0
|
||||
mml:
|
||||
MOV R0, #0
|
||||
MCR p15, 0, R0,c7,c5, 0
|
||||
MSR CPSR_cf, R12
|
||||
POP {R4-R11,PC}
|
||||
|
||||
|
||||
.global cache_close
|
||||
.section .text
|
||||
.type cache_close,%function
|
||||
cache_close:
|
||||
PUSH {R4-R11,LR}
|
||||
MOV R7, R0
|
||||
MRS R12, CPSR
|
||||
CPSID AIF
|
||||
TST R7, #2
|
||||
BEQ cci
|
||||
MRC p15, 0, R0,c1,c0, 0
|
||||
TST R0, #4
|
||||
BNE cci
|
||||
BL apmcu_dcache_invalidate
|
||||
MRC p15, 0, R0,c1,c0, 0
|
||||
ORR R0, R0, #4
|
||||
MCR p15, 0, R0,c1,c0, 0
|
||||
cci:
|
||||
TST R7, #1
|
||||
BEQ cct
|
||||
MOV R0, #0
|
||||
MCR p15, 0, R0,c7,c5, 0
|
||||
MRC p15, 0, R0,c1,c0, 0
|
||||
ORR R0, R0, #0x1000
|
||||
MCR p15, 0, R0,c1,c0, 0
|
||||
cct:
|
||||
MSR CPSR_cf, R12
|
||||
POP {R4-R11,PC}
|
File diff suppressed because it is too large
Load diff
|
@ -1,54 +0,0 @@
|
|||
ifneq (,$(findstring arm-linux-gnueabihf,$(shell gcc -dumpmachine)))
|
||||
CC := gcc
|
||||
AS := as
|
||||
LD := gcc
|
||||
OBJCOPY := objcopy
|
||||
else
|
||||
CC := aarch64-none-elf-gcc
|
||||
AS := aaarch64-none-elf-as
|
||||
LD := aaarch64-none-elf-gcc
|
||||
OBJCOPY := aarch64-none-elf-objcopy
|
||||
endif
|
||||
|
||||
VPATH := %.h common crypto
|
||||
INCLUDE_DIRS := .:$(PWD)/common:$(PWD)/crypto
|
||||
DSTPATH := ../../payloads
|
||||
|
||||
CFLAGS := -std=gnu99 -Os -mcpu=cortex-a53 -fno-builtin-printf -fno-strict-aliasing -fno-builtin-memcpy -fPIE -Wall -Wextra
|
||||
LDFLAGS := -nodefaultlibs -nostdlib -Wl,--build-id=none
|
||||
|
||||
|
||||
DA := da_x_64
|
||||
DA_BUILD := ../../build/da_x_64
|
||||
|
||||
DA_BUILD_BIN := $(DSTPATH)/$(DA).bin
|
||||
|
||||
DA_SRC = da_x_64.c common/libc.c crypto/sha256.c crypto/hmac-sha256.c
|
||||
ASM_SRC = common/start.S
|
||||
|
||||
all: CFLAGS += -DNDEBUG
|
||||
all: makepayloads
|
||||
|
||||
debug: CFLAGS += -DDEBUG -g
|
||||
debug: makepayloads
|
||||
|
||||
makepayloads: $(DA_BUILD)/da_x_64.bin
|
||||
mkdir -p $(DSTPATH)
|
||||
cp $(DA_BUILD)/$(DA).bin $(DA_BUILD_BIN)
|
||||
|
||||
$(DA_BUILD)/$(DA).bin: $(DA_BUILD)/$(DA).elf
|
||||
$(OBJCOPY) -O binary $^ $@
|
||||
|
||||
$(DA_BUILD)/$(DA).elf: $(DA_SRC:%.c=$(DA_BUILD)/%.o) $(ASM_SRC:%.S=$(DA_BUILD)/%.o)
|
||||
$(LD) -o $@ $^ $(LDFLAGS) -T common/generic.ld
|
||||
|
||||
$(DA_BUILD)/%.o: %.c
|
||||
mkdir -p $(@D)
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
$(DA_BUILD)/%.o: %.S
|
||||
mkdir -p $(@D)
|
||||
$(AS) -o $@ $<
|
||||
|
||||
clean:
|
||||
-rm -rf $(DSTPATH)/da_x_64.bin
|
File diff suppressed because it is too large
Load diff
|
@ -1,27 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/** \name Fixed width integers
|
||||
* @{
|
||||
*/
|
||||
typedef unsigned char u8_t; ///< Unsigned 8-bit type
|
||||
typedef unsigned short int u16_t; ///< Unsigned 16-bit type
|
||||
typedef unsigned int u32_t; ///< Unsigned 32-bit type
|
||||
typedef unsigned long long u64_t; ///< Unsigned 64-bit type
|
||||
|
||||
// typedef u64_t u64;
|
||||
// typedef u32_t u32;
|
||||
// typedef u16_t u16;
|
||||
// typedef u8_t u8;
|
||||
#ifndef size_t
|
||||
typedef unsigned size_t;
|
||||
#endif
|
||||
size_t strlen(const char *str);
|
||||
int printf(const char *format, ...);
|
||||
int sprintf (char *str, const char *format, ...);
|
||||
char *strcpy(char *to, const char *from);
|
||||
int strncmp(const char *s1, const char *s2, u32_t n);
|
||||
void* memset(void* dst, int c, u32_t n);
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
int memcmp(const void* s1, const void* s2, size_t n);
|
||||
char *strstr(const char *s1, const char *s2);
|
|
@ -1,23 +0,0 @@
|
|||
/* Sha256.h -- SHA-256 Hash
|
||||
2010-06-11 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __CRYPTO_SHA256_H
|
||||
#define __CRYPTO_SHA256_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
|
||||
typedef struct sha256_t
|
||||
{
|
||||
uint32_t state[8];
|
||||
uint64_t count;
|
||||
unsigned char buffer[64];
|
||||
} sha256_t;
|
||||
|
||||
void sha256_init(sha256_t *p);
|
||||
void sha256_update(sha256_t *p, const unsigned char *data, size_t size);
|
||||
void sha256_final(sha256_t *p, unsigned char *digest);
|
||||
void sha256_hash(unsigned char *buf, const unsigned char *data, size_t size);
|
||||
#endif
|
|
@ -1,18 +0,0 @@
|
|||
# Info
|
||||
- All binaries will end up in ../../payloads
|
||||
|
||||
# Release
|
||||
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
# Debug binaries with uart output enabled
|
||||
|
||||
```
|
||||
make debug
|
||||
```
|
||||
|
||||
# Run tests (emulates payloads via emulate_payload.py)
|
||||
|
||||
./runtest.sh
|
|
@ -1,18 +0,0 @@
|
|||
# Info
|
||||
- All binaries will end up in ../../payloads
|
||||
|
||||
# Release
|
||||
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
# Debug binaries with uart output enabled
|
||||
|
||||
```
|
||||
make debug
|
||||
```
|
||||
|
||||
# Run tests (emulates payloads via emulate_payload.py)
|
||||
|
||||
./runtest.sh
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* hmac-sha256.c
|
||||
* Copyright (C) 2017 Adrian Perez <aperez@igalia.com>
|
||||
*
|
||||
* Distributed under terms of the MIT license.
|
||||
*/
|
||||
|
||||
#include "hmac-sha256.h"
|
||||
#include "sha256.h"
|
||||
// #include "apicheck/apicheck.h"
|
||||
|
||||
/*
|
||||
* HMAC(H, K) == H(K ^ opad, H(K ^ ipad, text))
|
||||
*
|
||||
* H: Hash function (sha256)
|
||||
* K: Secret key
|
||||
* B: Block byte length
|
||||
* L: Byte length of hash function output
|
||||
*
|
||||
* https://tools.ietf.org/html/rfc2104
|
||||
*/
|
||||
|
||||
#define B 64
|
||||
#define L (SHA256_DIGEST_SIZE)
|
||||
#define K (SHA256_DIGEST_SIZE * 2)
|
||||
|
||||
#define I_PAD 0x36
|
||||
#define O_PAD 0x5C
|
||||
|
||||
void
|
||||
hmac_sha256 (uint8_t out[HMAC_SHA256_DIGEST_SIZE],
|
||||
const uint8_t *data, size_t data_len,
|
||||
const uint8_t *key, size_t key_len)
|
||||
{
|
||||
// api_check_return (out);
|
||||
// api_check_return (data);
|
||||
// api_check_return (key);
|
||||
// api_check_return (key_len <= B);
|
||||
|
||||
sha256_t ss;
|
||||
uint8_t kh[SHA256_DIGEST_SIZE];
|
||||
|
||||
/*
|
||||
* If the key length is bigger than the buffer size B, apply the hash
|
||||
* function to it first and use the result instead.
|
||||
*/
|
||||
if (key_len > B) {
|
||||
sha256_init (&ss);
|
||||
sha256_update (&ss, key, key_len);
|
||||
sha256_final (&ss, kh);
|
||||
key_len = SHA256_DIGEST_SIZE;
|
||||
key = kh;
|
||||
}
|
||||
|
||||
/*
|
||||
* (1) append zeros to the end of K to create a B byte string
|
||||
* (e.g., if K is of length 20 bytes and B=64, then K will be
|
||||
* appended with 44 zero bytes 0x00)
|
||||
* (2) XOR (bitwise exclusive-OR) the B byte string computed in step
|
||||
* (1) with ipad
|
||||
*/
|
||||
uint8_t kx[B];
|
||||
for (size_t i = 0; i < key_len; i++) kx[i] = I_PAD ^ key[i];
|
||||
for (size_t i = key_len; i < B; i++) kx[i] = I_PAD ^ 0;
|
||||
|
||||
/*
|
||||
* (3) append the stream of data 'text' to the B byte string resulting
|
||||
* from step (2)
|
||||
* (4) apply H to the stream generated in step (3)
|
||||
*/
|
||||
sha256_init (&ss);
|
||||
sha256_update (&ss, kx, B);
|
||||
sha256_update (&ss, data, data_len);
|
||||
sha256_final (&ss, out);
|
||||
|
||||
/*
|
||||
* (5) XOR (bitwise exclusive-OR) the B byte string computed in
|
||||
* step (1) with opad
|
||||
*
|
||||
* NOTE: The "kx" variable is reused.
|
||||
*/
|
||||
for (size_t i = 0; i < key_len; i++) kx[i] = O_PAD ^ key[i];
|
||||
for (size_t i = key_len; i < B; i++) kx[i] = O_PAD ^ 0;
|
||||
|
||||
/*
|
||||
* (6) append the H result from step (4) to the B byte string
|
||||
* resulting from step (5)
|
||||
* (7) apply H to the stream generated in step (6) and output
|
||||
* the result
|
||||
*/
|
||||
sha256_init (&ss);
|
||||
sha256_update (&ss, kx, B);
|
||||
sha256_update (&ss, out, SHA256_DIGEST_SIZE);
|
||||
sha256_final (&ss, out);
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* hmac-sha256.h
|
||||
* Copyright (C) 2017 Adrian Perez <aperez@igalia.com>
|
||||
*
|
||||
* Distributed under terms of the MIT license.
|
||||
*/
|
||||
|
||||
#ifndef HMAC_SHA256_H
|
||||
#define HMAC_SHA256_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define HMAC_SHA256_DIGEST_SIZE 32 /* Same as SHA-256's output size. */
|
||||
|
||||
void
|
||||
hmac_sha256 (uint8_t out[HMAC_SHA256_DIGEST_SIZE],
|
||||
const uint8_t *data, size_t data_len,
|
||||
const uint8_t *key, size_t key_len);
|
||||
|
||||
#endif /* !HMAC_SHA256_H */
|
|
@ -1,46 +0,0 @@
|
|||
|
||||
|
||||
#ifndef __ROTATE_DEFS_H
|
||||
#define __ROTATE_DEFS_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ROTL32(v, n) _rotl((v), (n))
|
||||
#define ROTL64(v, n) _rotl64((v), (n))
|
||||
|
||||
#define ROTR32(v, n) _rotr((v), (n))
|
||||
#define ROTR64(v, n) _rotr64((v), (n))
|
||||
|
||||
#else
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define U8V(v) ((uint8_t)(v) & 0xFFU)
|
||||
#define U16V(v) ((uint16_t)(v) & 0xFFFFU)
|
||||
#define U32V(v) ((uint32_t)(v) & 0xFFFFFFFFU)
|
||||
#define U64V(v) ((uint64_t)(v) & 0xFFFFFFFFFFFFFFFFU)
|
||||
|
||||
#define ROTL32(v, n) \
|
||||
(U32V((uint32_t)(v) << (n)) | ((uint32_t)(v) >> (32 - (n))))
|
||||
|
||||
// tests fail if we don't have this cast...
|
||||
#define ROTL64(v, n) \
|
||||
(U64V((uint64_t)(v) << (n)) | ((uint64_t)(v) >> (64 - (n))))
|
||||
|
||||
#define ROTR32(v, n) ROTL32(v, 32 - (n))
|
||||
#define ROTR64(v, n) ROTL64(v, 64 - (n))
|
||||
|
||||
#endif
|
||||
|
||||
#define ROTL8(v, n) \
|
||||
(U8V((uint8_t)(v) << (n)) | ((uint8_t)(v) >> (8 - (n))))
|
||||
|
||||
#define ROTL16(v, n) \
|
||||
(U16V((uint16_t)(v) << (n)) | ((uint16_t)(v) >> (16 - (n))))
|
||||
|
||||
#define ROTR8(v, n) ROTL8(v, 8 - (n))
|
||||
#define ROTR16(v, n) ROTL16(v, 16 - (n))
|
||||
|
||||
#endif
|
|
@ -1,221 +0,0 @@
|
|||
/* Crypto/Sha256.c -- SHA-256 Hash
|
||||
2010-06-11 : Igor Pavlov : Public domain
|
||||
This code is based on public domain code from Wei Dai's Crypto++ library. */
|
||||
|
||||
#include "rotate-bits.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/* define it for speed optimization */
|
||||
#define _SHA256_UNROLL
|
||||
#define _SHA256_UNROLL2
|
||||
|
||||
void
|
||||
sha256_init(sha256_t *p)
|
||||
{
|
||||
p->state[0] = 0x6a09e667;
|
||||
p->state[1] = 0xbb67ae85;
|
||||
p->state[2] = 0x3c6ef372;
|
||||
p->state[3] = 0xa54ff53a;
|
||||
p->state[4] = 0x510e527f;
|
||||
p->state[5] = 0x9b05688c;
|
||||
p->state[6] = 0x1f83d9ab;
|
||||
p->state[7] = 0x5be0cd19;
|
||||
p->count = 0;
|
||||
}
|
||||
|
||||
#define S0(x) (ROTR32(x, 2) ^ ROTR32(x,13) ^ ROTR32(x, 22))
|
||||
#define S1(x) (ROTR32(x, 6) ^ ROTR32(x,11) ^ ROTR32(x, 25))
|
||||
#define s0(x) (ROTR32(x, 7) ^ ROTR32(x,18) ^ (x >> 3))
|
||||
#define s1(x) (ROTR32(x,17) ^ ROTR32(x,19) ^ (x >> 10))
|
||||
|
||||
#define blk0(i) (W[i] = data[i])
|
||||
#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15]))
|
||||
|
||||
#define Ch(x,y,z) (z^(x&(y^z)))
|
||||
#define Maj(x,y,z) ((x&y)|(z&(x|y)))
|
||||
|
||||
#define a(i) T[(0-(i))&7]
|
||||
#define b(i) T[(1-(i))&7]
|
||||
#define c(i) T[(2-(i))&7]
|
||||
#define d(i) T[(3-(i))&7]
|
||||
#define e(i) T[(4-(i))&7]
|
||||
#define f(i) T[(5-(i))&7]
|
||||
#define g(i) T[(6-(i))&7]
|
||||
#define h(i) T[(7-(i))&7]
|
||||
|
||||
|
||||
#ifdef _SHA256_UNROLL2
|
||||
|
||||
#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\
|
||||
d += h; h += S0(a) + Maj(a, b, c)
|
||||
|
||||
#define RX_8(i) \
|
||||
R(a,b,c,d,e,f,g,h, i); \
|
||||
R(h,a,b,c,d,e,f,g, (i+1)); \
|
||||
R(g,h,a,b,c,d,e,f, (i+2)); \
|
||||
R(f,g,h,a,b,c,d,e, (i+3)); \
|
||||
R(e,f,g,h,a,b,c,d, (i+4)); \
|
||||
R(d,e,f,g,h,a,b,c, (i+5)); \
|
||||
R(c,d,e,f,g,h,a,b, (i+6)); \
|
||||
R(b,c,d,e,f,g,h,a, (i+7))
|
||||
|
||||
#else
|
||||
|
||||
#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\
|
||||
d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
|
||||
|
||||
#ifdef _SHA256_UNROLL
|
||||
|
||||
#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static const uint32_t K[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
static void
|
||||
sha256_transform(uint32_t *state, const uint32_t *data)
|
||||
{
|
||||
uint32_t W[16] = {0};
|
||||
unsigned j;
|
||||
#ifdef _SHA256_UNROLL2
|
||||
uint32_t a,b,c,d,e,f,g,h;
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
f = state[5];
|
||||
g = state[6];
|
||||
h = state[7];
|
||||
#else
|
||||
uint32_t T[8];
|
||||
for (j = 0; j < 8; j++)
|
||||
T[j] = state[j];
|
||||
#endif
|
||||
|
||||
for (j = 0; j < 64; j += 16)
|
||||
{
|
||||
#if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2)
|
||||
RX_8(0); RX_8(8);
|
||||
#else
|
||||
unsigned i;
|
||||
for (i = 0; i < 16; i++) { R(i); }
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _SHA256_UNROLL2
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
state[5] += f;
|
||||
state[6] += g;
|
||||
state[7] += h;
|
||||
#else
|
||||
for (j = 0; j < 8; j++)
|
||||
state[j] += T[j];
|
||||
#endif
|
||||
|
||||
/* Wipe variables */
|
||||
/* memset(W, 0, sizeof(W)); */
|
||||
/* memset(T, 0, sizeof(T)); */
|
||||
}
|
||||
|
||||
#undef S0
|
||||
#undef S1
|
||||
#undef s0
|
||||
#undef s1
|
||||
|
||||
static void
|
||||
sha256_write_byte_block(sha256_t *p)
|
||||
{
|
||||
uint32_t data32[16];
|
||||
unsigned i;
|
||||
for (i = 0; i < 16; i++)
|
||||
data32[i] =
|
||||
((uint32_t)(p->buffer[i * 4 ]) << 24) +
|
||||
((uint32_t)(p->buffer[i * 4 + 1]) << 16) +
|
||||
((uint32_t)(p->buffer[i * 4 + 2]) << 8) +
|
||||
((uint32_t)(p->buffer[i * 4 + 3]));
|
||||
sha256_transform(p->state, data32);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sha256_hash(unsigned char *buf, const unsigned char *data, size_t size)
|
||||
{
|
||||
sha256_t hash;
|
||||
sha256_init(&hash);
|
||||
sha256_update(&hash, data, size);
|
||||
sha256_final(&hash, buf);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sha256_update(sha256_t *p, const unsigned char *data, size_t size)
|
||||
{
|
||||
uint32_t curBufferPos = (uint32_t)p->count & 0x3F;
|
||||
while (size > 0)
|
||||
{
|
||||
p->buffer[curBufferPos++] = *data++;
|
||||
p->count++;
|
||||
size--;
|
||||
if (curBufferPos == 64)
|
||||
{
|
||||
curBufferPos = 0;
|
||||
sha256_write_byte_block(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sha256_final(sha256_t *p, unsigned char *digest)
|
||||
{
|
||||
uint64_t lenInBits = (p->count << 3);
|
||||
uint32_t curBufferPos = (uint32_t)p->count & 0x3F;
|
||||
unsigned i;
|
||||
p->buffer[curBufferPos++] = 0x80;
|
||||
while (curBufferPos != (64 - 8))
|
||||
{
|
||||
curBufferPos &= 0x3F;
|
||||
if (curBufferPos == 0)
|
||||
sha256_write_byte_block(p);
|
||||
p->buffer[curBufferPos++] = 0;
|
||||
}
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
p->buffer[curBufferPos++] = (unsigned char)(lenInBits >> 56);
|
||||
lenInBits <<= 8;
|
||||
}
|
||||
sha256_write_byte_block(p);
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
*digest++ = (unsigned char)(p->state[i] >> 24);
|
||||
*digest++ = (unsigned char)(p->state[i] >> 16);
|
||||
*digest++ = (unsigned char)(p->state[i] >> 8);
|
||||
*digest++ = (unsigned char)(p->state[i]);
|
||||
}
|
||||
sha256_init(p);
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
#include "libc.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/** \brief Division result
|
||||
* \sa uidiv
|
||||
*/
|
||||
typedef struct uidiv_result {
|
||||
u32_t quo; ///< Quotient
|
||||
u32_t rem; ///< Remainder
|
||||
} uidiv_result_t;
|
||||
|
||||
/********************************************//**
|
||||
* \brief Unsigned integer division
|
||||
*
|
||||
* ARM does not have native division support
|
||||
* \returns Result of operation or zero if
|
||||
* dividing by zero.
|
||||
***********************************************/
|
||||
uidiv_result_t
|
||||
uidiv (u32_t num, ///< Numerator
|
||||
u32_t dem) ///< Denominator
|
||||
{
|
||||
u32_t tmp = dem;
|
||||
uidiv_result_t ans = {0};
|
||||
|
||||
if (dem == 0)
|
||||
{
|
||||
// TODO: Somehow make error
|
||||
return ans;
|
||||
}
|
||||
|
||||
while (tmp <= num >> 1)
|
||||
{
|
||||
tmp <<= 1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (num >= tmp)
|
||||
{
|
||||
num -= tmp;
|
||||
ans.quo++;
|
||||
}
|
||||
ans.quo <<= 1;
|
||||
tmp >>= 1;
|
||||
} while (tmp >= dem);
|
||||
ans.quo >>= 1;
|
||||
ans.rem = num;
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
u32_t __aeabi_uidiv(u32_t num, u32_t dem)
|
||||
{
|
||||
return uidiv(num, dem).quo;
|
||||
}
|
||||
|
||||
u32_t __aeabi_uidivmod(u32_t num, u32_t dem)
|
||||
{
|
||||
return uidiv(num, dem).rem;
|
||||
}
|
||||
|
||||
void* memset(void* dst, int c, u32_t n)
|
||||
{
|
||||
char* q = dst;
|
||||
char* end = q + n;
|
||||
|
||||
for (;;) {
|
||||
if (q >= end) break;
|
||||
*q++ = (char) c;
|
||||
if (q >= end) break;
|
||||
*q++ = (char) c;
|
||||
if (q >= end) break;
|
||||
*q++ = (char) c;
|
||||
if (q >= end) break;
|
||||
*q++ = (char) c;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
u32_t
|
||||
strlen(const char *str)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
for (s = str; *s; ++s)
|
||||
;
|
||||
return (s - str);
|
||||
}
|
||||
|
||||
char *
|
||||
strcpy(char *to, const char *from)
|
||||
{
|
||||
char *save = to;
|
||||
|
||||
for (; (*to = *from) != '\0'; ++from, ++to);
|
||||
return(save);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare strings.
|
||||
*/
|
||||
int
|
||||
strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 == *s2++)
|
||||
if (*s1++ == 0)
|
||||
return (0);
|
||||
return (*(unsigned char *)s1 - *(unsigned char *)--s2);
|
||||
}
|
||||
|
||||
int
|
||||
strncmp(const char *s1, const char *s2, u32_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
return (0);
|
||||
do {
|
||||
if (*s1 != *s2++)
|
||||
return (*(unsigned char *)s1 - *(unsigned char *)--s2);
|
||||
if (*s1++ == 0)
|
||||
break;
|
||||
} while (--n != 0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
char *dp = dest;
|
||||
const char *sp = src;
|
||||
while (n--)
|
||||
*dp++ = *sp++;
|
||||
return dest;
|
||||
}
|
||||
|
||||
int memcmp(const void* s1, const void* s2, size_t n)
|
||||
{
|
||||
const unsigned char *p1 = s1, *p2 = s2;
|
||||
while(n--)
|
||||
if( *p1 != *p2 )
|
||||
return *p1 - *p2;
|
||||
else
|
||||
p1++,p2++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *strstr(const char *s1, const char *s2)
|
||||
{
|
||||
size_t n = strlen(s2);
|
||||
while(*s1)
|
||||
if(!memcmp(s1++,s2,n))
|
||||
return (char *)s1-1;
|
||||
return 0;
|
||||
}
|
0
mtkclient/src/stage1/emu_config/__init__.py → src/__init__.py
Executable file → Normal file
0
mtkclient/src/stage1/emu_config/__init__.py → src/__init__.py
Executable file → Normal file
37
src/da_x/CMakeLists.txt
Executable file
37
src/da_x/CMakeLists.txt
Executable file
|
@ -0,0 +1,37 @@
|
|||
cmake_minimum_required(VERSION 3.23)
|
||||
#
|
||||
# CMake Toolchain file for crosscompiling on ARM.
|
||||
#
|
||||
# Target operating system name.
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
|
||||
# Name of C compiler.
|
||||
set(CMAKE_C_COMPILER "/usr/bin/arm-linux-gnueabihf-gcc-12")
|
||||
set(CMAKE_C_OBJCOPY "/usr/bin/arm-linux-gnueabihf-objcopy")
|
||||
set(CMAKE_C_SIZE "/usr/bin/arm-linux-gnueabihf-size")
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
||||
enable_language(C ASM)
|
||||
|
||||
project(mtk_payload)
|
||||
set(CMAKE_C_FLAGS "-std=gnu99 -Os -mthumb -mcpu=cortex-a9 -fno-builtin-printf -fno-strict-aliasing -fno-builtin-memcpy -fno-stack-protector -fPIE -Wall -Wextra -z noexecstack")
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}" )
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-nodefaultlibs -nostdlib -Wl,--build-id=none")
|
||||
add_library(mycrt0 common/start.S)
|
||||
|
||||
add_executable(da_x.elf da_x.c)
|
||||
target_sources(da_x.elf PRIVATE crypto/dxcc.c crypto/hmac-sha256.c crypto/sej.c crypto/sha256.c crypto/V5/rpmb.c common/flash_handler.c common/libc.c)
|
||||
target_link_libraries(da_x.elf mycrt0)
|
||||
set_target_properties(da_x.elf PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${LINKER_SCRIPT})
|
||||
target_link_options(da_x.elf PRIVATE "-T${CMAKE_CURRENT_SOURCE_DIR}/common/generic.ld")
|
||||
target_link_options(da_x.elf PRIVATE "-L ${CMAKE_BINARY_DIR}")
|
||||
add_custom_target(da_x.bin ALL DEPENDS da_x.elf)
|
||||
add_custom_command(TARGET da_x.elf POST_BUILD
|
||||
COMMAND ${CMAKE_C_OBJCOPY} -O binary $<TARGET_FILE:da_x.elf> ${CMAKE_CURRENT_SOURCE_DIR}/../../mtkclient/payloads/da_x.bin
|
||||
COMMAND ${CMAKE_C_SIZE} $<TARGET_FILE:da_x.elf>)
|
||||
target_compile_options(da_x.elf PRIVATE -DV5)
|
674
src/da_x/LICENSE.txt
Executable file
674
src/da_x/LICENSE.txt
Executable file
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
@ -12,20 +12,20 @@ endif
|
|||
|
||||
VPATH := %.h common crypto
|
||||
INCLUDE_DIRS := .:$(PWD)/common:$(PWD)/crypto
|
||||
DSTPATH := ../../payloads
|
||||
DSTPATH := ../../mtkclient/payloads
|
||||
|
||||
CFLAGS := -std=gnu99 -Os -mthumb -mcpu=cortex-a9 -fno-builtin-printf -fno-strict-aliasing -fno-builtin-memcpy -fPIE -mno-unaligned-access -Wall -Wextra
|
||||
LDFLAGS := -nodefaultlibs -nostdlib -Wl,--build-id=none
|
||||
|
||||
|
||||
DA := da_x
|
||||
DA_BUILD := ../../build/da_x
|
||||
DA_BUILD := ../build
|
||||
|
||||
DA_BUILD_BIN := $(DSTPATH)/$(DA).bin
|
||||
|
||||
DA_SRC = da_x.c common/libc.c crypto/sha256.c crypto/hmac-sha256.c
|
||||
ASM_SRC = common/start.S
|
||||
DA_SRC = da_x.c common/libc.c crypto/aes.c crypto/mtk_crypt.c crypto/sha256.c crypto/hmac-sha256.c crypto/V5/rpmb.c crypto/dxcc.c crypto/sej.c common/flash_handler.c
|
||||
|
||||
ASM_SRC = common/start.S
|
||||
all: CFLAGS += -DNDEBUG
|
||||
all: makepayloads
|
||||
|
||||
|
@ -38,13 +38,14 @@ makepayloads: $(DA_BUILD)/da_x.bin
|
|||
|
||||
$(DA_BUILD)/$(DA).bin: $(DA_BUILD)/$(DA).elf
|
||||
$(OBJCOPY) -O binary $^ $@
|
||||
cp $(DA_BUILD)/$(DA).elf $(DA_BUILD_BIN)
|
||||
|
||||
$(DA_BUILD)/$(DA).elf: $(DA_SRC:%.c=$(DA_BUILD)/%.o) $(ASM_SRC:%.S=$(DA_BUILD)/%.o)
|
||||
$(LD) -o $@ $^ $(LDFLAGS) -T common/generic.ld
|
||||
|
||||
$(DA_BUILD)/%.o: %.c
|
||||
mkdir -p $(@D)
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
$(CC) -c -o $@ $< $(CFLAGS) -DV5
|
||||
|
||||
$(DA_BUILD)/%.o: %.S
|
||||
mkdir -p $(@D)
|
||||
|
@ -52,3 +53,4 @@ $(DA_BUILD)/%.o: %.S
|
|||
|
||||
clean:
|
||||
-rm -rf $(DSTPATH)/da_x.bin
|
||||
-rm -rf $(DA_BUILD)
|
8
src/da_x/build.sh
Executable file
8
src/da_x/build.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
|
||||
|
10
src/da_x/common/defs.h
Normal file
10
src/da_x/common/defs.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
#ifndef DA_X_DEFS_H
|
||||
#define DA_X_DEFS_H
|
||||
#define WRAP_RD32(addr) (*(volatile uint32_t *)(addr))
|
||||
#define WRAP_WR32(addr,data) ((*(volatile uint32_t *)(addr)) = (uint32_t)data)
|
||||
#define WRAP_SET_BIT(BS,REG) ((*(volatile uint32_t*)(REG)) |= (uint32_t)(BS))
|
||||
#define WRAP_CLR_BIT(BS,REG) ((*(volatile uint32_t*)(REG)) &= ~((uint32_t)(BS)))
|
||||
#endif //DA_X_DEFS_H
|
277
src/da_x/common/flash_handler.c
Normal file
277
src/da_x/common/flash_handler.c
Normal file
|
@ -0,0 +1,277 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
#include "flash_handler.h"
|
||||
#include "libc.h"
|
||||
#include "../crypto/hmac-sha256.h"
|
||||
#include "../crypto/V5/rpmb.h"
|
||||
|
||||
int (*mmc_get_card)(int /*id*/)=(const void*)0x22222222;
|
||||
int (*mmc_set_part_config)(struct mmc_card */*card*/, uint8_t /*cfg*/)=(const void*)0x33333333;
|
||||
int (*mmc_rpmb_send_command)(struct mmc_card */*card*/, uint8_t */*data_frame*/, uint32_t /*blks*/, int /*type*/, uint8_t /*req_type*/)=(const void*)0x44444444;
|
||||
int (*ufshcd_queuecommand)(struct ufs_hba */*hba*/, struct ufs_aio_scsi_cmd */*cmd*/)=(const void*)0x55555555;
|
||||
bool (*ufshcd_get_free_tag)(struct ufs_hba */*hba*/, int */*tag_out*/)=(const void*)0x66666666;
|
||||
uint32_t g_ufs_hba=0x77777777;
|
||||
static uint8_t rpmb_key[32]={0x64, 0x76, 0xEE, 0xF0, 0xF1, 0x6B, 0x30, 0x47, 0xE9, 0x79, 0x31, 0x58, 0xF6, 0x42, 0xDA, 0x46, 0xF7, 0x3B, 0x53, 0xFD, 0xC5, 0xF8, 0x84, 0xCE, 0x03, 0x73, 0x15, 0xBC, 0x54, 0x47, 0xD4, 0x6A};
|
||||
|
||||
uint8_t* get_current_rpmb_key(){
|
||||
return rpmb_key;
|
||||
}
|
||||
|
||||
void set_current_rpmb_key(uint8_t* rpmbkey){
|
||||
memcpy(rpmb_key,rpmbkey,0x20);
|
||||
}
|
||||
|
||||
void mcpy(uint8_t* src, uint8_t* dst, int len)
|
||||
{
|
||||
uint8_t* i;
|
||||
uint8_t* m;
|
||||
uint8_t* t;
|
||||
|
||||
for (i=src;len--;i++)
|
||||
{
|
||||
m=dst++;
|
||||
t=i;
|
||||
*t=*m;
|
||||
}
|
||||
}
|
||||
|
||||
int ufs_init() {
|
||||
struct rpmb_data_frame frame;
|
||||
struct ufs_aio_scsi_cmd cmd;
|
||||
struct ufs_hba* hba = (struct ufs_hba*)g_ufs_hba;
|
||||
int tag;
|
||||
ufshcd_get_free_tag(hba, &tag);
|
||||
cmd.data_buf = &frame;
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
frame.req_resp = __builtin_bswap16(RPMB_GET_WRITE_COUNTER);
|
||||
cmd_scsi_security_protocol_out(&cmd, tag);
|
||||
int res = ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
cmd_scsi_security_protocol_in(&cmd, tag);
|
||||
res = ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
res=__builtin_bswap16(frame.result);
|
||||
if (!res){
|
||||
res = rpmb_key_generate(frame, rpmb_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
ufshcd_put_tag(hba, tag);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int ufs_read_frame(uint32_t address, uint8_t* data){
|
||||
struct ufs_hba* hba = (struct ufs_hba*)g_ufs_hba;
|
||||
struct rpmb_data_frame frame;
|
||||
struct ufs_aio_scsi_cmd cmd;
|
||||
int tag;
|
||||
int res;
|
||||
if (!ufshcd_get_free_tag(hba, &tag))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
cmd.data_buf = &frame;
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
frame.addr = __builtin_bswap16(address);
|
||||
frame.blk_cnt = __builtin_bswap16(1);
|
||||
frame.req_resp = __builtin_bswap16(RPMB_READ_DATA);
|
||||
cmd_scsi_security_protocol_out(&cmd, tag);
|
||||
res = ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
cmd_scsi_security_protocol_in(&cmd, tag);
|
||||
res = ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
res = __builtin_bswap16(frame.result);
|
||||
if (!res) {
|
||||
memcpy(data,frame.data,0x100);
|
||||
}
|
||||
}
|
||||
}
|
||||
ufshcd_put_tag(hba, tag);
|
||||
return res;
|
||||
}
|
||||
|
||||
int ufs_write_frame(uint32_t address, uint8_t* data)
|
||||
{
|
||||
struct ufs_hba* hba = (struct ufs_hba*)g_ufs_hba;
|
||||
struct rpmb_data_frame frame;
|
||||
struct ufs_aio_scsi_cmd cmd;
|
||||
int tag;
|
||||
int res;
|
||||
if (!ufshcd_get_free_tag(hba, &tag)){
|
||||
return -1;
|
||||
}
|
||||
// 1. Step: Write counter read request
|
||||
cmd.data_buf = &frame;
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
frame.req_resp = __builtin_bswap16(RPMB_GET_WRITE_COUNTER);
|
||||
cmd_scsi_security_protocol_out(&cmd, tag);
|
||||
res=ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
// 1. Step: Read counter to frame.wc_cnt
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
cmd_scsi_security_protocol_in(&cmd, tag);
|
||||
res = ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
// 2. Step: Write data
|
||||
frame.addr = __builtin_bswap16(address);
|
||||
frame.blk_cnt = __builtin_bswap16(1);
|
||||
frame.result = 0;
|
||||
//frame.wr_cnt = __builtin_bswap32(wr_cnt);
|
||||
frame.req_resp = __builtin_bswap16(RPMB_WRITE_DATA);
|
||||
memcpy(frame.data,data,0x100);
|
||||
hmac_sha256(frame.key_MAC, frame.data, 0x200 - RPMB_DATA_BEG, rpmb_key, 0x20);
|
||||
cmd_scsi_security_protocol_out(&cmd, tag);
|
||||
res = ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
// Step 3: Send Request for Result Read
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
frame.req_resp = __builtin_bswap16(RPMB_RESULT_READ);
|
||||
cmd_scsi_security_protocol_out(&cmd, tag);
|
||||
res = ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
// Step 3: Response frame check
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
cmd_scsi_security_protocol_in(&cmd, tag);
|
||||
res = ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
res = __builtin_bswap16(frame.result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ufshcd_put_tag(hba, tag);
|
||||
return res;
|
||||
}
|
||||
|
||||
int ufs_prog_rpmbkey(uint8_t* rpmbkey){
|
||||
struct ufs_hba* hba = (struct ufs_hba*)g_ufs_hba;
|
||||
struct rpmb_data_frame frame;
|
||||
struct ufs_aio_scsi_cmd cmd;
|
||||
cmd.data_buf = &frame;
|
||||
int tag;
|
||||
int res=0;
|
||||
if (!ufshcd_get_free_tag(hba, &tag))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
cmd_scsi_security_protocol_out(&cmd, tag);
|
||||
// ufshcd_authen_key_prog_req_prepare
|
||||
memset(&frame,0,sizeof(struct rpmb_data_frame));
|
||||
memcpy(frame.key_MAC,rpmbkey,0x20);
|
||||
frame.req_resp = __builtin_bswap16(RPMB_PROGRAM_KEY);
|
||||
//
|
||||
res = ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
cmd_scsi_security_protocol_out(&cmd, tag);
|
||||
//ufshcd_authen_result_read_req_prepare
|
||||
memset(&frame,0,sizeof(struct rpmb_data_frame));
|
||||
frame.req_resp = __builtin_bswap16(RPMB_RESULT_READ);
|
||||
//
|
||||
res = ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
//memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
cmd_scsi_security_protocol_in(&cmd, tag);
|
||||
res = ufshcd_queuecommand(hba, &cmd);
|
||||
if (!res) {
|
||||
// ufshcd_authen_result_read_rsp_check
|
||||
res = __builtin_bswap16(frame.result);
|
||||
}
|
||||
}
|
||||
}
|
||||
ufshcd_put_tag(hba,tag);
|
||||
return res;
|
||||
}
|
||||
|
||||
int mmc_init(){
|
||||
struct rpmb_data_frame frame;
|
||||
struct mmc_card* card = (struct mmc_card*)mmc_get_card(0);
|
||||
mmc_set_part_config(card, (card->raw_ext_csd[EXT_CSD_PART_CFG] & 0xF8) | 3);
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
frame.req_resp = __builtin_bswap16(RPMB_GET_WRITE_COUNTER);
|
||||
mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_GET_WRITE_COUNTER, RPMB_REQ);
|
||||
mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_GET_WRITE_COUNTER, RPMB_RESP);
|
||||
int res=(int)__builtin_bswap16(frame.result);
|
||||
if (!res) {
|
||||
res = rpmb_key_generate(frame, rpmb_key);
|
||||
}
|
||||
mmc_set_part_config(card, card->raw_ext_csd[EXT_CSD_PART_CFG] & 0xF8);
|
||||
return res;
|
||||
}
|
||||
|
||||
int mmc_prog_rpmbkey(uint8_t* rpmbkey){
|
||||
struct rpmb_data_frame frame;
|
||||
struct mmc_card* card = (struct mmc_card*)mmc_get_card(0);
|
||||
mmc_set_part_config(card, (card->raw_ext_csd[EXT_CSD_PART_CFG] & 0xF8) | 3);
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
frame.blk_cnt = __builtin_bswap16(1);
|
||||
frame.req_resp = __builtin_bswap16(RPMB_PROGRAM_KEY);
|
||||
memcpy(frame.key_MAC,rpmbkey,0x20);
|
||||
mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_PROGRAM_KEY, RPMB_REQ);
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
frame.req_resp = __builtin_bswap16(RPMB_RESULT_READ);
|
||||
mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_RESULT_READ, RPMB_REQ);
|
||||
frame.req_resp = __builtin_bswap16(RPMB_PROGRAM_KEY);
|
||||
mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_RESULT_READ, RPMB_RESP);
|
||||
int res = __builtin_bswap16(frame.result);
|
||||
mmc_set_part_config(card, card->raw_ext_csd[EXT_CSD_PART_CFG] & 0xF8);
|
||||
return res;
|
||||
}
|
||||
|
||||
int mmc_read_frame(uint32_t address, uint8_t* data)
|
||||
{
|
||||
struct rpmb_data_frame frame;
|
||||
struct mmc_card* card = (struct mmc_card*)mmc_get_card(0);
|
||||
mmc_set_part_config(card, (card->raw_ext_csd[EXT_CSD_PART_CFG] & 0xF8) | 3);
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
frame.addr = __builtin_bswap16((uint16_t)address&0xFFFF);
|
||||
frame.req_resp = __builtin_bswap16(RPMB_READ_DATA);
|
||||
|
||||
mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_READ_DATA, RPMB_REQ);
|
||||
mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_READ_DATA, RPMB_RESP);
|
||||
int res = __builtin_bswap16(frame.result);
|
||||
if (!res){
|
||||
memcpy(data,frame.data,0x100);
|
||||
}
|
||||
mmc_set_part_config(card, card->raw_ext_csd[EXT_CSD_PART_CFG] & 0xF8);
|
||||
return res;
|
||||
}
|
||||
|
||||
int mmc_write_frame(uint32_t address, uint8_t* data)
|
||||
{
|
||||
struct rpmb_data_frame frame;
|
||||
struct mmc_card* card = (struct mmc_card*)mmc_get_card(0);
|
||||
mmc_set_part_config(card, (card->raw_ext_csd[EXT_CSD_PART_CFG] & 0xF8) | 3);
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
frame.req_resp = __builtin_bswap16(RPMB_GET_WRITE_COUNTER);
|
||||
int res=mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_GET_WRITE_COUNTER, RPMB_REQ);
|
||||
if (!res){
|
||||
res=mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_GET_WRITE_COUNTER, RPMB_RESP);
|
||||
if (!res){
|
||||
frame.addr = __builtin_bswap16(address);
|
||||
frame.blk_cnt = __builtin_bswap16(1);
|
||||
frame.result = 0;
|
||||
frame.req_resp = __builtin_bswap16(RPMB_WRITE_DATA);
|
||||
memcpy(frame.data,data,0x100);
|
||||
hmac_sha256(frame.key_MAC, frame.data, 0x200 - RPMB_DATA_BEG, (const uint8_t*)rpmb_key, 0x20);
|
||||
res = mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_WRITE_DATA, RPMB_REQ);
|
||||
if (!res) {
|
||||
memset(&frame, 0, sizeof(struct rpmb_data_frame));
|
||||
frame.req_resp = __builtin_bswap16(RPMB_RESULT_READ);
|
||||
res=mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_RESULT_READ, RPMB_REQ);
|
||||
if (!res) {
|
||||
res = mmc_rpmb_send_command((struct mmc_card *)card->host, (uint8_t*)&frame, 1, RPMB_RESULT_READ, RPMB_RESP);
|
||||
if (!res) {
|
||||
res = __builtin_bswap16(frame.result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mmc_set_part_config(card, card->raw_ext_csd[EXT_CSD_PART_CFG] & 0xF8);
|
||||
return res;
|
||||
}
|
24
src/da_x/common/flash_handler.h
Normal file
24
src/da_x/common/flash_handler.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
#ifndef DA_X_COMMAND_HANDLER_H
|
||||
#define DA_X_COMMAND_HANDLER_H
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
enum storage_type {
|
||||
STORAGE_EMMC=0,
|
||||
STORAGE_UFS=1
|
||||
};
|
||||
|
||||
void mcpy(uint8_t* src, uint8_t* dst, int len);
|
||||
int ufs_init();
|
||||
int ufs_read_frame(uint32_t address, uint8_t* data);
|
||||
int ufs_write_frame(uint32_t address, uint8_t* data);
|
||||
int ufs_prog_rpmbkey(uint8_t* rpmbkey);
|
||||
int mmc_prog_rpmbkey(uint8_t* rpmbkey);
|
||||
int mmc_init();
|
||||
int mmc_read_frame(uint32_t address, uint8_t* data);
|
||||
int mmc_write_frame(uint32_t address, uint8_t* data);
|
||||
uint8_t* get_current_rpmb_key();
|
||||
void set_current_rpmb_key(uint8_t* rpmbkey);
|
||||
#endif //DA_X_COMMAND_HANDLER_H
|
|
@ -3,12 +3,19 @@ OUTPUT_ARCH(arm)
|
|||
|
||||
ENTRY(start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FLAGS(5);
|
||||
data PT_LOAD FLAGS(6);
|
||||
bss PT_LOAD FLAGS(6);
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x68000000;
|
||||
.text : { *(.text.start) *(.text.main) *(.text .text.* .gnu.linkonce.t.*) }
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
.data : { *(.data .data.* .gnu.linkonce.d.*) }
|
||||
.bss : { *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) }
|
||||
.text : { *(.text.start) *(.text.main) *(.text .text.* .gnu.linkonce.t.*) } :text
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } :text
|
||||
.data : { *(.data .data.* .gnu.linkonce.d.*) } :data
|
||||
.bss : { *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) } :bss
|
||||
/DISCARD/ : { *(.interp) *(.dynsym) *(.dynstr) *(.hash) *(.dynamic) *(.comment) }
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
#include "libc.h"
|
||||
|
||||
#include <stdarg.h>
|
|
@ -1,3 +1,6 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \name Fixed width integers
|
||||
|
@ -24,4 +27,4 @@ void* memset(void* dst, int c, u32_t n);
|
|||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
int memcmp(const void* s1, const void* s2, size_t n);
|
||||
char *strstr(const char *s1, const char *s2);
|
||||
char *strstr(const char *s1, const char *s2);
|
4
mtkclient/src/da_x_64/common/generic.ld → src/da_x/common/linker.ld
Executable file → Normal file
4
mtkclient/src/da_x_64/common/generic.ld → src/da_x/common/linker.ld
Executable file → Normal file
|
@ -1,12 +1,12 @@
|
|||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(start)
|
||||
ENTRY(main)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x68000000;
|
||||
.text : { *(.text.start) *(.text.main) *(.text .text.* .gnu.linkonce.t.*) }
|
||||
.text : { *(.text.main) *(.text .text.* .gnu.linkonce.t.*) }
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
.data : { *(.data .data.* .gnu.linkonce.d.*) }
|
||||
.bss : { *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) }
|
|
@ -1,3 +1,6 @@
|
|||
/* Copyright 2024 (c) B.Kerler */
|
||||
/* Use of this source code is governed by a GPLv3 license, see LICENSE.txt. */
|
||||
|
||||
.syntax unified
|
||||
|
||||
.code 32
|
112
src/da_x/crypto/V5/rpmb.c
Normal file
112
src/da_x/crypto/V5/rpmb.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
#include "rpmb.h"
|
||||
#include "../../common/defs.h"
|
||||
#include "../dxcc.h"
|
||||
#include "../hmac-sha256.h"
|
||||
|
||||
void ufshcd_put_tag(struct ufs_hba *hba, int tag)
|
||||
{
|
||||
/* clear_bit(tag, &hba->lrb_in_use); */
|
||||
hba->lrb_in_use &= ~(1 << tag);
|
||||
}
|
||||
|
||||
void cmd_scsi_security_protocol_out(struct ufs_aio_scsi_cmd *cmd, int tag)
|
||||
{
|
||||
uint32_t blk_cnt = 1;
|
||||
uint8_t protocol=UFS_SECURITY_PROTOCOL;
|
||||
uint32_t protocol_specific=RPMB_PROTOCOL_ID;
|
||||
memset(cmd->cmd_data, 0, MAX_CDB_SIZE);
|
||||
cmd->lun = WLUN_RPMB;
|
||||
cmd->tag = tag;
|
||||
cmd->cmd_len = 0xC;
|
||||
cmd->dir = DMA_TO_DEVICE;
|
||||
cmd->exp_len = blk_cnt << 9;
|
||||
cmd->attr = 0;
|
||||
cmd->cmd_data[0] = SECURITY_PROTOCOL_OUT; //0xB5 .. 0xA2 ?
|
||||
cmd->cmd_data[1] = protocol; //0xEC
|
||||
cmd->cmd_data[2] = (protocol_specific >> 8) & 0xFF; //security protocol specific
|
||||
cmd->cmd_data[3] = protocol_specific & 0xFF; //security protocol specific
|
||||
cmd->cmd_data[4] = 0x0; // INC_512 = 0
|
||||
cmd->cmd_data[5] = 0; // reserved
|
||||
cmd->cmd_data[6] = ((blk_cnt << 9) >> 24) & 0xFF; //Reserved
|
||||
cmd->cmd_data[7] = ((blk_cnt << 9) >> 16) & 0xFF; //Reserved
|
||||
cmd->cmd_data[8] = ((blk_cnt << 9) >> 8) & 0xFF; //Reserved
|
||||
cmd->cmd_data[9] = 0x0; //(blk_cnt << 9) & 0xFF; actually = 0 //Reserved
|
||||
cmd->cmd_data[0xA] = 0x0; //Reserved
|
||||
cmd->cmd_data[0xB] = (uint8_t)0; // control
|
||||
}
|
||||
|
||||
void cmd_scsi_security_protocol_in(struct ufs_aio_scsi_cmd *cmd, int tag)
|
||||
{
|
||||
uint32_t blk_cnt = 1;
|
||||
uint8_t protocol=UFS_SECURITY_PROTOCOL;
|
||||
uint32_t protocol_specific=RPMB_PROTOCOL_ID;
|
||||
memset(cmd->cmd_data, 0, MAX_CDB_SIZE);
|
||||
cmd->exp_len = blk_cnt * 512;
|
||||
cmd->tag = tag;
|
||||
cmd->dir = DMA_FROM_DEVICE;
|
||||
cmd->cmd_len = 0xC;
|
||||
cmd->lun = WLUN_RPMB;
|
||||
cmd->attr = ATTR_SIMPLE;
|
||||
cmd->cmd_len = 12;
|
||||
cmd->cmd_data[0] = SECURITY_PROTOCOL_IN; //opcode
|
||||
cmd->cmd_data[1] = protocol; //security protocol
|
||||
cmd->cmd_data[2] = (protocol_specific >> 8) & 0xFF; //security protocol specific
|
||||
cmd->cmd_data[3] = protocol_specific & 0xFF; //security protocol specific
|
||||
cmd->cmd_data[4] = 0x0; // INC_512 = 0
|
||||
cmd->cmd_data[5] = 0x0; //Reserved
|
||||
cmd->cmd_data[6] = ((blk_cnt << 9) >> 24) & 0xFF; //Reserved
|
||||
cmd->cmd_data[7] = ((blk_cnt << 9) >> 16) & 0xFF; //Reserved
|
||||
cmd->cmd_data[8] = ((blk_cnt << 9) >> 8) & 0xFF; //Reserved
|
||||
cmd->cmd_data[9] = 0x0; //(blk_cnt << 9) & 0xFF; actually = 0 //Reserved
|
||||
cmd->cmd_data[10] = 0x0; //Reserved
|
||||
cmd->cmd_data[11] = 0x0; //control = 0
|
||||
}
|
||||
|
||||
int rpmb_key_generate(struct rpmb_data_frame frame, uint8_t* rpmb_key)
|
||||
{
|
||||
uint8_t hash[34]={0};
|
||||
uint8_t rpmbiv[16]={'RPMB KEYSASI'};
|
||||
uint8_t sw_rpmb[0x20]={'vutsrqponmlkjihgfedcba9876543210'};
|
||||
uint8_t* sasi=&rpmbiv[8];
|
||||
int res = -2;
|
||||
hmac_sha256(hash, frame.data, 512 - RPMB_DATA_BEG, (const uint8_t*)rpmb_key, 32);
|
||||
if (!memcmp(frame.key_MAC, hash, 32))
|
||||
{
|
||||
res=0;
|
||||
}
|
||||
else {
|
||||
memset(rpmb_key, 0, 0x20);
|
||||
hmac_sha256(hash, frame.data, 512 - RPMB_DATA_BEG, (const uint8_t *) rpmb_key, 32);
|
||||
if (!memcmp(frame.key_MAC, hash, 32)) {
|
||||
res=0;
|
||||
} else {
|
||||
WRAP_WR32(0x1000108C, 0x18000000);
|
||||
dxcc((volatile uint32_t *) 0x10210000, 1, rpmbiv, 8, sasi, 4, rpmb_key, 32);
|
||||
WRAP_WR32(0x10001088, 0x18000000);
|
||||
hmac_sha256(hash, frame.data, 512 - RPMB_DATA_BEG, (const uint8_t *) rpmb_key, 0x20);
|
||||
if (!memcmp(frame.key_MAC, hash, 32)) {
|
||||
res=0;
|
||||
} else {
|
||||
WRAP_WR32(0x10210A64, 0xFFFFFFFF);
|
||||
WRAP_WR32(0x1000108C, 0x18000000);
|
||||
dxcc((volatile uint32_t *) 0x10210000, 1, rpmbiv, 8, sasi, 4, rpmb_key, 32);
|
||||
WRAP_WR32(0x10001088, 0x18000000);
|
||||
hmac_sha256(hash, frame.data, 512 - RPMB_DATA_BEG, (const uint8_t *) rpmb_key, 0x20);
|
||||
if (!memcmp(frame.key_MAC, hash, 32)) {
|
||||
res=0;
|
||||
} else {
|
||||
memcpy(rpmb_key, sw_rpmb, 0x20);
|
||||
hmac_sha256(hash, frame.data, 512 - RPMB_DATA_BEG, (const uint8_t *) rpmb_key, 0x20);
|
||||
if (!memcmp(frame.key_MAC, hash, 32)) {
|
||||
res=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
567
src/da_x/crypto/V5/rpmb.h
Normal file
567
src/da_x/crypto/V5/rpmb.h
Normal file
|
@ -0,0 +1,567 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
#ifndef DA_X_RPMB_H
|
||||
#define DA_X_RPMB_H
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../../common/libc.h"
|
||||
|
||||
#define EXT_CSD_PART_CFG 179
|
||||
#define WLUN_ID (1<<7)
|
||||
#define WLUN_REPORT_LUNS (WLUN_ID | 0x1)
|
||||
#define WLUN_UFS_DEVICE (WLUN_ID | 0x50)
|
||||
#define WLUN_BOOT (WLUN_ID | 0x30)
|
||||
#define WLUN_RPMB (WLUN_ID | 0x44)
|
||||
|
||||
enum {
|
||||
ATTR_SIMPLE = 0,
|
||||
ATTR_ORDERED = 1,
|
||||
ATTR_HEAD_OF_QUEUE = 2,
|
||||
};
|
||||
|
||||
/*#define UFS_UPIU_RPMB_WLUN 0xC4*/
|
||||
#define SECURITY_PROTOCOL_IN 0xA2
|
||||
#define SECURITY_PROTOCOL_OUT 0xB5
|
||||
#define UFS_SECURITY_PROTOCOL 0xEC
|
||||
#define RPMB_PROTOCOL_ID (0x1)
|
||||
|
||||
#define RPMB_PROGRAM_KEY 1 /* Program RPMB Authentication Key */
|
||||
#define RPMB_GET_WRITE_COUNTER 2 /* Read RPMB write counter */
|
||||
#define RPMB_WRITE_DATA 3 /* Write data to RPMB partition */
|
||||
#define RPMB_READ_DATA 4 /* Read data from RPMB partition */
|
||||
#define RPMB_RESULT_READ 5 /* Read result request */
|
||||
#define RPMB_REQ_SEC_WPCB_WRITE 6
|
||||
#define RPMB_REQ_SEC_WPCB_READ 7
|
||||
#define RPMB_REQ 1 /* RPMB request mark */
|
||||
#define RPMB_RESP (1 << 1)/* RPMB response mark */
|
||||
#define RPMB_AVALIABLE_SECTORS 8 /* 4K page size */
|
||||
|
||||
#define RPMB_TYPE_BEG 510 // FF
|
||||
#define RPMB_RES_BEG 508 // FE
|
||||
#define RPMB_BLKS_BEG 506 // FD
|
||||
#define RPMB_ADDR_BEG 504 // FC
|
||||
#define RPMB_WCOUNTER_BEG 500 // FA
|
||||
|
||||
#define RPMB_NONCE_BEG 484
|
||||
#define RPMB_DATA_BEG 228
|
||||
#define RPMB_MAC_BEG 196
|
||||
|
||||
#define UFS_UPIU_MAX_GENERAL_LUN 3
|
||||
|
||||
#define dma_data_direction uint8_t
|
||||
|
||||
struct rpmb_data_frame
|
||||
{
|
||||
uint8_t stuff[196];
|
||||
uint8_t key_MAC[32];
|
||||
uint8_t data[256];
|
||||
uint8_t nonce[16];
|
||||
uint32_t wr_cnt;
|
||||
uint16_t addr;
|
||||
uint16_t blk_cnt;
|
||||
uint16_t result;
|
||||
uint16_t req_resp;
|
||||
};
|
||||
|
||||
struct mmc_cid {
|
||||
unsigned int manfid;
|
||||
char prod_name[8];
|
||||
unsigned int serial;
|
||||
unsigned short oemid;
|
||||
unsigned short year;
|
||||
unsigned char hwrev;
|
||||
unsigned char fwrev;
|
||||
unsigned char month;
|
||||
unsigned char cbx;
|
||||
};
|
||||
|
||||
struct mmc_csd {
|
||||
unsigned char csd_struct; /* csd structure version */
|
||||
unsigned char mmca_vsn;
|
||||
unsigned short cmdclass; /* card command classes */
|
||||
unsigned short tacc_clks; /* data read access-time-1 in clks */
|
||||
unsigned int tacc_ns; /* data read access-time-2 */
|
||||
unsigned int r2w_factor; /* write speed factor */
|
||||
unsigned int max_dtr; /* max. data transfer rate */
|
||||
unsigned int read_blkbits; /* max. read data block length */
|
||||
unsigned int write_blkbits; /* max. write data block length */
|
||||
unsigned int capacity; /* card capacity */
|
||||
unsigned int erase_sctsz; /* erase sector size */
|
||||
unsigned int write_prot_grpsz;
|
||||
unsigned int read_partial:1,
|
||||
read_misalign:1,
|
||||
write_partial:1,
|
||||
write_misalign:1,
|
||||
write_prot_grp:1,
|
||||
perm_wr_prot:1,
|
||||
tmp_wr_prot:1,
|
||||
erase_blk_en:1,
|
||||
copy:1,
|
||||
dsr:1;
|
||||
};
|
||||
|
||||
struct mmc_raw_ext_csd {
|
||||
/* mode segment */
|
||||
unsigned char rsv1[134];
|
||||
unsigned char sec_bad_blk_mgmt;
|
||||
unsigned char rsv2[1];
|
||||
unsigned char enh_start_addr[4];
|
||||
unsigned char enh_sz_mult[3];
|
||||
unsigned char gp_sz_mult[12];
|
||||
unsigned char part_set_cmpl;
|
||||
unsigned char part_attr;
|
||||
unsigned char max_enh_sz_mult[3];
|
||||
unsigned char part_supp;
|
||||
unsigned char rsv3[1];
|
||||
unsigned char rst_n_func;
|
||||
unsigned char rsv4[5];
|
||||
unsigned char rpmb_sz_mult;
|
||||
unsigned char fw_cfg;
|
||||
unsigned char rsv5[1];
|
||||
unsigned char user_wp;
|
||||
unsigned char rsv6[1];
|
||||
unsigned char boot_wp;
|
||||
unsigned char rsv7[1];
|
||||
unsigned char erase_grp_def;
|
||||
unsigned char rsv8[1];
|
||||
unsigned char boot_bus_width;
|
||||
unsigned char boot_cfg_prot;
|
||||
unsigned char part_cfg;
|
||||
unsigned char rsv9[1];
|
||||
unsigned char erase_mem_cont;
|
||||
unsigned char rsv10[1];
|
||||
unsigned char bus_width;
|
||||
unsigned char rsv11[1];
|
||||
unsigned char hs_timing;
|
||||
unsigned char rsv12[1];
|
||||
unsigned char pwr_cls;
|
||||
unsigned char rsv13[1];
|
||||
unsigned char cmd_set_rev;
|
||||
unsigned char rsv14[1];
|
||||
unsigned char cmd_set;
|
||||
|
||||
/* propertities segment */
|
||||
unsigned char ext_csd_rev;
|
||||
unsigned char rsv15[1];
|
||||
unsigned char csd_struct;
|
||||
unsigned char rsv16[1];
|
||||
unsigned char card_type;
|
||||
unsigned char rsv17[1];
|
||||
unsigned char pwr_cls_52_195;
|
||||
unsigned char pwr_cls_26_195;
|
||||
unsigned char pwr_cls_52_360;
|
||||
unsigned char pwr_cls_26_360;
|
||||
unsigned char rsv18[1];
|
||||
unsigned char min_perf_r_4_26;
|
||||
unsigned char min_perf_w_4_26;
|
||||
unsigned char min_perf_r_8_26_4_52;
|
||||
unsigned char min_perf_w_8_26_4_52;
|
||||
unsigned char min_perf_r_8_52;
|
||||
unsigned char min_perf_w_8_52;
|
||||
unsigned char rsv19[1];
|
||||
unsigned char sec_cnt[4];
|
||||
unsigned char rsv20[1];
|
||||
unsigned char slp_awake_tmo;
|
||||
unsigned char rsv21[1];
|
||||
unsigned char slp_curr_vccq;
|
||||
unsigned char slp_curr_vcc;
|
||||
unsigned char hc_wp_grp_sz;
|
||||
unsigned char rel_wr_sec_cnt;
|
||||
unsigned char erase_tmo_mult;
|
||||
unsigned char hc_erase_grp_sz;
|
||||
unsigned char acc_sz;
|
||||
unsigned char boot_sz_mult;
|
||||
unsigned char rsv22[1];
|
||||
unsigned char boot_info;
|
||||
unsigned char sec_trim_mult;
|
||||
unsigned char sec_erase_mult;
|
||||
unsigned char sec_supp;
|
||||
unsigned char trim_mult;
|
||||
unsigned char rsv23[1];
|
||||
unsigned char min_perf_ddr_r_8_52;
|
||||
unsigned char min_perf_ddr_w_8_52;
|
||||
unsigned char rsv24[2];
|
||||
unsigned char pwr_cls_ddr_52_195;
|
||||
unsigned char pwr_cls_ddr_52_360;
|
||||
unsigned char rsv25[1];
|
||||
unsigned char ini_tmo_ap;
|
||||
unsigned char rsv26[262];
|
||||
unsigned char supp_cmd_set;
|
||||
unsigned char rsv27[7];
|
||||
};
|
||||
|
||||
struct mmc_ext_csd {
|
||||
unsigned int trim_tmo_ms;
|
||||
unsigned int hc_wp_grp_sz;
|
||||
unsigned int hc_erase_grp_sz;
|
||||
unsigned int sectors;
|
||||
unsigned int hs_max_dtr;
|
||||
unsigned int boot_part_sz;
|
||||
unsigned int rpmb_sz;
|
||||
unsigned int access_sz;
|
||||
unsigned int enh_sz;
|
||||
unsigned int enh_start_addr;
|
||||
unsigned char rev;
|
||||
unsigned char boot_info;
|
||||
unsigned char part_en:1,
|
||||
enh_attr_en:1,
|
||||
ddr_support:1;
|
||||
unsigned char erased_mem_cont;
|
||||
};
|
||||
|
||||
|
||||
struct sd_scr {
|
||||
unsigned char scr_struct;
|
||||
unsigned char sda_vsn;
|
||||
unsigned char data_bit_after_erase;
|
||||
unsigned char security;
|
||||
unsigned char bus_widths;
|
||||
unsigned char sda_vsn3;
|
||||
unsigned char ex_security;
|
||||
unsigned char cmd_support;
|
||||
};
|
||||
|
||||
struct sd_switch_caps {
|
||||
unsigned int hs_max_dtr;
|
||||
unsigned int ddr;
|
||||
unsigned int drv_strength;
|
||||
unsigned int max_cur;
|
||||
};
|
||||
|
||||
struct mmc_host
|
||||
{
|
||||
struct mmc_card *card;
|
||||
uint64_t max_hw_segs;
|
||||
uint64_t max_phys_segs;
|
||||
uint64_t max_seg_size;
|
||||
uint32_t max_blk_size;
|
||||
uint32_t max_blk_count;
|
||||
uint32_t base;
|
||||
uint32_t caps;
|
||||
uint32_t f_min;
|
||||
uint32_t f_max;
|
||||
uint32_t clk;
|
||||
uint32_t sclk;
|
||||
uint32_t blklen;
|
||||
uint32_t blkbits;
|
||||
uint32_t ocr;
|
||||
uint32_t ocr_avail;
|
||||
uint32_t timeout_ns;
|
||||
uint32_t timeout_clks;
|
||||
uint8_t clksrc;
|
||||
uint8_t id;
|
||||
uint8_t boot_type;
|
||||
uint8_t app_cmd;
|
||||
uint32_t app_cmd_arg;
|
||||
uint32_t time_read;
|
||||
void *priv;
|
||||
int (*blk_read)(struct mmc_host *host, uint8_t *dst, uint32_t src, uint32_t nblks);
|
||||
int (*blk_write)(struct mmc_host *host, uint32_t dst, uint8_t *src, uint32_t nblks);
|
||||
};
|
||||
|
||||
/* MMC device */
|
||||
struct mmc_card {
|
||||
struct mmc_host *host;
|
||||
unsigned int nblks;
|
||||
unsigned int blklen;
|
||||
unsigned int ocr;
|
||||
unsigned int maxhz;
|
||||
unsigned int uhs_mode;
|
||||
unsigned int rca;
|
||||
unsigned int type;
|
||||
unsigned short state;
|
||||
unsigned short ready;
|
||||
uint32_t raw_cid[4];
|
||||
uint32_t raw_csd[4];
|
||||
uint32_t raw_scr[2];
|
||||
uint8_t raw_ext_csd[512];
|
||||
struct mmc_cid cid;
|
||||
struct mmc_csd csd;
|
||||
struct mmc_ext_csd ext_csd;
|
||||
struct sd_scr scr;
|
||||
struct sd_switch_caps sw_caps;
|
||||
};
|
||||
|
||||
|
||||
#define MAX_CDB_SIZE 16
|
||||
|
||||
enum dma_data_direction {
|
||||
DMA_BIDIRECTIONAL = 0,
|
||||
DMA_TO_DEVICE = 1,
|
||||
DMA_FROM_DEVICE = 2,
|
||||
DMA_NONE = 3,
|
||||
};
|
||||
|
||||
struct ufs_aio_scsi_cmd {
|
||||
uint32_t lun;
|
||||
int tag;
|
||||
dma_data_direction dir; //dma_data_direction
|
||||
uint8_t attr;
|
||||
uint8_t cmd_data[MAX_CDB_SIZE];
|
||||
uint16_t cmd_len;
|
||||
uint32_t exp_len;
|
||||
struct rpmb_data_frame * data_buf;
|
||||
};
|
||||
|
||||
/* UTP QUERY Transaction Specific Fields OpCode */
|
||||
enum query_opcode {
|
||||
UPIU_QUERY_OPCODE_NOP = 0x0,
|
||||
UPIU_QUERY_OPCODE_READ_DESC = 0x1,
|
||||
UPIU_QUERY_OPCODE_WRITE_DESC = 0x2,
|
||||
UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
|
||||
UPIU_QUERY_OPCODE_WRITE_ATTR = 0x4,
|
||||
UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
|
||||
UPIU_QUERY_OPCODE_SET_FLAG = 0x6,
|
||||
UPIU_QUERY_OPCODE_CLEAR_FLAG = 0x7,
|
||||
UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8,
|
||||
};
|
||||
|
||||
/* Flag idn for Query Requests*/
|
||||
enum flag_idn {
|
||||
QUERY_FLAG_IDN_FDEVICEINIT = 0x01,
|
||||
QUERY_FLAG_IDN_PWR_ON_WPE = 0x03,
|
||||
QUERY_FLAG_IDN_BKOPS_EN = 0x04,
|
||||
};
|
||||
|
||||
/* Attribute idn for Query requests */
|
||||
enum attr_idn {
|
||||
QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03,
|
||||
QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
|
||||
QUERY_ATTR_IDN_REF_CLK_FREQ = 0x0A,
|
||||
QUERY_ATTR_IDN_EE_CONTROL = 0x0D,
|
||||
QUERY_ATTR_IDN_EE_STATUS = 0x0E,
|
||||
};
|
||||
|
||||
/* Descriptor idn for Query requests */
|
||||
enum desc_idn {
|
||||
QUERY_DESC_IDN_DEVICE = 0x0,
|
||||
QUERY_DESC_IDN_CONFIGURATION = 0x1,
|
||||
QUERY_DESC_IDN_UNIT = 0x2,
|
||||
QUERY_DESC_IDN_RFU_0 = 0x3,
|
||||
QUERY_DESC_IDN_INTERCONNECT = 0x4,
|
||||
QUERY_DESC_IDN_STRING = 0x5,
|
||||
QUERY_DESC_IDN_RFU_1 = 0x6,
|
||||
QUERY_DESC_IDN_GEOMETRY = 0x7,
|
||||
QUERY_DESC_IDN_POWER = 0x8,
|
||||
QUERY_DESC_IDN_HEALTH = 0x9,
|
||||
QUERY_DESC_IDN_MAX,
|
||||
};
|
||||
|
||||
#define ufs_paddr_t uint32_t
|
||||
|
||||
struct ufs_pa_layer_attr {
|
||||
uint32_t gear_rx;
|
||||
uint32_t gear_tx;
|
||||
uint32_t lane_rx;
|
||||
uint32_t lane_tx;
|
||||
uint32_t pwr_rx;
|
||||
uint32_t pwr_tx;
|
||||
uint32_t hs_rate;
|
||||
};
|
||||
|
||||
#define UFS_MAX_CMD_DATA_SIZE (64)
|
||||
|
||||
enum dev_cmd_type {
|
||||
DEV_CMD_TYPE_NOP = 0x0,
|
||||
DEV_CMD_TYPE_QUERY = 0x1,
|
||||
};
|
||||
|
||||
#define MAX_PRODUCT_ID_LEN (16)
|
||||
#define MAX_PRODUCT_REVISION_LEVEL_LEN (4)
|
||||
#define MAX_SERAL_NUMBER_LEN (64) /* spec (126*2), 64 because code size */
|
||||
|
||||
struct ufs_device_info {
|
||||
uint16_t wmanufacturerid; // from Device Descriptor
|
||||
uint8_t num_active_lu; // from Device Descriptor
|
||||
uint16_t ufs_ver; // from Device Descriptor
|
||||
uint8_t bootable;
|
||||
char product_id[MAX_PRODUCT_ID_LEN + 1];
|
||||
char product_revision_level[MAX_PRODUCT_REVISION_LEVEL_LEN + 1];
|
||||
char serial_number[MAX_SERAL_NUMBER_LEN * 2 + 1]; /* 1 byte need 2 char(ex.FF) + 1 end */
|
||||
uint8_t serial_number_len;
|
||||
uint8_t ud0_base_offset;
|
||||
uint8_t ud_config_len;
|
||||
uint8_t hpb_support;
|
||||
uint16_t hpb_ver;
|
||||
uint8_t tw_support;
|
||||
uint8_t tw_red;
|
||||
uint8_t tw_type;
|
||||
uint16_t tw_ver;
|
||||
uint32_t wb_buf_au;
|
||||
uint8_t pre_eol_info;
|
||||
uint8_t life_time_est_a;
|
||||
uint8_t life_time_est_b;
|
||||
};
|
||||
struct ufs_custom_info {
|
||||
uint32_t custom_flag;
|
||||
uint32_t force_provision; /* default:0, force:1, skip:2 */
|
||||
uint32_t tw_size_gb;
|
||||
uint32_t tw_no_red;
|
||||
uint32_t hpb_size_gb;
|
||||
};
|
||||
|
||||
struct ufs_pwr_mode_info {
|
||||
bool is_valid;
|
||||
struct ufs_pa_layer_attr info;
|
||||
};
|
||||
|
||||
struct ufs_unit_desc_cfg_param {
|
||||
uint8_t b_lu_enable;
|
||||
uint8_t b_boot_lun_id;
|
||||
uint8_t b_lu_write_protect;
|
||||
uint8_t b_memory_type;
|
||||
uint8_t d_num_alloc_units[4];
|
||||
uint8_t b_data_reliability;
|
||||
uint8_t b_logical_block_size;
|
||||
uint8_t b_provisioning_type;
|
||||
uint8_t w_context_capabilities[2];
|
||||
uint8_t reserved[3];
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
UFS_LU_0 = 0
|
||||
,UFS_LU_1 = 1
|
||||
,UFS_LU_2 = 2
|
||||
,UFS_LU_3 = 3
|
||||
,UFS_LU_INTERNAL_CNT = 3
|
||||
} ufs_logical_unit_internal;
|
||||
|
||||
/**
|
||||
* struct utp_upiu_query - upiu request buffer structure for
|
||||
* query request.
|
||||
* @opcode: command to perform B-0
|
||||
* @idn: a value that indicates the particular type of data B-1
|
||||
* @index: Index to further identify data B-2
|
||||
* @selector: Index to further identify data B-3
|
||||
* @reserved_osf: spec reserved field B-4,5
|
||||
* @length: number of descriptor bytes to read/write B-6,7
|
||||
* @value: Attribute value to be written DW-5
|
||||
* @reserved: spec reserved DW-6,7
|
||||
*/
|
||||
struct utp_upiu_query {
|
||||
uint8_t opcode;
|
||||
uint8_t idn;
|
||||
uint8_t index;
|
||||
uint8_t selector;
|
||||
uint16_t reserved_osf;
|
||||
uint16_t length;
|
||||
uint32_t value;
|
||||
uint32_t reserved[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ufs_query_req - parameters for building a query request
|
||||
* @query_func: UPIU header query function
|
||||
* @upiu_req: the query request data
|
||||
*/
|
||||
struct ufs_query_req {
|
||||
uint8_t query_func;
|
||||
struct utp_upiu_query upiu_req;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ufs_query_resp - UPIU QUERY
|
||||
* @response: device response code
|
||||
* @upiu_res: query response data
|
||||
*/
|
||||
struct ufs_query_res {
|
||||
uint8_t response;
|
||||
struct utp_upiu_query upiu_res;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ufs_query - holds relevent data structures for query request
|
||||
* @request: request upiu and function
|
||||
* @descriptor: buffer for sending/receiving descriptor
|
||||
* @response: response upiu and response
|
||||
*/
|
||||
struct ufs_query {
|
||||
struct ufs_query_req request;
|
||||
uint8_t *descriptor;
|
||||
struct ufs_query_res response;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ufs_dev_cmd - all assosiated fields with device management commands
|
||||
* @type: device management command type - Query, NOP OUT
|
||||
* @lock: lock to allow one command at a time
|
||||
* @complete: internal commands completion
|
||||
* @tag_wq: wait queue until free command slot is available
|
||||
*/
|
||||
struct ufs_dev_cmd {
|
||||
enum dev_cmd_type type;
|
||||
struct ufs_query query;
|
||||
};
|
||||
|
||||
struct ufs_hba {
|
||||
void *hci_base;
|
||||
void *pericfg_base;
|
||||
void *mphy_base;
|
||||
int nutrs;
|
||||
//int nutmrs;
|
||||
|
||||
/* Virtual memory reference */
|
||||
struct utp_transfer_cmd_desc *ucdl_base_addr;
|
||||
struct utp_transfer_req_desc *utrdl_base_addr;
|
||||
//struct utp_task_req_desc *utmrdl_base_addr;
|
||||
//void * sense_buf_base_addr[UFS_AIO_MAX_NUTRS];
|
||||
|
||||
/* DMA memory reference */
|
||||
ufs_paddr_t ucdl_dma_addr;
|
||||
ufs_paddr_t utrdl_dma_addr;
|
||||
//ufs_paddr_t utmrdl_dma_addr;
|
||||
//ufs_paddr_t sense_buf_dma_addr[UFS_AIO_MAX_NUTRS];
|
||||
|
||||
unsigned int hci_quirks;
|
||||
unsigned int dev_quirks;
|
||||
|
||||
struct uic_command *active_uic_cmd;
|
||||
struct ufs_pa_layer_attr pwr_info;
|
||||
|
||||
struct ufshcd_lrb *lrb;
|
||||
unsigned long lrb_in_use;
|
||||
|
||||
struct ufs_device_info dev_info;
|
||||
struct ufs_custom_info custom_info;
|
||||
|
||||
uint8_t active_tr_tag;
|
||||
uint8_t mode;
|
||||
uint8_t unit_desc_cfg_param_valid;
|
||||
//uint8_t active_tm_tag;
|
||||
int active_lun;
|
||||
|
||||
unsigned long outstanding_reqs;
|
||||
|
||||
struct ufs_pwr_mode_info max_pwr_info;
|
||||
|
||||
/* Device management request data */
|
||||
struct ufs_dev_cmd dev_cmd;
|
||||
|
||||
int (* blk_read)(struct ufs_hba * hba, uint32_t lun, uint32_t blk_start, uint32_t blk_cnt, unsigned long * buf);
|
||||
int (* blk_write)(struct ufs_hba * hba, uint32_t lun, uint32_t blk_start, uint32_t blk_cnt, unsigned long * buf);
|
||||
int (* blk_erase)(struct ufs_hba * hba, uint32_t lun, uint32_t blk_start, uint32_t blk_cnt);
|
||||
int (* nopin_nopout)(struct ufs_hba * hba);
|
||||
int (* query_flag)(struct ufs_hba *hba, enum query_opcode opcode, enum flag_idn idn, bool *flag_res);
|
||||
int (* query_attr)(struct ufs_hba *hba, enum query_opcode opcode, enum attr_idn idn, uint8_t index, uint8_t selector, uint32_t *attr_val);
|
||||
int (* read_descriptor)(struct ufs_hba * hba, enum desc_idn desc_id, int desc_index, uint8_t selector, uint8_t *buf, uint32_t size);
|
||||
int (* write_descriptor)(struct ufs_hba * hba, enum desc_idn desc_id, int desc_index, uint8_t selector, uint8_t *buf, uint32_t size);
|
||||
int (* dme_get)(struct ufs_hba *hba, uint32_t attr_sel, uint32_t *mib_val);
|
||||
int (* dme_peer_get)(struct ufs_hba *hba, uint32_t attr_sel, uint32_t *mib_val);
|
||||
int (* dme_set)(struct ufs_hba *hba, uint32_t attr_sel, uint32_t mib_val);
|
||||
int (* dme_peer_set)(struct ufs_hba *hba, uint32_t attr_sel, uint32_t mib_val);
|
||||
int (* ffu_write)(struct ufs_hba * hba, unsigned long * buf, uint32_t buf_size);
|
||||
|
||||
// unit descriptor configurable parameters (in Configuration Descriptor)
|
||||
struct ufs_unit_desc_cfg_param unit_desc_cfg_param[UFS_UPIU_MAX_GENERAL_LUN];
|
||||
|
||||
uint32_t drv_status;
|
||||
uint32_t irq;
|
||||
};
|
||||
|
||||
void ufshcd_put_tag(struct ufs_hba *hba, int tag);
|
||||
void cmd_scsi_security_protocol_out(struct ufs_aio_scsi_cmd *cmd, int tag);
|
||||
void cmd_scsi_security_protocol_in(struct ufs_aio_scsi_cmd *cmd, int tag);
|
||||
int rpmb_key_generate(struct rpmb_data_frame frame, uint8_t* rpmb_key);
|
||||
|
||||
#endif //DA_X_RPMB_H
|
219
src/da_x/crypto/dxcc.c
Normal file
219
src/da_x/crypto/dxcc.c
Normal file
|
@ -0,0 +1,219 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
#include "dxcc.h"
|
||||
|
||||
void SaSi_SB_AddDescSequence(volatile uint32_t *result, HwDesc_s *desc)
|
||||
{
|
||||
while ( (result[DX_DSCRPTR_QUEUE0_CONTENT_REG_OFFSET/4] & 0x3FF) == 0 )
|
||||
;
|
||||
result[DX_DSCRPTR_QUEUE0_WORD0_REG_OFFSET/4] = (volatile uint32_t)desc->word[0];
|
||||
result[DX_DSCRPTR_QUEUE0_WORD1_REG_OFFSET/4] = (volatile uint32_t)desc->word[1];
|
||||
result[DX_DSCRPTR_QUEUE0_WORD2_REG_OFFSET/4] = (volatile uint32_t)desc->word[2];
|
||||
result[DX_DSCRPTR_QUEUE0_WORD3_REG_OFFSET/4] = (volatile uint32_t)desc->word[3];
|
||||
result[DX_DSCRPTR_QUEUE0_WORD4_REG_OFFSET/4] = (volatile uint32_t)desc->word[4];
|
||||
result[DX_DSCRPTR_QUEUE0_WORD5_REG_OFFSET/4] = (volatile uint32_t)desc->word[5];
|
||||
}
|
||||
|
||||
void SaSi_PalDmaMap(uint32_t offset, volatile uint64_t* dst)
|
||||
{
|
||||
*dst=offset;
|
||||
}
|
||||
|
||||
int SB_ReadFlag(volatile uint32_t* base)
|
||||
{
|
||||
volatile uint32_t res=0;
|
||||
do {
|
||||
res=base[0xBA0/4];
|
||||
}
|
||||
while (!res);
|
||||
return res;
|
||||
}
|
||||
|
||||
void SaSi_PalDmaUnMap(volatile uint64_t* dst)
|
||||
{
|
||||
(void)dst;
|
||||
}
|
||||
|
||||
void SB_HalInit(volatile uint32_t* base)
|
||||
{
|
||||
base[DX_HOST_ICR_REG_OFFSET/4]=(volatile uint32_t)4;
|
||||
}
|
||||
|
||||
int SB_CryptoWait(volatile uint32_t* base)
|
||||
{
|
||||
volatile uint32_t val;
|
||||
do {
|
||||
val=(volatile uint32_t)base[DX_HOST_IRR_REG_OFFSET/4];
|
||||
} while (!val);
|
||||
return val;
|
||||
}
|
||||
|
||||
int SB_HalWaitDescCompletion(volatile uint32_t* base)
|
||||
{
|
||||
struct HwDesc desc;
|
||||
SB_HalInit(base);
|
||||
uint32_t outv = 0;
|
||||
volatile uint64_t out = 0;
|
||||
SaSi_PalDmaMap((uint32_t)&outv, &out);
|
||||
desc.word[0] = 0;
|
||||
desc.word[1] = 0x8000011;
|
||||
desc.word[2] = out;
|
||||
desc.word[5] = ((out>>32)&0xFFFFFFFF) << 16;
|
||||
desc.word[3] = 0x8000012;
|
||||
desc.word[4] = 0x100;
|
||||
SaSi_SB_AddDescSequence(base, &desc);
|
||||
while ( (SB_CryptoWait(base) & 4) == 0 );
|
||||
volatile uint32_t val=0;
|
||||
do
|
||||
{
|
||||
val = SB_ReadFlag(base);
|
||||
} while (!val);
|
||||
if ( val == 1 )
|
||||
{
|
||||
SB_HalInit(base);
|
||||
SaSi_PalDmaUnMap(&out);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SaSi_PalDmaUnMap(&out);
|
||||
return 0xF6000001;
|
||||
}
|
||||
}
|
||||
|
||||
void write_reg(volatile uint32_t addr, volatile uint32_t value)
|
||||
{
|
||||
*(volatile uint32_t*)addr=value;
|
||||
}
|
||||
|
||||
int SBROM_AesCmacDriver(volatile uint32_t *base,
|
||||
uint32_t hwmode,
|
||||
uint64_t key,
|
||||
uint64_t buf,
|
||||
int bufferlen,
|
||||
uint64_t out)
|
||||
{
|
||||
struct HwDesc desc;
|
||||
int keylen = 0;
|
||||
if ( hwmode == 1 )
|
||||
{
|
||||
if (((base[DX_HOST_SEP_HOST_GPR4_REG_OFFSET/4])&2)!=0)
|
||||
{
|
||||
keylen = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
keylen = 16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
keylen = 16;
|
||||
}
|
||||
SB_HalInit(base);
|
||||
volatile uint32_t kval = (keylen << 19) - 0x800000;
|
||||
desc.word[1] = 0x8000041;
|
||||
desc.word[4] = kval | 0x1001C20;
|
||||
desc.word[0] = 0;
|
||||
desc.word[2] = 0;
|
||||
desc.word[3] = 0;
|
||||
desc.word[5] = 0;
|
||||
SaSi_SB_AddDescSequence(base, &desc);
|
||||
|
||||
desc.word[0] = 0;
|
||||
desc.word[1] = 0;
|
||||
desc.word[2] = 0;
|
||||
desc.word[3] = 0;
|
||||
desc.word[4] = 0;
|
||||
|
||||
if ( !hwmode )
|
||||
{
|
||||
desc.word[0] = (uint32_t)key;
|
||||
desc.word[5] = (uint16_t)(key>>32);
|
||||
desc.word[1] = 0x42;
|
||||
}
|
||||
desc.word[4] = kval | ((hwmode&3)<<15) | (((hwmode>>2)&3)<<20) | 0x4001C20;
|
||||
SaSi_SB_AddDescSequence(base, &desc);
|
||||
|
||||
desc.word[2] = 0;
|
||||
desc.word[0] = (uint32_t)buf;
|
||||
desc.word[5] = (uint16_t)(buf>>32);
|
||||
desc.word[3] = 0;
|
||||
desc.word[1] = (4 * (bufferlen & 0xFFFFFF)) | 2;
|
||||
desc.word[4] = 1;
|
||||
SaSi_SB_AddDescSequence(base, &desc);
|
||||
|
||||
if (hwmode!=2)
|
||||
{
|
||||
desc.word[5] = ((uint16_t)(out>>32)) << 16;
|
||||
desc.word[0] = 0;
|
||||
desc.word[4] = 0x8001C26;
|
||||
desc.word[1] = 0;
|
||||
desc.word[2] = (uint32_t)out;
|
||||
desc.word[3] = 0x42;
|
||||
SaSi_SB_AddDescSequence(base, &desc);
|
||||
}
|
||||
|
||||
return SB_HalWaitDescCompletion(base);
|
||||
}
|
||||
|
||||
int SBROM_AesCMac(volatile uint32_t* base, int hwmode, uint8_t* buffer, int bufferlen, uint8_t* outbuf)
|
||||
{
|
||||
int ret;
|
||||
uint64_t iv=0;
|
||||
/*if (val0)
|
||||
SaSi_PalDmaMap((uint32_t)&val0, &iv);
|
||||
if (buffer)
|
||||
SaSi_PalDmaMap((uint32_t)&buffer, &buf);
|
||||
if (outbuf)
|
||||
SaSi_PalDmaMap((uint32_t)&outbuf, &out);
|
||||
*/
|
||||
|
||||
ret = SBROM_AesCmacDriver(base, hwmode, iv, (uint32_t)buffer, bufferlen, (uint32_t)outbuf);
|
||||
/*if (val0)
|
||||
SaSi_PalDmaUnMap(&iv);
|
||||
if (buffer)
|
||||
SaSi_PalDmaUnMap(&buf);
|
||||
if (outbuf)
|
||||
SaSi_PalDmaUnMap(&out);
|
||||
*/
|
||||
return ret;
|
||||
}
|
||||
int dxcc(volatile uint32_t* base, int hwmode, uint8_t* key, int keylen, uint8_t* seed, int seedlen, uint8_t* outbuf, int derivelen)
|
||||
{
|
||||
uint8_t* buffer=(uint8_t*)0x200d10;
|
||||
uint8_t* tmp=(uint8_t*)0x200d00;
|
||||
uint32_t i;
|
||||
uint32_t pos=0;
|
||||
int ret;
|
||||
if (!hwmode)
|
||||
return 0xF2000002;
|
||||
if (!key && (keylen || keylen > 0x20))
|
||||
return 0xF2000003;
|
||||
if (!seed && (seedlen || seedlen > 0x20))
|
||||
return 0xF2000003;
|
||||
memset(buffer,0,0x43);
|
||||
buffer[pos++]=1;
|
||||
if (key)
|
||||
{
|
||||
memcpy(&buffer[pos++], key, keylen);
|
||||
pos += keylen;
|
||||
}
|
||||
buffer[pos]=0;
|
||||
if (seed)
|
||||
{
|
||||
memcpy(&buffer[pos], seed, seedlen);
|
||||
pos += seedlen;
|
||||
}
|
||||
buffer[pos]=(8*derivelen)&0xFF;
|
||||
for (i=0;i<((uint32_t)derivelen+15)>>4;i++)
|
||||
{
|
||||
buffer[0] = i+1;
|
||||
ret = SBROM_AesCMac(base,hwmode,buffer,keylen+seedlen+3,tmp);
|
||||
memcpy(outbuf+(16*i),tmp,0x10);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
26
src/da_x/crypto/dxcc.h
Normal file
26
src/da_x/crypto/dxcc.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
#ifndef DXCC_H
|
||||
#define DXCC_H
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../common/libc.h"
|
||||
#define HW_DESC_SIZE_WORDS 6
|
||||
typedef struct HwDesc {
|
||||
uint32_t word[HW_DESC_SIZE_WORDS];
|
||||
} HwDesc_s;
|
||||
|
||||
#define DX_DSCRPTR_QUEUE0_WORD0_REG_OFFSET 0xE80
|
||||
#define DX_DSCRPTR_QUEUE0_WORD1_REG_OFFSET 0xE84
|
||||
#define DX_DSCRPTR_QUEUE0_WORD2_REG_OFFSET 0xE88
|
||||
#define DX_DSCRPTR_QUEUE0_WORD3_REG_OFFSET 0xE8C
|
||||
#define DX_DSCRPTR_QUEUE0_WORD4_REG_OFFSET 0xE90
|
||||
#define DX_DSCRPTR_QUEUE0_WORD5_REG_OFFSET 0xE94
|
||||
#define DX_DSCRPTR_QUEUE0_CONTENT_REG_OFFSET 0xE9C
|
||||
#define DX_HOST_IRR_REG_OFFSET 0xA00
|
||||
#define DX_HOST_ICR_REG_OFFSET 0xA08
|
||||
#define DX_HOST_SEP_HOST_GPR4_REG_OFFSET 0xAA0
|
||||
|
||||
int dxcc(volatile uint32_t* base, int hwmode, uint8_t* key, int keylen, uint8_t* seed, int seedlen, uint8_t* outbuf, int derivelen);
|
||||
#endif
|
|
@ -1,3 +1,5 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
|
||||
#ifndef __ROTATE_DEFS_H
|
76
src/da_x/crypto/sej.c
Normal file
76
src/da_x/crypto/sej.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
#include "sej.h"
|
||||
|
||||
uint32_t g_UnqKey_IV[8] = {0x6786CFBD, 0x44B7F1E0, 0x1544B07B, 0x53A28EB3, 0xD7AB8AA2, 0xB9E30E7E, 0x172156E0, 0x3064C973};
|
||||
|
||||
volatile uint32_t hacc_base=0x1000a000;
|
||||
|
||||
int32_t toSigned32(uint32_t n){
|
||||
n = n & 0xffffffff;
|
||||
return n | (-(n & 0x80000000));
|
||||
}
|
||||
|
||||
static uint32_t get_world_clock_value(){
|
||||
return INREG32(0x10017008);
|
||||
}
|
||||
|
||||
int32_t check_timeout(const uint32_t clockvalue, int32_t timeout){
|
||||
uint32_t tmp = -clockvalue;
|
||||
const uint32_t curtime = get_world_clock_value();
|
||||
if (curtime < clockvalue){
|
||||
tmp = ~clockvalue;
|
||||
}
|
||||
return tmp + get_world_clock_value() >= ((uint32_t)timeout)*1000*13;
|
||||
}
|
||||
|
||||
void HACC_V3_Terminate(void) {
|
||||
OUTREG32(HACC_ACON2,HACC_AES_CLR);
|
||||
for (int32_t i = 0; i < 8; i++){
|
||||
OUTREG32(HACC_AKEY0 + (4 * i),0);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t sej_set_otp(uint32_t* otp){
|
||||
for (int32_t i = 0; i < 8; i++) {
|
||||
OUTREG32(HACC_SW_OTP0 + (4 * i),otp[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t HACC_V3_Run(volatile uint32_t *p_src, uint32_t src_len, volatile uint32_t *p_dst, bool legacy, uint8_t attr, uint8_t sej_param){
|
||||
if (src_len>0x40){
|
||||
return 0x9999;
|
||||
}
|
||||
if (legacy){
|
||||
if ((attr&8)!=0&&(sej_param&2)!=0) {
|
||||
SETREG32(HACC_ACONK, HACC_AES_R2K);
|
||||
} else {
|
||||
OUTREG32(HACC_ACONK, INREG32(HACC_ACONK)&0xFFFFFEFF);
|
||||
}
|
||||
}
|
||||
for (int32_t i = 0; i < (int)(src_len / 4); i += 4) {
|
||||
for (int32_t x = 0; x < 4; x++) {
|
||||
OUTREG32(HACC_ASRC0 + (4 * x), p_src[x+i]);
|
||||
}
|
||||
OUTREG32(HACC_ACON2, HACC_AES_START);
|
||||
const uint32_t clockvalue = get_world_clock_value();
|
||||
while ((INREG32(HACC_ACON2) & HACC_AES_RDY) == 0) {
|
||||
if (check_timeout(clockvalue, 200)) {
|
||||
return 0x4006;
|
||||
}
|
||||
}
|
||||
for (int32_t x = 0; x < 4; x++) {
|
||||
p_dst[x+i]= INREG32(HACC_AOUT0 + ((4*x)));
|
||||
}
|
||||
}
|
||||
if (legacy){
|
||||
if ((attr&8)!=0 && (sej_param&2)==0){
|
||||
for (int32_t x = 0; x < 4; x++) {
|
||||
OUTREG32(HACC_AKEY0 + (4 * x),INREG32(HACC_AOUT0 + (4 * x))^INREG32(HACC_AKEY0 + (4 * x)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
164
src/da_x/crypto/sej.h
Normal file
164
src/da_x/crypto/sej.h
Normal file
|
@ -0,0 +1,164 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
#ifndef SEJ_H
|
||||
#define SEJ_H
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
extern volatile uint32_t hacc_base;
|
||||
|
||||
#define HACC_CG (0x1 << 10)
|
||||
|
||||
#define HACC_AES_TEST_SRC (0x02000000)
|
||||
#define HACC_AES_TEST_TMP (0x02100000)
|
||||
#define HACC_AES_TEST_DST (0x02200000)
|
||||
|
||||
#define HACC_CFG_0 (0x5a5a3257) /* CHECKME */
|
||||
#define HACC_CFG_1 (0x66975412) /* CHECKME */
|
||||
#define HACC_CFG_2 (0x66975412) /* CHECKME */
|
||||
#define HACC_CFG_3 (0x5a5a3257) /* CHECKME */
|
||||
|
||||
#define HACC_CON (hacc_base+0x0000)
|
||||
#define HACC_ACON (hacc_base+0x0004)
|
||||
#define HACC_ACON2 (hacc_base+0x0008)
|
||||
#define HACC_ACONK (hacc_base+0x000C)
|
||||
#define HACC_ASRC0 (hacc_base+0x0010)
|
||||
#define HACC_ASRC1 (hacc_base+0x0014)
|
||||
#define HACC_ASRC2 (hacc_base+0x0018)
|
||||
#define HACC_ASRC3 (hacc_base+0x001C)
|
||||
#define HACC_AKEY0 (hacc_base+0x0020)
|
||||
#define HACC_AKEY1 (hacc_base+0x0024)
|
||||
#define HACC_AKEY2 (hacc_base+0x0028)
|
||||
#define HACC_AKEY3 (hacc_base+0x002C)
|
||||
#define HACC_AKEY4 (hacc_base+0x0030)
|
||||
#define HACC_AKEY5 (hacc_base+0x0034)
|
||||
#define HACC_AKEY6 (hacc_base+0x0038)
|
||||
#define HACC_AKEY7 (hacc_base+0x003C)
|
||||
#define HACC_ACFG0 (hacc_base+0x0040)
|
||||
#define HACC_ACFG1 (hacc_base+0x0044)
|
||||
#define HACC_ACFG2 (hacc_base+0x0048)
|
||||
#define HACC_ACFG3 (hacc_base+0x004c)
|
||||
#define HACC_AOUT0 (hacc_base+0x0050)
|
||||
#define HACC_AOUT1 (hacc_base+0x0054)
|
||||
#define HACC_AOUT2 (hacc_base+0x0058)
|
||||
#define HACC_AOUT3 (hacc_base+0x005C)
|
||||
#define HACC_SW_OTP0 (hacc_base+0x0060)
|
||||
#define HACC_SW_OTP1 (hacc_base+0x0064)
|
||||
#define HACC_SW_OTP2 (hacc_base+0x0068)
|
||||
#define HACC_SW_OTP3 (hacc_base+0x006c)
|
||||
#define HACC_SW_OTP4 (hacc_base+0x0070)
|
||||
#define HACC_SW_OTP5 (hacc_base+0x0074)
|
||||
#define HACC_SW_OTP6 (hacc_base+0x0078)
|
||||
#define HACC_SW_OTP7 (hacc_base+0x007c)
|
||||
#define HACC_SECINIT0 (hacc_base+0x0080)
|
||||
#define HACC_SECINIT1 (hacc_base+0x0084)
|
||||
#define HACC_SECINIT2 (hacc_base+0x0088)
|
||||
#define HACC_MKJ (hacc_base+0x00a0)
|
||||
#define HACC_UNK (hacc_base+0x00bc)
|
||||
|
||||
/* AES */
|
||||
#define HACC_AES_DEC 0x00000000
|
||||
#define HACC_AES_ENC 0x00000001
|
||||
#define HACC_AES_MODE_MASK 0x00000002
|
||||
#define HACC_AES_ECB 0x00000000
|
||||
#define HACC_AES_CBC 0x00000002
|
||||
#define HACC_AES_TYPE_MASK 0x00000030
|
||||
#define HACC_AES_128 0x00000000
|
||||
#define HACC_AES_192 0x00000010
|
||||
#define HACC_AES_256 0x00000020
|
||||
#define HACC_AES_CHG_BO_MASK 0x00001000
|
||||
#define HACC_AES_CHG_BO_OFF 0x00000000
|
||||
#define HACC_AES_CHG_BO_ON 0x00001000
|
||||
#define HACC_AES_START 0x00000001
|
||||
#define HACC_AES_CLR 0x00000002
|
||||
#define HACC_AES_RDY 0x00008000
|
||||
|
||||
/* AES key relevant */
|
||||
#define HACC_AES_BK2C 0x00000010
|
||||
#define HACC_AES_R2K 0x00000100
|
||||
|
||||
/* SECINIT magic */
|
||||
#define HACC_SECINIT0_MAGIC 0xAE0ACBEA
|
||||
#define HACC_SECINIT1_MAGIC 0xCD957018
|
||||
#define HACC_SECINIT2_MAGIC 0x46293911
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* CONSTANT DEFINITIONS
|
||||
******************************************************************************/
|
||||
#define HACC_AES_MAX_KEY_SZ (32)
|
||||
#define AES_CFG_SZ (16)
|
||||
#define AES_BLK_SZ (16)
|
||||
#define HACC_HW_KEY_SZ (16)
|
||||
#define _CRYPTO_SEED_LEN (16)
|
||||
|
||||
/******************************************************************************
|
||||
* TYPE DEFINITIONS
|
||||
******************************************************************************/
|
||||
typedef enum {
|
||||
AES_ECB_MODE,
|
||||
AES_CBC_MODE
|
||||
} AES_MODE;
|
||||
|
||||
typedef enum {
|
||||
AES_DEC,
|
||||
AES_ENC
|
||||
} AES_OPS;
|
||||
|
||||
typedef enum {
|
||||
AES_KEY_128 = 16,
|
||||
AES_KEY_192 = 24,
|
||||
AES_KEY_256 = 32
|
||||
} AES_KEY_SZ;
|
||||
|
||||
typedef enum {
|
||||
AES_SW_KEY,
|
||||
AES_HW_KEY,
|
||||
AES_HW_WRAP_KEY
|
||||
} AES_KEY_ID;
|
||||
|
||||
typedef struct {
|
||||
unsigned char config[AES_CFG_SZ];
|
||||
} AES_CFG;
|
||||
|
||||
typedef struct {
|
||||
unsigned int size;
|
||||
unsigned char seed[HACC_AES_MAX_KEY_SZ];
|
||||
} AES_KEY_SEED;
|
||||
|
||||
struct hacc_context {
|
||||
AES_CFG cfg;
|
||||
unsigned int blk_sz;
|
||||
unsigned char sw_key[HACC_AES_MAX_KEY_SZ];
|
||||
unsigned char hw_key[HACC_AES_MAX_KEY_SZ];
|
||||
};
|
||||
|
||||
enum cryptmode_t {
|
||||
SW_ENCRYPTED = 0,
|
||||
HW_ENCRYPTED = 1,
|
||||
HW_ENCRYPTED_5G = 2,
|
||||
UNLOCK = 3
|
||||
};
|
||||
|
||||
struct SymKey {
|
||||
uint32_t* key;
|
||||
uint8_t key_len;
|
||||
uint8_t mode;
|
||||
uint32_t* iv;
|
||||
uint8_t iv_len;
|
||||
};
|
||||
|
||||
#define READ_REGISTER_UINT32(reg) \
|
||||
(*(volatile unsigned int * const)(reg))
|
||||
|
||||
#define WRITE_REGISTER_UINT32(reg, val) \
|
||||
((*(volatile unsigned int * const)(reg)) = (val))
|
||||
|
||||
#define INREG32(x) READ_REGISTER_UINT32((unsigned int *)((void *)(x)))
|
||||
#define OUTREG32(x, y) WRITE_REGISTER_UINT32((unsigned int *)((void *)(x)), (unsigned int)(y))
|
||||
#define SETREG32(x, y) OUTREG32(x, INREG32(x)|(y))
|
||||
#define CLRREG32(x, y) OUTREG32(x, INREG32(x)&~(y))
|
||||
#define MASKREG32(x, y, z) OUTREG32(x, (INREG32(x)&~(y))|(z))
|
||||
|
||||
#endif
|
182
src/da_x/da_x.c
Executable file
182
src/da_x/da_x.c
Executable file
|
@ -0,0 +1,182 @@
|
|||
// Copyright 2024 (c) B.Kerler
|
||||
// Use of this source code is governed by a GPLv3 license, see LICENSE.txt.
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common/defs.h"
|
||||
#include "common/libc.h"
|
||||
#include "crypto/sej.h"
|
||||
#include "common/flash_handler.h"
|
||||
|
||||
static uint32_t storage=STORAGE_EMMC;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int (*read)(uint8_t* buffer, uint32_t* length);
|
||||
int (*write)(uint8_t* buffer, uint32_t length);
|
||||
int (*log_to_pc)(const uint8_t* buffer, uint32_t length);
|
||||
int (*log_to_uart)(const uint8_t* buffer, uint32_t length);
|
||||
} com_channel_struct;
|
||||
|
||||
typedef int (*HHANDLE)(com_channel_struct*);
|
||||
extern void apmcu_dcache_clean_invalidate();
|
||||
extern void apmcu_dcache_invalidate();
|
||||
extern int cache_init(int param);
|
||||
extern int cache_close(int param);
|
||||
|
||||
int (*register_major_command)(uint32_t /*ctrl_code*/, HHANDLE /*handle*/)=(const void*)0x11111111;
|
||||
uint32_t efuse_addr=0x88888888;
|
||||
|
||||
/* -------------------------------- Commands --------------------------------------- */
|
||||
|
||||
int cmd_readmem(com_channel_struct *channel){
|
||||
volatile uint64_t addr=0;
|
||||
uint8_t buffer[0x20000]={0};
|
||||
uint32_t length=0;
|
||||
uint32_t cmdlen=8;
|
||||
channel->read((uint8_t*)&addr,&cmdlen);
|
||||
cmdlen=4;
|
||||
channel->read((uint8_t*)&length,&cmdlen);
|
||||
if (length>0x20000) length=0x20000;
|
||||
memcpy(buffer,(volatile uint64_t*)addr,length);
|
||||
return channel->write((uint8_t *)buffer,length);
|
||||
}
|
||||
|
||||
int cmd_readregister(com_channel_struct *channel){
|
||||
volatile uint32_t addr=0;
|
||||
volatile uint32_t dword=0;
|
||||
uint32_t cmdlen=4;
|
||||
channel->read((uint8_t*)&addr,&cmdlen);
|
||||
cmdlen=4;
|
||||
dword=WRAP_RD32(addr);
|
||||
//dword=*(volatile uint32_t*)addr;
|
||||
return channel->write((uint8_t *)&dword,cmdlen);
|
||||
}
|
||||
|
||||
int cmd_writemem(com_channel_struct *channel){
|
||||
volatile uint64_t addr=0;
|
||||
uint32_t length=0;
|
||||
uint32_t cmdlen=8;
|
||||
channel->read((uint8_t*)&addr,&cmdlen);
|
||||
cmdlen=4;
|
||||
channel->read((uint8_t*)&length,&cmdlen);
|
||||
return channel->read((uint8_t *)addr,&length);
|
||||
}
|
||||
|
||||
int cmd_writeregister(com_channel_struct *channel){
|
||||
volatile uint32_t addr=0;
|
||||
volatile uint32_t dword=0;
|
||||
uint32_t cmdlen=4;
|
||||
channel->read((uint8_t*)&addr,&cmdlen);
|
||||
cmdlen=4;
|
||||
channel->read((uint8_t*)&dword,&cmdlen);
|
||||
WRAP_WR32(addr,dword);
|
||||
//*(volatile uint32_t*)addr=dword;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_ack(com_channel_struct *channel){
|
||||
uint32_t ack=0xA1A2A3A4;
|
||||
return channel->write((uint8_t *)&ack,4);
|
||||
}
|
||||
|
||||
int cmd_rpmb_read(com_channel_struct *channel)
|
||||
{
|
||||
uint32_t size = 4;
|
||||
uint32_t address = 0;
|
||||
uint32_t sectors = 0;
|
||||
channel->read((uint8_t*)&address, &size);
|
||||
size=4;
|
||||
channel->read((uint8_t*)§ors, &size);
|
||||
uint8_t data[0x100]={0};
|
||||
int res = -1;
|
||||
for (uint32_t cursector=address;cursector<address+sectors;cursector++){
|
||||
if (storage==STORAGE_UFS) {
|
||||
res = ufs_read_frame(cursector,data);
|
||||
}
|
||||
else if (storage==STORAGE_EMMC) {
|
||||
res = mmc_read_frame(cursector,data);
|
||||
}
|
||||
if (res) {
|
||||
channel->write((uint8_t *)&res, 2);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
channel->write((uint8_t *)data, 0x100);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int cmd_rpmb_write(com_channel_struct *channel, const char* /*xml*/)
|
||||
{
|
||||
uint32_t size = 4;
|
||||
uint32_t address = 0;
|
||||
uint32_t sectors = 0;
|
||||
uint8_t data[0x100]={0};
|
||||
channel->read((uint8_t*)&address, &size);
|
||||
size=4;
|
||||
channel->read((uint8_t*)§ors, &size);
|
||||
int res = -1;
|
||||
size = 0x100;
|
||||
for (uint32_t cursector=address;cursector<address+sectors;cursector++) {
|
||||
channel->read(data, &size);
|
||||
if (storage == STORAGE_UFS) {
|
||||
res = ufs_write_frame(cursector, data);
|
||||
} else if (storage == STORAGE_EMMC) {
|
||||
res = mmc_write_frame(cursector, data);
|
||||
}
|
||||
channel->write((uint8_t*)&res, 2);
|
||||
if (res) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_rpmb_init(com_channel_struct *channel)
|
||||
{
|
||||
int res = -1;
|
||||
if (storage==STORAGE_UFS){
|
||||
res=ufs_init();
|
||||
} else if (storage==STORAGE_EMMC) {
|
||||
res=mmc_init();
|
||||
}
|
||||
channel->write((uint8_t*)&res, 2);
|
||||
if (!res) {
|
||||
channel->write((uint8_t*)get_current_rpmb_key(),0x20);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_rpmb_set_key(com_channel_struct *channel)
|
||||
{
|
||||
uint32_t size = 0x20;
|
||||
uint8_t rpmbkey[0x20];
|
||||
channel->read((uint8_t*)rpmbkey, &size);
|
||||
set_current_rpmb_key(rpmbkey);
|
||||
channel->write(get_current_rpmb_key(),0x20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_set_storage(com_channel_struct *channel)
|
||||
{
|
||||
uint32_t size = 0x4;
|
||||
channel->read((uint8_t*)&storage, &size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__ ((section(".text.main"))) int main() {
|
||||
cache_init(3);
|
||||
register_major_command(0xF0000,(void*)cmd_ack);
|
||||
register_major_command(0xF0001,(void*)cmd_readmem);
|
||||
register_major_command(0xF0002,(void*)cmd_readregister);
|
||||
register_major_command(0xF0003,(void*)cmd_writemem);
|
||||
register_major_command(0xF0004,(void*)cmd_writeregister);
|
||||
register_major_command(0xF0005,(void*)cmd_set_storage);
|
||||
register_major_command(0xF0006,(void*)cmd_rpmb_set_key);
|
||||
register_major_command(0xF0008,(void*)cmd_rpmb_init);
|
||||
register_major_command(0xF0009,(void*)cmd_rpmb_read);
|
||||
register_major_command(0xF000A,(void*)cmd_rpmb_write);
|
||||
cache_close(1);
|
||||
return 0;
|
||||
}
|
17
src/da_x/readme.build
Executable file
17
src/da_x/readme.build
Executable file
|
@ -0,0 +1,17 @@
|
|||
# Info
|
||||
- All binaries will end up in ../../payloads
|
||||
|
||||
# Requirements for compiling
|
||||
|
||||
For compiling, arm-linux-gnueabihf-gcc-12 is required.
|
||||
|
||||
```bash
|
||||
sudo apt install -y gcc-arm-linux* g++-arm-linux*
|
||||
```
|
||||
|
||||
# Compile
|
||||
|
||||
```bash
|
||||
./build.sh
|
||||
```
|
||||
|
0
src/stage1/__init__.py
Normal file
0
src/stage1/__init__.py
Normal file
0
src/stage1/emu_config/__init__.py
Executable file
0
src/stage1/emu_config/__init__.py
Executable file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue