mirror of
https://github.com/bkerler/mtkclient.git
synced 2024-11-14 19:25:05 -05:00
Merge pull request #696 from bkerler/newcrypto
Add full lock V3 support
This commit is contained in:
commit
305903c64d
10 changed files with 539 additions and 297 deletions
|
@ -2,6 +2,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# (c) B.Kerler 2018-2021 GPLv3 License
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from mtkclient.Library.utils import LogBase, logsetup
|
||||
from mtkclient.Library.hwcrypto_gcpu import GCpu
|
||||
|
@ -62,12 +63,17 @@ class hwcrypto(metaclass=LogBase):
|
|||
if mode == "cbc":
|
||||
return self.sej.hw_aes128_cbc_encrypt(buf=data, encrypt=True)
|
||||
elif mode == "sst":
|
||||
return self.sej.hw_aes128_sst_encrypt(buf=data, encrypt=True)
|
||||
data2=self.sej.generate_hw_meta(encrypt=True,data=data)
|
||||
data3=self.sej.SST_Secure_Algo_With_Level(buf=data, encrypt=True)
|
||||
print(data2.hex())
|
||||
print(data3.hex())
|
||||
sys.stdout.flush()
|
||||
return data3
|
||||
else:
|
||||
if mode == "cbc":
|
||||
return self.sej.hw_aes128_cbc_encrypt(buf=data, encrypt=False)
|
||||
elif mode == "sst":
|
||||
return self.sej.hw_aes128_sst_encrypt(buf=data, encrypt=False)
|
||||
return self.sej.SST_Secure_Algo_With_Level(buf=data, encrypt=False)
|
||||
if mode == "rpmb":
|
||||
return self.sej.generate_rpmb(meid=data, otp=otp)
|
||||
elif mode == "mtee":
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
import logging, os
|
||||
from struct import pack, unpack
|
||||
from mtkclient.Library.utils import LogBase
|
||||
from mtkclient.Library.cryptutils import cryptutils
|
||||
|
||||
CustomSeed = bytes.fromhex("00be13bb95e218b53d07a089cb935255294f70d4088f3930350bc636cc49c9025ece7a62c292853ef55b23a6ef7b7464c7f3f2a74ae919416d6b4d9c1d6809655dd82d43d65999cf041a386e1c0f1e58849d8ed09ef07e6a9f0d7d3b8dad6cbae4668a2fd53776c3d26f88b0bf617c8112b8b1a871d322d9513491e07396e1638090055f4b8b9aa2f4ec24ebaeb917e81f468783ea771b278614cd5779a3ca50df5cc5af0edc332e2b69b2b42154bcfffd0af13ce5a467abb7fb107fe794f928da44b6db7215aa53bd0398e3403126fad1f7de2a56edfe474c5a06f8dd9bc0b3422c45a9a132e64e48fcacf63f787560c4c89701d7c125118c20a5ee820c3a16")
|
||||
|
||||
CustomSeed = bytearray(b"12abcdef")
|
||||
|
||||
# SEJ = Security Engine for JTAG protection
|
||||
|
||||
|
@ -16,6 +18,13 @@ def bytes_to_dwords(buf):
|
|||
return res
|
||||
|
||||
|
||||
class symkey:
|
||||
key = None
|
||||
key_len = 0x10
|
||||
mode = 1
|
||||
iv = None
|
||||
|
||||
|
||||
AES_CBC_MODE = 1
|
||||
AES_SW_KEY = 0
|
||||
AES_HW_KEY = 1
|
||||
|
@ -260,95 +269,6 @@ class sej(metaclass=LogBase):
|
|||
# self.crypto_secure(1)
|
||||
return
|
||||
|
||||
def SEJ_Init_MTEE(self, encrypt=True, iv=None):
|
||||
if iv is None:
|
||||
iv = self.g_HACC_CFG_MTEE
|
||||
acon_setting = self.HACC_AES_CHG_BO_OFF | self.HACC_AES_CBC | self.HACC_AES_128
|
||||
if encrypt:
|
||||
acon_setting |= self.HACC_AES_ENC
|
||||
else:
|
||||
acon_setting |= self.HACC_AES_DEC
|
||||
|
||||
# clear key
|
||||
self.reg.HACC_AKEY0 = 0
|
||||
self.reg.HACC_AKEY1 = 0
|
||||
self.reg.HACC_AKEY2 = 0
|
||||
self.reg.HACC_AKEY3 = 0
|
||||
self.reg.HACC_AKEY4 = 0
|
||||
self.reg.HACC_AKEY5 = 0
|
||||
self.reg.HACC_AKEY6 = 0
|
||||
self.reg.HACC_AKEY7 = 0
|
||||
|
||||
self.reg.HACC_ACON2 = self.HACC_AES_CBC
|
||||
self.reg.HACC_ACONK = self.HACC_AES_BK2C
|
||||
self.reg.HACC_ACONK |= 0x100
|
||||
self.reg.HACC_ACON = self.HACC_AES_CLR
|
||||
|
||||
self.reg.HACC_ACFG0 = iv[0]
|
||||
self.reg.HACC_ACFG1 = iv[1]
|
||||
self.reg.HACC_ACFG2 = iv[2]
|
||||
self.reg.HACC_ACFG3 = iv[3]
|
||||
|
||||
for val in [[0x2d44bb70,0xa744d227,0xd0a9864b,0x83ffc244],
|
||||
[0x7ec8266b,0x43e80fb2,0x1a6348a,0x2067f9a0],
|
||||
[0x54536405,0xd546a6b1,0x1cc3ec3a,0xde377a83]]:
|
||||
self.reg.HACC_ASRC0 = val[0]
|
||||
self.reg.HACC_ASRC1 = val[1]
|
||||
self.reg.HACC_ASRC2 = val[2]
|
||||
self.reg.HACC_ASRC3 = val[3]
|
||||
self.reg.HACC_ACON2 = self.HACC_AES_START
|
||||
i = 0
|
||||
while i < 20:
|
||||
if self.reg.HACC_ACON2 & self.HACC_AES_RDY != 0:
|
||||
break
|
||||
i += 1
|
||||
if i == 20:
|
||||
self.error("SEJ Hardware seems not to be configured correctly. Results may be wrong.")
|
||||
|
||||
self.reg.HACC_ACON2 = self.HACC_AES_CBC
|
||||
self.reg.HACC_ACFG0 = iv[0]
|
||||
self.reg.HACC_ACFG1 = iv[1]
|
||||
self.reg.HACC_ACFG2 = iv[2]
|
||||
self.reg.HACC_ACFG3 = iv[3]
|
||||
self.reg.HACC_ACON = acon_setting
|
||||
self.reg.HACC_ACONK = 0x0
|
||||
|
||||
def SEJ_Init(self, encrypt=True, iv=None):
|
||||
if iv is None:
|
||||
iv = self.g_HACC_CFG_1
|
||||
acon_setting = self.HACC_AES_CHG_BO_OFF | self.HACC_AES_CBC | self.HACC_AES_128
|
||||
if encrypt:
|
||||
acon_setting |= self.HACC_AES_ENC
|
||||
else:
|
||||
acon_setting |= self.HACC_AES_DEC
|
||||
|
||||
# clear key
|
||||
self.reg.HACC_AKEY0 = 0
|
||||
self.reg.HACC_AKEY1 = 0
|
||||
self.reg.HACC_AKEY2 = 0
|
||||
self.reg.HACC_AKEY3 = 0
|
||||
self.reg.HACC_AKEY4 = 0
|
||||
self.reg.HACC_AKEY5 = 0
|
||||
self.reg.HACC_AKEY6 = 0
|
||||
self.reg.HACC_AKEY7 = 0
|
||||
self.reg.HACC_ACFG0 = iv[0] # g_AC_CFG
|
||||
self.reg.HACC_ACFG1 = iv[1]
|
||||
self.reg.HACC_ACFG2 = iv[2]
|
||||
self.reg.HACC_ACFG3 = iv[3]
|
||||
self.reg.HACC_UNK |= 2
|
||||
|
||||
# clear HACC_ASRC/HACC_ACFG/HACC_AOUT
|
||||
self.reg.HACC_ACON2 = 0x40000000 | self.HACC_AES_CLR
|
||||
|
||||
while True:
|
||||
if self.reg.HACC_ACON2 > 0x80000000:
|
||||
break
|
||||
|
||||
self.reg.HACC_UNK &= 0xFFFFFFFE
|
||||
self.reg.HACC_ACONK = self.HACC_AES_BK2C
|
||||
self.reg.HACC_ACON = acon_setting
|
||||
return acon_setting
|
||||
|
||||
def SEJ_Run(self, data):
|
||||
pdst = bytearray()
|
||||
psrc = bytes_to_dwords(data)
|
||||
|
@ -374,6 +294,155 @@ class sej(metaclass=LogBase):
|
|||
pos += 4
|
||||
return pdst
|
||||
|
||||
def SEJ_AES_HW_Init(self, attr, key: symkey, sej_param=3):
|
||||
# key.mode 0 = ECB
|
||||
# key.mode 1 = CBC
|
||||
if key.key is None:
|
||||
key.key = b""
|
||||
if attr << 31 and sej_param << 31:
|
||||
if key.key is None:
|
||||
return 0x6001
|
||||
if key.iv is None and key.mode == 1:
|
||||
return 0x6002
|
||||
|
||||
self.reg.HACC_SECINIT0 = 1
|
||||
if attr & 1 == 0 or sej_param & 1 != 0:
|
||||
acon_setting = self.HACC_AES_128
|
||||
elif len(key.key) == 0x18:
|
||||
acon_setting = self.HACC_AES_192
|
||||
elif len(key.key) == 0x20:
|
||||
acon_setting = self.HACC_AES_256
|
||||
else:
|
||||
acon_setting = self.HACC_AES_192
|
||||
if key.mode:
|
||||
acon_setting |= self.HACC_AES_CBC
|
||||
self.reg.HACC_ACON = acon_setting
|
||||
"""
|
||||
if m_src_addr<<30 or m_dst_addr << 30:
|
||||
return 0x6007
|
||||
if not m_src_len:
|
||||
return 0x600A
|
||||
if m_src_len != m_dst_len:
|
||||
return 0x6000
|
||||
if m_src_len << 29:
|
||||
return 0x6032
|
||||
memset(outbuf,0,0x20)
|
||||
if attr&4 == 0:
|
||||
CP_Power_On_SEJ_HW(1)
|
||||
"""
|
||||
|
||||
if attr & 1 != 0:
|
||||
self.reg.HACC_AKEY0 = 0
|
||||
self.reg.HACC_AKEY1 = 0
|
||||
self.reg.HACC_AKEY2 = 0
|
||||
self.reg.HACC_AKEY3 = 0
|
||||
self.reg.HACC_AKEY4 = 0
|
||||
self.reg.HACC_AKEY5 = 0
|
||||
self.reg.HACC_AKEY6 = 0
|
||||
self.reg.HACC_AKEY7 = 0
|
||||
if sej_param & 1 != 0:
|
||||
self.reg.HACC_ACONK = self.HACC_AES_BK2C
|
||||
else:
|
||||
keydata = [0, 0, 0, 0, 0, 0, 0, 0]
|
||||
# toDo: Is this valid ?
|
||||
for i in range(0, len(key.key), 4):
|
||||
keydata[i // 4] = unpack(">I", key.key[i:i + 4])[0]
|
||||
if len(key.key) >= 8:
|
||||
self.reg.HACC_AKEY0 = keydata[0]
|
||||
self.reg.HACC_AKEY1 = keydata[1]
|
||||
if len(key.key) >= 16:
|
||||
self.reg.HACC_AKEY2 = keydata[2]
|
||||
self.reg.HACC_AKEY3 = keydata[3]
|
||||
if len(key.key) >= 24:
|
||||
self.reg.HACC_AKEY4 = keydata[4]
|
||||
self.reg.HACC_AKEY5 = keydata[5]
|
||||
if len(key.key) >= 32:
|
||||
self.reg.HACC_AKEY6 = keydata[6]
|
||||
self.reg.HACC_AKEY7 = keydata[7]
|
||||
if attr & 2 != 0:
|
||||
self.reg.HACC_ACON2 = self.HACC_AES_CLR
|
||||
self.reg.HACC_ACFG0 = key.iv[0] # g_AC_CFG
|
||||
self.reg.HACC_ACFG1 = key.iv[1]
|
||||
self.reg.HACC_ACFG2 = key.iv[2]
|
||||
self.reg.HACC_ACFG3 = key.iv[3]
|
||||
|
||||
def SEJ_AES_HW_Internal(self, data, encrypt, attr, sej_param, legacy=True):
|
||||
if encrypt:
|
||||
self.reg.HACC_ACON |= 1
|
||||
if legacy:
|
||||
if (attr & 8) != 0 and (sej_param & 2) != 0:
|
||||
self.reg.HACC_ACONK |= self.HACC_AES_R2K
|
||||
else:
|
||||
self.reg.HACC_ACONK &= 0xFFFFFEFF
|
||||
pdst = bytearray()
|
||||
psrc = bytes_to_dwords(data)
|
||||
plen = len(psrc)
|
||||
pos = 0
|
||||
for i in range(plen // 4):
|
||||
self.reg.HACC_ASRC0 = psrc[pos + 0]
|
||||
self.reg.HACC_ASRC1 = psrc[pos + 1]
|
||||
self.reg.HACC_ASRC2 = psrc[pos + 2]
|
||||
self.reg.HACC_ASRC3 = psrc[pos + 3]
|
||||
self.reg.HACC_ACON2 = self.HACC_AES_START
|
||||
i = 0
|
||||
while i < 20:
|
||||
if self.reg.HACC_ACON2 & self.HACC_AES_RDY != 0:
|
||||
break
|
||||
i += 1
|
||||
if i == 20:
|
||||
self.error("SEJ Hardware seems not to be configured correctly. Results may be wrong.")
|
||||
pdst.extend(pack("<I", self.reg.HACC_AOUT0))
|
||||
pdst.extend(pack("<I", self.reg.HACC_AOUT1))
|
||||
pdst.extend(pack("<I", self.reg.HACC_AOUT2))
|
||||
pdst.extend(pack("<I", self.reg.HACC_AOUT3))
|
||||
pos += 4
|
||||
if legacy:
|
||||
if (attr & 8) != 0 and (sej_param & 2) == 0:
|
||||
# Key_Feedback_XOR_Handler
|
||||
keylen = 0x20
|
||||
for pos in range(keylen // 4):
|
||||
self.reg.HACC_AKEY0[pos] = pdst[pos] ^ self.reg.HACC_AKEY0[pos]
|
||||
return pdst
|
||||
|
||||
def SST_Secure_Algo_With_Level(self, buf, encrypt=True, aes_top_legacy=True):
|
||||
seed = (CustomSeed[2] << 16) | (CustomSeed[1] << 8) | CustomSeed[0] | (CustomSeed[3] << 24)
|
||||
iv = [seed, (~seed) & 0xFFFFFFFF, (((seed >> 16) | (seed << 16)) & 0xFFFFFFFF),
|
||||
(~((seed >> 16) | (seed << 16)) & 0xFFFFFFFF)]
|
||||
key = symkey()
|
||||
key.key = None
|
||||
key.key_len = 0x10
|
||||
key.mode = 1 # CBC
|
||||
key.iv = iv
|
||||
if aes_top_legacy:
|
||||
sej_param = 3
|
||||
else:
|
||||
sej_param = 5
|
||||
# Cipher Internal
|
||||
if sej_param & 0xC != 0:
|
||||
if sej_param & 4 != 0:
|
||||
# sej_param 5
|
||||
attr = 0x3A
|
||||
else:
|
||||
attr = 0x32
|
||||
flag = 1
|
||||
else:
|
||||
# aes_top_legacy
|
||||
attr = 0x33
|
||||
flag = 0
|
||||
metaflag = not flag
|
||||
# CS_MTK_Cipher_Internal
|
||||
if metaflag:
|
||||
# length=0x10
|
||||
attr = 0x5B
|
||||
self.SEJ_AES_HW_Init(attr, key, sej_param)
|
||||
for pos in range(3):
|
||||
src = b"".join([int.to_bytes(val,4,'little') for val in self.g_CFG_RANDOM_PATTERN])
|
||||
buf2 = self.SEJ_AES_HW_Internal(src, encrypt=False, attr=attr, sej_param=sej_param)
|
||||
attr = attr & 0xFFFFFFFA | 4
|
||||
self.SEJ_AES_HW_Init(attr, key, sej_param)
|
||||
buf2 = self.SEJ_AES_HW_Internal(buf, encrypt=encrypt, attr=attr, sej_param=sej_param)
|
||||
return buf2
|
||||
|
||||
def SEJ_Terminate(self):
|
||||
self.reg.HACC_ACON2 = self.HACC_AES_CLR
|
||||
self.reg.HACC_AKEY0 = 0
|
||||
|
@ -385,10 +454,10 @@ class sej(metaclass=LogBase):
|
|||
self.reg.HACC_AKEY6 = 0
|
||||
self.reg.HACC_AKEY7 = 0
|
||||
|
||||
def SEJ_V3_Init(self, ben=True, iv=None):
|
||||
if iv is None:
|
||||
iv = self.g_HACC_CFG_1
|
||||
acon_setting = self.HACC_AES_CHG_BO_OFF | self.HACC_AES_CBC | self.HACC_AES_128
|
||||
def SEJ_V3_Init(self, ben=True, iv=None, legacy=False):
|
||||
acon_setting = self.HACC_AES_CHG_BO_OFF | self.HACC_AES_128
|
||||
if iv is not None:
|
||||
acon_setting |= self.HACC_AES_CBC
|
||||
if ben:
|
||||
acon_setting |= self.HACC_AES_ENC
|
||||
else:
|
||||
|
@ -413,34 +482,52 @@ class sej(metaclass=LogBase):
|
|||
|
||||
# clear HACC_ASRC/HACC_ACFG/HACC_AOUT
|
||||
self.reg.HACC_ACON2 = self.HACC_AES_CLR # 0x08
|
||||
self.reg.HACC_UNK = 1
|
||||
#self.reg.HACC_UNK = 1
|
||||
self.reg.HACC_ACFG0 = iv[0] # g_AC_CFG
|
||||
self.reg.HACC_ACFG1 = iv[1]
|
||||
self.reg.HACC_ACFG2 = iv[2]
|
||||
self.reg.HACC_ACFG3 = iv[3]
|
||||
|
||||
# encrypt fix pattern 3 rounds to generate a pattern from HUID/HUK
|
||||
for i in range(0, 3):
|
||||
pos = i * 4
|
||||
self.reg.HACC_ASRC0 = self.g_CFG_RANDOM_PATTERN[pos]
|
||||
self.reg.HACC_ASRC1 = self.g_CFG_RANDOM_PATTERN[pos + 1]
|
||||
self.reg.HACC_ASRC2 = self.g_CFG_RANDOM_PATTERN[pos + 2]
|
||||
self.reg.HACC_ASRC3 = self.g_CFG_RANDOM_PATTERN[pos + 3]
|
||||
self.reg.HACC_ACON2 = self.HACC_AES_START
|
||||
i = 0
|
||||
while i < 20:
|
||||
if self.reg.HACC_ACON2 & self.HACC_AES_RDY != 0:
|
||||
if legacy:
|
||||
self.reg.HACC_UNK |= 2
|
||||
# clear HACC_ASRC/HACC_ACFG/HACC_AOUT
|
||||
self.reg.HACC_ACON2 = 0x40000000 | self.HACC_AES_CLR
|
||||
while True:
|
||||
if self.reg.HACC_ACON2 > 0x80000000:
|
||||
break
|
||||
i += 1
|
||||
if i == 20:
|
||||
self.error("SEJ Hardware seems not to be configured correctly. Results may be wrong.")
|
||||
self.reg.HACC_ACON2 = self.HACC_AES_CLR
|
||||
self.reg.HACC_ACFG0 = iv[0]
|
||||
self.reg.HACC_ACFG1 = iv[1]
|
||||
self.reg.HACC_ACFG2 = iv[2]
|
||||
self.reg.HACC_ACFG3 = iv[3]
|
||||
self.reg.HACC_ACON = acon_setting
|
||||
self.reg.HACC_ACONK = 0
|
||||
|
||||
self.reg.HACC_UNK &= 0xFFFFFFFE
|
||||
self.reg.HACC_ACONK = self.HACC_AES_BK2C
|
||||
self.reg.HACC_ACON = acon_setting
|
||||
else:
|
||||
# The reg below needed for mtee ?
|
||||
self.reg.HACC_UNK = 1
|
||||
|
||||
# encrypt fix pattern 3 rounds to generate a pattern from HUID/HUK
|
||||
for i in range(0, 3):
|
||||
pos = i * 4
|
||||
self.reg.HACC_ASRC0 = self.g_CFG_RANDOM_PATTERN[pos]
|
||||
self.reg.HACC_ASRC1 = self.g_CFG_RANDOM_PATTERN[pos + 1]
|
||||
self.reg.HACC_ASRC2 = self.g_CFG_RANDOM_PATTERN[pos + 2]
|
||||
self.reg.HACC_ASRC3 = self.g_CFG_RANDOM_PATTERN[pos + 3]
|
||||
self.reg.HACC_ACON2 = self.HACC_AES_START
|
||||
i = 0
|
||||
while i < 20:
|
||||
if self.reg.HACC_ACON2 & self.HACC_AES_RDY != 0:
|
||||
break
|
||||
i += 1
|
||||
if i == 20:
|
||||
self.error("SEJ Hardware seems not to be configured correctly. Results may be wrong.")
|
||||
|
||||
self.reg.HACC_ACON2 = self.HACC_AES_CLR
|
||||
|
||||
self.reg.HACC_ACFG0 = iv[0]
|
||||
self.reg.HACC_ACFG1 = iv[1]
|
||||
self.reg.HACC_ACFG2 = iv[2]
|
||||
self.reg.HACC_ACFG3 = iv[3]
|
||||
self.reg.HACC_ACON = acon_setting
|
||||
self.reg.HACC_ACONK = 0
|
||||
return acon_setting
|
||||
|
||||
def hw_aes128_cbc_encrypt(self, buf, encrypt=True, iv=None):
|
||||
if iv is None:
|
||||
|
@ -454,19 +541,6 @@ class sej(metaclass=LogBase):
|
|||
self.SEJ_Terminate()
|
||||
return buf2
|
||||
|
||||
def hw_aes128_sst_encrypt(self, buf, encrypt=True):
|
||||
seed = (CustomSeed[2]<<16) | (CustomSeed[1]<<8) | CustomSeed[0] | (CustomSeed[3]<<24)
|
||||
iv = [seed,(~seed)&0xFFFFFFFF,(((seed>>16)|(seed<<16))&0xFFFFFFFF),(~((seed>>16)|(seed<<16))&0xFFFFFFFF)]
|
||||
|
||||
self.tz_pre_init()
|
||||
self.info("HACC init")
|
||||
self.SEJ_Init(encrypt=encrypt, iv=iv)
|
||||
self.info("HACC run")
|
||||
buf2 = self.SEJ_Run(buf)
|
||||
self.info("HACC terminate")
|
||||
self.SEJ_Terminate()
|
||||
return buf2
|
||||
|
||||
def sej_set_otp(self, data):
|
||||
pd = bytes_to_dwords(data)
|
||||
self.reg.HACC_SW_OTP0 = pd[0]
|
||||
|
@ -526,10 +600,18 @@ class sej(metaclass=LogBase):
|
|||
self.sej_set_key(AES_HW_WRAP_KEY, AES_KEY_256, hw_key)
|
||||
|
||||
def sej_sec_cfg_sw(self, data, encrypt=True):
|
||||
"""
|
||||
Left for reference - hw implementation
|
||||
--------------------------------------
|
||||
self.sej_set_mode(AES_CBC_MODE)
|
||||
self.sej_set_key(AES_SW_KEY, AES_KEY_256, b"1A52A367CB12C458965D32CD874B36B2")
|
||||
iv = bytes.fromhex("57325A5A125497661254976657325A5A")
|
||||
res = self.sej_do_aes(encrypt, iv, data, len(data))
|
||||
"""
|
||||
ctx = cryptutils.aes()
|
||||
res = ctx.aes_cbc(key=b"25A1763A21BC854CD569DC23B4782B63",
|
||||
iv=bytes.fromhex("57325A5A125497661254976657325A5A"), data=data,
|
||||
decrypt=not encrypt)
|
||||
return res
|
||||
|
||||
def xor_data(self, data):
|
||||
|
@ -545,7 +627,7 @@ class sej(metaclass=LogBase):
|
|||
if encrypt:
|
||||
data = self.xor_data(bytearray(data))
|
||||
self.info("HACC init")
|
||||
self.SEJ_Init(encrypt=encrypt)
|
||||
self.SEJ_V3_Init(ben=encrypt,iv=self.g_HACC_CFG_1,legacy=True)
|
||||
self.info("HACC run")
|
||||
dec = self.SEJ_Run(data)
|
||||
self.info("HACC terminate")
|
||||
|
@ -623,9 +705,23 @@ class sej(metaclass=LogBase):
|
|||
if otp is not None:
|
||||
self.sej_set_otp(otp)
|
||||
self.info("HACC init")
|
||||
self.SEJ_Init_MTEE(encrypt=True)
|
||||
self.SEJ_V3_Init(ben=True, iv=self.g_HACC_CFG_MTEE)
|
||||
self.info("HACC run")
|
||||
dec = self.SEJ_Run(bytes.fromhex("7777772E6D6564696174656B2E636F6D30313233343536373839414243444546"))
|
||||
self.info("HACC terminate")
|
||||
self.SEJ_Terminate()
|
||||
return dec
|
||||
|
||||
def generate_hw_meta(self, otp=None, encrypt=False, data=b""):
|
||||
if otp is not None:
|
||||
self.sej_set_otp(otp)
|
||||
seed = (CustomSeed[2] << 16) | (CustomSeed[1] << 8) | CustomSeed[0] | (CustomSeed[3] << 24)
|
||||
iv = [seed, (~seed) & 0xFFFFFFFF, (((seed >> 16) | (seed << 16)) & 0xFFFFFFFF),
|
||||
(~((seed >> 16) | (seed << 16)) & 0xFFFFFFFF)]
|
||||
self.info("HACC init")
|
||||
self.SEJ_V3_Init(ben=encrypt, iv=iv)
|
||||
self.info("HACC run")
|
||||
dec = self.SEJ_Run(data)
|
||||
self.info("HACC terminate")
|
||||
self.SEJ_Terminate()
|
||||
return dec
|
|
@ -6,7 +6,7 @@ from mtkclient.config.payloads import pathconfig
|
|||
from mtkclient.Library.error import ErrorHandler
|
||||
from mtkclient.Library.hwcrypto import crypto_setup, hwcrypto
|
||||
from mtkclient.Library.utils import LogBase, logsetup, find_binary
|
||||
from mtkclient.Library.seccfg import seccfg
|
||||
from mtkclient.Library.seccfg import seccfgV4, seccfgV3
|
||||
from binascii import hexlify
|
||||
from mtkclient.Library.utils import mtktee
|
||||
import hashlib
|
||||
|
@ -160,105 +160,10 @@ class legacyext(metaclass=LogBase):
|
|||
setup.writemem = self.writemem
|
||||
return hwcrypto(setup, self.loglevel, self.config.gui)
|
||||
|
||||
def seccfg_custom_V3(self, seccfg_data, lockflag, hwc, partition):
|
||||
|
||||
# enum {
|
||||
ATTR_LOCK = 0x6000
|
||||
ATTR_VERIFIED = 0x6001
|
||||
ATTR_CUSTOM = 0x6002
|
||||
ATTR_MP_DEFAULT = 0x6003
|
||||
ATTR_DEFAULT = 0x33333333
|
||||
ATTR_UNLOCK = 0x44444444
|
||||
# } SECCFG_ATTR;
|
||||
|
||||
magic_number_beg = 0x10
|
||||
magic_number_end = magic_number_beg + 4
|
||||
|
||||
secattr_beg = 0x854
|
||||
|
||||
enc_cfg_sz = 0x1860
|
||||
enc_cfg_beg = 0x2C
|
||||
enc_cfg_end = enc_cfg_sz - 4
|
||||
|
||||
enc_cfg_secattr = secattr_beg - enc_cfg_beg
|
||||
|
||||
if seccfg_data[magic_number_beg : magic_number_end] != pack("<I", 0x4D4D4D4D):
|
||||
return False
|
||||
|
||||
sc_new = seccfg(hwc)
|
||||
self.setotp(hwc)
|
||||
|
||||
enc_data = seccfg_data[enc_cfg_beg : enc_cfg_end]
|
||||
|
||||
self.info("Attempt decrypt current seccfg")
|
||||
data_wr = sc_new.hwc.sej.sej_sec_cfg_hw_V3(enc_data, False)
|
||||
|
||||
|
||||
if lockflag == "lock":
|
||||
_SEC_ATTR_NEW = ATTR_DEFAULT
|
||||
else:
|
||||
_SEC_ATTR_NEW = ATTR_UNLOCK
|
||||
|
||||
|
||||
_SEC_ATTR_CURRENT = data_wr[enc_cfg_secattr : enc_cfg_secattr + 4]
|
||||
_SEC_ATTR_CURRENT = unpack('<I', _SEC_ATTR_CURRENT)[0]
|
||||
|
||||
|
||||
if (lockflag == "lock"
|
||||
and _SEC_ATTR_CURRENT != ATTR_UNLOCK):
|
||||
return False, ("Can't find lock state, current (%#x)" % _SEC_ATTR_CURRENT)
|
||||
elif (lockflag == "unlock"
|
||||
and _SEC_ATTR_CURRENT != ATTR_DEFAULT
|
||||
and _SEC_ATTR_CURRENT != ATTR_MP_DEFAULT
|
||||
and _SEC_ATTR_CURRENT != ATTR_CUSTOM
|
||||
and _SEC_ATTR_CURRENT != ATTR_VERIFIED
|
||||
and _SEC_ATTR_CURRENT != ATTR_LOCK):
|
||||
return False, ("Can't find unlock state, current (%#x)" % _SEC_ATTR_CURRENT)
|
||||
|
||||
|
||||
self.info("Set %s flag" % lockflag)
|
||||
data_wr[enc_cfg_secattr : enc_cfg_secattr + 4] = pack('<I', _SEC_ATTR_NEW)
|
||||
|
||||
self.info("Attempt encrypt new seccfg")
|
||||
enc_data = sc_new.hwc.sej.sej_sec_cfg_hw_V3(data_wr, True)
|
||||
|
||||
# Test new seccfg {
|
||||
self.info("Attempt decrypt new seccfg")
|
||||
data_wr = sc_new.hwc.sej.sej_sec_cfg_hw_V3(enc_data, False)
|
||||
|
||||
if data_wr[enc_cfg_secattr : enc_cfg_secattr + 4] == pack('<I', _SEC_ATTR_NEW):
|
||||
self.info("Test OK. Set %s in new seccfg successfully" % lockflag)
|
||||
else:
|
||||
return False, "Test error. Can't decrypt new seccfg"
|
||||
# }
|
||||
|
||||
seccfg_data[enc_cfg_beg : enc_cfg_end] = enc_data
|
||||
|
||||
# 0x22 is (SECURE_CFG_V3*)->fb_status
|
||||
# 0x23 is (SECURE_CFG_V3*)->dbg_status
|
||||
if lockflag == "lock":
|
||||
seccfg_data[0x22:0x23] = b'\x00'
|
||||
seccfg_data[0x23:0x24] = b'\x01'
|
||||
elif lockflag == "unlock":
|
||||
# seccfg_data[0x22:0x23] = b'\x67'
|
||||
seccfg_data[0x22:0x23] = b'\xF2'
|
||||
seccfg_data[0x23:0x24] = b'\x07'
|
||||
|
||||
enc_writedata = seccfg_data
|
||||
|
||||
|
||||
self.info("Attempt write new seccfg config")
|
||||
if self.legacy.writeflash(addr=partition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=len(enc_writedata),
|
||||
filename=None, wdata=enc_writedata, parttype="user", display=True):
|
||||
return True, "Successfully wrote custom seccfg."
|
||||
return False, "Error on writing custom seccfg config to flash."
|
||||
|
||||
def seccfg(self, lockflag):
|
||||
if lockflag not in ["unlock", "lock"]:
|
||||
return False, "Valid flags are: unlock, lock"
|
||||
hwc = self.cryptosetup()
|
||||
sc_org = seccfg(hwc)
|
||||
data, guid_gpt = self.legacy.partition.get_gpt(self.mtk.config.gpt_settings, "user")
|
||||
seccfg_data = None
|
||||
partition = None
|
||||
|
@ -272,32 +177,29 @@ class legacyext(metaclass=LogBase):
|
|||
break
|
||||
if seccfg_data is None:
|
||||
return False, "Couldn't detect existing seccfg partition. Aborting unlock."
|
||||
if seccfg_data[:4] != pack("<I", 0x4D4D4D4D):
|
||||
# Probe antother seccfg format
|
||||
state, msg = self.seccfg_custom_V3(seccfg_data, lockflag, hwc, partition)
|
||||
if state:
|
||||
return True, msg
|
||||
else:
|
||||
self.info(msg)
|
||||
|
||||
return False, "Unknown seccfg partition header. Aborting unlock."
|
||||
|
||||
if not sc_org.parse(seccfg_data):
|
||||
return False, "Error on parsing seccfg."
|
||||
sc_new = seccfg(hwc)
|
||||
self.setotp(hwc)
|
||||
hwtype = "hw"
|
||||
V3 = True
|
||||
sc_new.create(sc_org=sc_org, hwtype=hwtype, V3=V3)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
V3=False
|
||||
if seccfg_data[:0xC] == b"AND_SECCFG_v":
|
||||
sc_org = seccfgV3(hwc, self.mtk)
|
||||
if not sc_org.parse(seccfg_data):
|
||||
return False, "V3 Device has is either already unlocked or algo is unknown. Aborting."
|
||||
writedata = sc_org.create(lockflag)
|
||||
else:
|
||||
sc_org = seccfgV4(hwc,self.mtk)
|
||||
if not sc_org.parse(seccfg_data):
|
||||
return False, "Error on parsing seccfg."
|
||||
sc_new = seccfgV4(hwc,self.mtk)
|
||||
self.setotp(hwc)
|
||||
hwtype = "hw"
|
||||
V3 = True
|
||||
sc_new.create(sc_org=sc_org, hwtype=hwtype, V3=V3)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
hwtype = "sw"
|
||||
sc_new.create(sc_org=sc_org, hwtype=hwtype)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
return False, "Device has is either already unlocked or algo is unknown. Aborting."
|
||||
writedata = sc_new.create(sc_org=None, hwtype=hwtype, lockflag=lockflag, V3=V3)
|
||||
V3=False
|
||||
sc_new.create(sc_org=sc_org, hwtype=hwtype, V3=V3)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
hwtype = "sw"
|
||||
sc_new.create(sc_org=sc_org, hwtype=hwtype)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
return False, "Device has is either already unlocked or algo is unknown. Aborting."
|
||||
writedata = sc_new.create(sc_org=None, hwtype=hwtype, lockflag=lockflag, V3=V3)
|
||||
if self.legacy.writeflash(addr=partition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=len(writedata),
|
||||
filename=None, wdata=writedata, parttype="user", display=True):
|
||||
|
@ -380,7 +282,8 @@ class legacyext(metaclass=LogBase):
|
|||
open(os.path.join("logs", "hrid.txt"), "wb").write(hexlify(hrid))
|
||||
"""
|
||||
if hwcode == 0x699 and self.config.chipconfig.sej_base:
|
||||
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej")
|
||||
otp = self.config.get_otp()
|
||||
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej", otp=otp)
|
||||
if mtee3:
|
||||
self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8'))
|
||||
self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8'))
|
||||
|
@ -397,21 +300,22 @@ class legacyext(metaclass=LogBase):
|
|||
meid_addr = self.config.chipconfig.meid_addr
|
||||
meid = b"".join([pack("<I", val) for val in self.readmem(meid_addr, 4)])
|
||||
if meid != b"":
|
||||
otp = self.config.get_otp()
|
||||
self.info("Generating sej rpmbkey...")
|
||||
self.setotp(hwc)
|
||||
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej")
|
||||
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp)
|
||||
if rpmbkey:
|
||||
self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8'))
|
||||
self.config.hwparam.writesetting("rpmbkey", hexlify(rpmbkey).decode('utf-8'))
|
||||
retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8')
|
||||
self.info("Generating sej mtee...")
|
||||
mtee = hwc.aes_hwcrypt(mode="mtee", btype="sej")
|
||||
mtee = hwc.aes_hwcrypt(mode="mtee", btype="sej", otp=otp)
|
||||
if mtee:
|
||||
self.info("MTEE : " + hexlify(mtee).decode('utf-8'))
|
||||
self.config.hwparam.writesetting("mtee", hexlify(mtee).decode('utf-8'))
|
||||
retval["mtee"] = hexlify(mtee).decode('utf-8')
|
||||
self.info("Generating sej mtee3...")
|
||||
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej")
|
||||
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej", otp=otp)
|
||||
if mtee3:
|
||||
self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8'))
|
||||
self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8'))
|
||||
|
|
|
@ -244,6 +244,12 @@ class DAloader(metaclass=LogBase):
|
|||
else:
|
||||
return self.lft.generate_keys()
|
||||
|
||||
def readfuses(self):
|
||||
if self.xflash:
|
||||
return self.xft.readfuses()
|
||||
else:
|
||||
return self.lft.readfuses()
|
||||
|
||||
def is_patched(self):
|
||||
return self.da.patch
|
||||
|
||||
|
|
|
@ -288,13 +288,13 @@ class PLTools(metaclass=LogBase):
|
|||
self.error("Error on dumping Bootrom.")
|
||||
return False
|
||||
|
||||
def run_crypto(self, data, iv, btype="sej", encrypt=True):
|
||||
def run_crypto(self, data, iv, btype="sej", encrypt=True, otp=None):
|
||||
if data is None:
|
||||
data = bytearray()
|
||||
for i in range(32):
|
||||
data.append(self.config.meid[i % len(self.config.meid)])
|
||||
if btype == "":
|
||||
encrypted = self.hwcrypto.aes_hwcrypt(data=data, iv=iv, encrypt=encrypt, btype=btype)
|
||||
encrypted = self.hwcrypto.aes_hwcrypt(data=data, iv=iv, encrypt=encrypt, btype=btype, otp=otp)
|
||||
return encrypted
|
||||
return False
|
||||
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
from struct import unpack, pack
|
||||
from mtkclient.Library.utils import structhelper_io
|
||||
from io import BytesIO
|
||||
import hashlib
|
||||
|
||||
from mtkclient.config.mtk_config import Mtk_Config
|
||||
|
||||
class seccfg:
|
||||
def __init__(self, hwc):
|
||||
|
||||
class seccfgV4:
|
||||
def __init__(self, hwc, mtk):
|
||||
self.hwc = hwc
|
||||
self.mtk = mtk
|
||||
self.magic = 0x4D4D4D4D
|
||||
self.seccfg_ver = None
|
||||
self.seccfg_size = None
|
||||
|
@ -15,12 +20,18 @@ class seccfg:
|
|||
self.hash = b""
|
||||
|
||||
def parse(self, data):
|
||||
seccfg_data = unpack("<IIIIIII", data[:7 * 4])
|
||||
self.magic, self.seccfg_ver, self.seccfg_size, self.lock_state, self.critical_lock_state, \
|
||||
self.sboot_runtime, self.endflag = seccfg_data
|
||||
self.hash = data[7 * 4:(7 * 4) + 32]
|
||||
rf = structhelper_io(BytesIO(bytearray(data)))
|
||||
self.magic = rf.dword()
|
||||
self.seccfg_ver = rf.dword()
|
||||
self.seccfg_size = rf.dword()
|
||||
self.lock_state = rf.dword()
|
||||
self.critical_lock_state = rf.dword()
|
||||
self.sboot_runtime = rf.dword()
|
||||
self.endflag = rf.dword()
|
||||
rf.seek(self.seccfg_size - 0x20)
|
||||
self.hash = rf.bytes(0x20)
|
||||
if self.magic != 0x4D4D4D4D or self.endflag != 0x45454545:
|
||||
self.error("Unknown seccfg structure !")
|
||||
self.error("Unknown V4 seccfg structure !")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -69,5 +80,191 @@ class seccfg:
|
|||
enc_hash = self.hwc.sej.sej_sec_cfg_hw_V3(dec_hash, True)
|
||||
self.hash = enc_hash
|
||||
data = seccfg_data + enc_hash
|
||||
data += b"\x00" * (0x200 - len(data))
|
||||
while len(data) % 0x200 != 0:
|
||||
data += b"\x00"
|
||||
return bytearray(data)
|
||||
|
||||
|
||||
class SECCFG_STATUS:
|
||||
SEC_CFG_COMPLETE_NUM = 0x43434343 # CCCC
|
||||
SEC_CFG_INCOMPLETE_NUM = 0x49494949 # IIII
|
||||
|
||||
|
||||
class SECCFG_ATTR:
|
||||
ATTR_LOCK = 0x6000
|
||||
ATTR_VERIFIED = 0x6001
|
||||
ATTR_CUSTOM = 0x6002
|
||||
ATTR_MP_DEFAULT = 0x6003
|
||||
ATTR_DEFAULT = 0x33333333
|
||||
ATTR_UNLOCK = 0x44444444
|
||||
|
||||
|
||||
class SIU_STATUS:
|
||||
UBOOT_UPDATED_BY_SIU = 0x0001
|
||||
BOOT_UPDATED_BY_SIU = 0x0010
|
||||
RECOVERY_UPDATED_BY_SIU = 0x0100
|
||||
SYSTEM_UPDATED_BY_SIU = 0x1000
|
||||
|
||||
|
||||
class ROM_TYPE:
|
||||
NORMAL_ROM = 0x01
|
||||
YAFFS_IMG = 0x08
|
||||
|
||||
|
||||
class SEC_IMG_ATTR:
|
||||
ATTR_SEC_IMG_UPDATE = 0x10,
|
||||
ATTR_SEC_IMG_COMPLETE = 0x43434343, # CCCC
|
||||
ATTR_SEC_IMG_INCOMPLETE = 0x49494949, # IIII
|
||||
ATTR_SEC_IMG_FORCE_UPDATE = 0x46464646 # FFFF
|
||||
|
||||
|
||||
class seccfgV3:
|
||||
def __init__(self, hwc, mtk):
|
||||
self.hwtype = None
|
||||
self.data = None
|
||||
self.org_data = None
|
||||
self.hwc = hwc
|
||||
self.mtk = mtk
|
||||
self.info = b"AND_SECCFG_v\x00\x00\x00\x00"
|
||||
self.magic = 0x4D4D4D4D
|
||||
self.seccfg_ver = 3
|
||||
self.seccfg_size = 0x1860
|
||||
self.seccfg_enc_len = 0x01000000 # 0x07F20000 for unlocked
|
||||
self.seccfg_enc_offset = 0
|
||||
self.endflag = 0x45454545
|
||||
self.sw_sec_lock_try = 0
|
||||
self.sw_sec_lock_done = 0
|
||||
self.page_size = 0
|
||||
self.page_count = 0
|
||||
self.imginfo = b"\x00" * (0x68 * 20)
|
||||
self.siu_status = 0
|
||||
self.seccfg_status = SECCFG_STATUS.SEC_CFG_COMPLETE_NUM
|
||||
self.seccfg_attr = SECCFG_ATTR.ATTR_DEFAULT
|
||||
self.seccfg_ext = b"\x00" * 0x1004
|
||||
if self.hwc.read32 is not None:
|
||||
self.setotp(hwc)
|
||||
|
||||
def setotp(self, hwc):
|
||||
otp = None
|
||||
if self.mtk.config.preloader is not None:
|
||||
idx = self.mtk.config.preloader.find(b"\x4D\x4D\x4D\x01\x30")
|
||||
if idx != -1:
|
||||
otp = self.mtk.config.preloader[idx + 0xC:idx + 0xC + 32]
|
||||
if otp is None:
|
||||
otp = 32 * b"\x00"
|
||||
hwc.sej.sej_set_otp(otp)
|
||||
|
||||
def parse(self, data):
|
||||
if data[:0x10] != b"AND_SECCFG_v\x00\x00\x00\x00":
|
||||
return False
|
||||
rf = structhelper_io(BytesIO(bytearray(data)))
|
||||
self.info = rf.bytes(0x10)
|
||||
self.magic = rf.dword()
|
||||
self.seccfg_ver = rf.dword()
|
||||
self.seccfg_size = rf.dword()
|
||||
self.seccfg_enc_offset = rf.dword()
|
||||
self.seccfg_enc_len = rf.dword() # 0x1 = Locked, 0xF207 = Unlocked
|
||||
self.sw_sec_lock_try = rf.bytes(1)
|
||||
self.sw_sec_lock_done = rf.bytes(1)
|
||||
self.page_size = rf.short()
|
||||
self.page_count = rf.dword()
|
||||
self.data = rf.bytes(self.seccfg_size - 0x2C - 4)
|
||||
self.endflag = rf.dword()
|
||||
if self.magic != 0x4D4D4D4D or self.endflag != 0x45454545:
|
||||
self.error("Unknown V3 seccfg structure !")
|
||||
return False
|
||||
ret = self.hwc.sej.sej_sec_cfg_sw(self.data, False)
|
||||
if ret[:4] != b"IIII":
|
||||
ret = self.hwc.sej.sej_sec_cfg_hw(self.data, False)
|
||||
if ret[:4] != b"IIII":
|
||||
ret = self.hwc.sej.sej_sec_cfg_hw_V3(self.data, False)
|
||||
if ret[:4] != b"IIII":
|
||||
self.error("Unknown V3 seccfg encryption !")
|
||||
return False
|
||||
else:
|
||||
self.hwtype = "V3"
|
||||
else:
|
||||
self.hwtype = "V2"
|
||||
else:
|
||||
self.hwtype = "SW"
|
||||
self.org_data = ret
|
||||
ed = structhelper_io(BytesIO(bytearray(ret)))
|
||||
self.imginfo = [ed.bytes(0x68) for _ in range(20)]
|
||||
self.siu_status = ed.dword()
|
||||
self.seccfg_status = ed.dword()
|
||||
if self.seccfg_status not in [SECCFG_STATUS.SEC_CFG_COMPLETE_NUM,SECCFG_STATUS.SEC_CFG_INCOMPLETE_NUM]:
|
||||
return False
|
||||
self.seccfg_attr = ed.dword()
|
||||
if self.seccfg_attr not in [SECCFG_ATTR.ATTR_DEFAULT,SECCFG_ATTR.ATTR_UNLOCK,SECCFG_ATTR.ATTR_MP_DEFAULT,
|
||||
SECCFG_ATTR.ATTR_LOCK, SECCFG_ATTR.ATTR_CUSTOM,SECCFG_ATTR.ATTR_VERIFIED]:
|
||||
return False
|
||||
self.seccfg_ext = ed.bytes(0x1000 + 4)
|
||||
return True
|
||||
|
||||
def create(self, lockflag: str = "unlock"):
|
||||
seccfg_attr_new = SECCFG_ATTR.ATTR_DEFAULT
|
||||
if lockflag == "unlock":
|
||||
self.seccfg_enc_len = 0x07F20000
|
||||
seccfg_attr_new = SECCFG_ATTR.ATTR_UNLOCK
|
||||
elif lockflag == "lock":
|
||||
self.seccfg_enc_len = 0x01000000
|
||||
seccfg_attr_new = SECCFG_ATTR.ATTR_DEFAULT
|
||||
|
||||
"""
|
||||
if lockflag == "lock" and self.seccfg_attr != SECCFG_ATTR.ATTR_UNLOCK:
|
||||
return False, ("Can't find lock state, current (%#x)" % self.seccfg_attr)
|
||||
elif lockflag == "unlock" and self.seccfg_attr != SECCFG_ATTR.ATTR_DEFAULT \
|
||||
and self.seccfg_attr != SECCFG_ATTR.ATTR_MP_DEFAULT \
|
||||
and self.seccfg_attr != SECCFG_ATTR.ATTR_CUSTOM \
|
||||
and self.seccfg_attr != SECCFG_ATTR.ATTR_VERIFIED \
|
||||
and self.seccfg_attr != SECCFG_ATTR.ATTR_LOCK:
|
||||
return False, ("Can't find unlock state, current (%#x)" % self.seccfg_attr)
|
||||
"""
|
||||
data = bytearray()
|
||||
wf = BytesIO(data)
|
||||
wf.write(self.info)
|
||||
wf.write(int.to_bytes(self.magic, 4, 'little'))
|
||||
wf.write(int.to_bytes(self.seccfg_ver, 4, 'little'))
|
||||
wf.write(int.to_bytes(self.seccfg_size, 4, 'little'))
|
||||
wf.write(int.to_bytes(self.seccfg_enc_offset, 4, 'little'))
|
||||
wf.write(int.to_bytes(self.seccfg_enc_len, 4, 'little'))
|
||||
wf.write(int.to_bytes(self.sw_sec_lock_try, 1, 'little'))
|
||||
wf.write(int.to_bytes(self.sw_sec_lock_done, 1, 'little'))
|
||||
wf.write(int.to_bytes(self.page_size, 2, 'little'))
|
||||
wf.write(int.to_bytes(self.page_count, 4, 'little'))
|
||||
|
||||
ed = BytesIO()
|
||||
for imginfo in self.imginfo:
|
||||
ed.write(imginfo)
|
||||
ed.write(int.to_bytes(self.siu_status, 4, 'little'))
|
||||
ed.write(int.to_bytes(self.seccfg_status, 4, 'little'))
|
||||
ed.write(int.to_bytes(seccfg_attr_new, 4, 'little'))
|
||||
ed.write(self.seccfg_ext)
|
||||
data = ed.getbuffer()
|
||||
if self.hwtype == "SW":
|
||||
data = self.hwc.sej.sej_sec_cfg_sw(data, True)
|
||||
elif self.hwtype == "V2":
|
||||
data = self.hwc.sej.sej_sec_cfg_hw(data, True)
|
||||
elif self.hwtype == "V3":
|
||||
data = self.hwc.sej.sej_sec_cfg_hw_V3(data, True)
|
||||
wf.write(data)
|
||||
wf.write(int.to_bytes(self.endflag, 4, 'little'))
|
||||
|
||||
data = bytearray(wf.getbuffer())
|
||||
while len(data) % 0x200 != 0:
|
||||
data += b"\x00"
|
||||
return bytearray(data)
|
||||
|
||||
if __name__ == "__main__":
|
||||
with open("seccfg.bin","rb") as rf:
|
||||
data = rf.read()
|
||||
from hwcrypto import hwcrypto, crypto_setup
|
||||
setup = crypto_setup()
|
||||
hwc = hwcrypto(setup)
|
||||
class mtk:
|
||||
config = Mtk_Config()
|
||||
sej_base = None
|
||||
v3=seccfgV3(hwc,mtk)
|
||||
v3.parse(data)
|
||||
newdata=v3.create("lock")
|
||||
print(newdata.hex())
|
|
@ -29,8 +29,6 @@ except ImportError:
|
|||
from struct import unpack, pack
|
||||
from io import BytesIO
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
class mtktee:
|
||||
magic = None
|
||||
hdrlen = None
|
||||
|
@ -805,7 +803,7 @@ def write_object(definition, *args):
|
|||
return obj
|
||||
|
||||
|
||||
def print_progress(iteration, total, prefix='', suffix='', decimals=1, bar_length=100):
|
||||
def print_progress(iteration, total, prefix='', suffix='', decimals=1, bar_length=50):
|
||||
"""
|
||||
Call in a loop to create terminal progress bar
|
||||
@params:
|
||||
|
|
|
@ -6,7 +6,7 @@ from mtkclient.config.brom_config import efuse
|
|||
from mtkclient.Library.error import ErrorHandler, ErrorCodes_XFlash
|
||||
from mtkclient.Library.hwcrypto import crypto_setup, hwcrypto
|
||||
from mtkclient.Library.utils import LogBase, progress, logsetup, find_binary
|
||||
from mtkclient.Library.seccfg import seccfg
|
||||
from mtkclient.Library.seccfg import seccfgV3, seccfgV4
|
||||
from binascii import hexlify
|
||||
from mtkclient.Library.utils import mtktee
|
||||
import json
|
||||
|
@ -372,11 +372,11 @@ class xflashext(metaclass=LogBase):
|
|||
hwc = self.cryptosetup()
|
||||
if self.config.chipconfig.meid_addr:
|
||||
meid = self.config.get_meid()
|
||||
otp = self.config.get_otp()
|
||||
if meid != b"\x00" * 16:
|
||||
# self.config.set_meid(meid)
|
||||
self.info("Generating sej rpmbkey...")
|
||||
self.setotp(hwc)
|
||||
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej")
|
||||
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):
|
||||
self.xsend(rpmbkey)
|
||||
|
@ -503,8 +503,6 @@ class xflashext(metaclass=LogBase):
|
|||
def seccfg(self, lockflag):
|
||||
if lockflag not in ["unlock", "lock"]:
|
||||
return False, "Valid flags are: unlock, lock"
|
||||
hwc = self.cryptosetup()
|
||||
sc_org = seccfg(hwc)
|
||||
data, guid_gpt = self.xflash.partition.get_gpt(self.mtk.config.gpt_settings, "user")
|
||||
seccfg_data = None
|
||||
partition = None
|
||||
|
@ -522,23 +520,29 @@ class xflashext(metaclass=LogBase):
|
|||
return False, "Couldn't detect existing seccfg partition. Aborting unlock."
|
||||
if seccfg_data[:4] != pack("<I", 0x4D4D4D4D):
|
||||
return False, "Unknown seccfg partition header. Aborting unlock."
|
||||
|
||||
if not sc_org.parse(seccfg_data):
|
||||
return False, "Error on parsing seccfg"
|
||||
sc_new = seccfg(hwc)
|
||||
self.setotp(hwc)
|
||||
hwtype = "hw"
|
||||
V3 = True
|
||||
sc_new.create(sc_org=sc_org, hwtype=hwtype, V3=V3)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
V3 = False
|
||||
hwc = self.cryptosetup()
|
||||
if seccfg_data[:0xC] == b"AND_SECCFG_v":
|
||||
sc_org = seccfgV3(hwc, self.mtk)
|
||||
if not sc_org.parse(seccfg_data):
|
||||
return False, "V3 Device has is either already unlocked or algo is unknown. Aborting."
|
||||
writedata = sc_org.create(lockflag)
|
||||
else:
|
||||
sc_org = seccfgV4(hwc, self.mtk)
|
||||
if not sc_org.parse(seccfg_data):
|
||||
return False, "Error on parsing seccfg"
|
||||
sc_new = seccfgV4(hwc, self.mtk)
|
||||
hwtype = "hw"
|
||||
V3 = True
|
||||
sc_new.create(sc_org=sc_org, hwtype=hwtype, V3=V3)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
hwtype = "sw"
|
||||
sc_new.create(sc_org=sc_org, hwtype=hwtype)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
return False, "Device has is either already unlocked or algo is unknown. Aborting."
|
||||
writedata = sc_new.create(sc_org=None, hwtype=hwtype, lockflag=lockflag, V3=V3)
|
||||
V3 = False
|
||||
sc_new.create(sc_org=sc_org, hwtype=hwtype, V3=V3)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
hwtype = "sw"
|
||||
sc_new.create(sc_org=sc_org, hwtype=hwtype)
|
||||
if sc_org.hash != sc_new.hash:
|
||||
return False, "Device has is either already unlocked or algo is unknown. Aborting."
|
||||
writedata = sc_new.create(sc_org=None, hwtype=hwtype, lockflag=lockflag, V3=V3)
|
||||
if self.xflash.writeflash(addr=partition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=len(writedata),
|
||||
filename=None, wdata=writedata, parttype="user", display=True):
|
||||
|
@ -569,13 +573,27 @@ class xflashext(metaclass=LogBase):
|
|||
return data
|
||||
return None
|
||||
|
||||
def read_fuses(self):
|
||||
if self.mtk.config.chipconfig.efuse_addr is not None:
|
||||
base = self.mtk.config.chipconfig.efuse_addr
|
||||
hwcode = self.mtk.config.hwcode
|
||||
efuseconfig = efuse(base, hwcode)
|
||||
data = []
|
||||
for idx in range(len(efuseconfig.efuses)):
|
||||
addr = efuseconfig.efuses[idx]
|
||||
data.append(bytearray(self.mtk.daloader.peek(addr=addr, length=4)))
|
||||
return data
|
||||
|
||||
def generate_keys(self):
|
||||
hwc = self.cryptosetup()
|
||||
meid = self.config.get_meid()
|
||||
socid = self.config.get_socid()
|
||||
hwcode = self.config.get_hwcode()
|
||||
cid = self.config.get_cid()
|
||||
otp = self.config.get_otp()
|
||||
retval = {}
|
||||
#data=hwc.aes_hwcrypt(data=bytes.fromhex("F6 25 25 AD 0C A4 3A AA CC EF 93 1F 2D C2 A3 EE"), mode="sst", btype="sej",
|
||||
# encrypt=True)
|
||||
if meid is not None:
|
||||
self.info("MEID : " + hexlify(meid).decode('utf-8'))
|
||||
retval["meid"] = hexlify(meid).decode('utf-8')
|
||||
|
@ -668,18 +686,18 @@ class xflashext(metaclass=LogBase):
|
|||
# self.config.set_meid(meid)
|
||||
self.info("Generating sej rpmbkey...")
|
||||
self.setotp(hwc)
|
||||
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej")
|
||||
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp)
|
||||
if rpmbkey:
|
||||
self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8'))
|
||||
self.config.hwparam.writesetting("rpmbkey", hexlify(rpmbkey).decode('utf-8'))
|
||||
retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8')
|
||||
self.info("Generating sej mtee...")
|
||||
mtee = hwc.aes_hwcrypt(mode="mtee", btype="sej")
|
||||
mtee = hwc.aes_hwcrypt(mode="mtee", btype="sej", otp=otp)
|
||||
if mtee:
|
||||
self.config.hwparam.writesetting("mtee", hexlify(mtee).decode('utf-8'))
|
||||
self.info("MTEE : " + hexlify(mtee).decode('utf-8'))
|
||||
retval["mtee"] = hexlify(mtee).decode('utf-8')
|
||||
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej")
|
||||
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej", otp=otp)
|
||||
if mtee3:
|
||||
self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8'))
|
||||
self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8'))
|
||||
|
|
|
@ -66,6 +66,7 @@ class Mtk_Config(metaclass=LogBase):
|
|||
self.hwparam_path = "logs"
|
||||
self.sram = None
|
||||
self.dram = None
|
||||
self.otp = None
|
||||
if loglevel == logging.DEBUG:
|
||||
logfilename = os.path.join("logs", "log.txt")
|
||||
fh = logging.FileHandler(logfilename)
|
||||
|
@ -108,6 +109,22 @@ class Mtk_Config(metaclass=LogBase):
|
|||
self.meid = meid
|
||||
self.hwparam.writesetting("meid", hexlify(meid).decode('utf-8'))
|
||||
|
||||
def get_otp(self):
|
||||
if self.otp is None:
|
||||
self.otp = self.hwparam.loadsetting("otp")
|
||||
if self.preloader is not None:
|
||||
idx = self.preloader.find(b"\x4D\x4D\x4D\x01\x30")
|
||||
if idx != -1:
|
||||
self.otp = self.preloader[idx + 0xC:idx + 0xC + 32]
|
||||
self.hwparam.writesetting("otp",hexlify(self.otp).decode('utf-8'))
|
||||
if self.otp is None:
|
||||
self.otp = 32 * b"\x00"
|
||||
return self.otp
|
||||
|
||||
def set_otp(self,otp):
|
||||
self.otp = otp
|
||||
self.hwparam.writesetting("otp",hexlify(otp).decode('utf-8'))
|
||||
|
||||
def get_meid(self):
|
||||
if self.meid is None:
|
||||
if self.peek is not None:
|
||||
|
|
8
stage2
8
stage2
|
@ -444,25 +444,25 @@ class Stage2(metaclass=LogBase):
|
|||
retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8')
|
||||
return retval, keyinfo
|
||||
if mode == "sej_aes_decrypt":
|
||||
dec_data = self.hwcrypto.aes_hwcrypt(mode="cbc", data=data, btype="sej", encrypt=False)
|
||||
dec_data = self.hwcrypto.aes_hwcrypt(mode="cbc", data=data, btype="sej", encrypt=False, otp=otp)
|
||||
keyinfo+="\n"
|
||||
keyinfo+="Data: " + hexlify(dec_data).decode('utf-8')
|
||||
keyinfo+="\n"
|
||||
return dec_data, keyinfo
|
||||
elif mode == "sej_aes_encrypt":
|
||||
enc_data = self.hwcrypto.aes_hwcrypt(mode="cbc", data=data, btype="sej", encrypt=True)
|
||||
enc_data = self.hwcrypto.aes_hwcrypt(mode="cbc", data=data, btype="sej", encrypt=True, otp=otp)
|
||||
keyinfo+="\n"
|
||||
keyinfo+="Data: " + hexlify(enc_data).decode('utf-8')
|
||||
keyinfo+="\n"
|
||||
return enc_data, keyinfo
|
||||
elif mode == "sej_sst_decrypt":
|
||||
dec_data = self.hwcrypto.aes_hwcrypt(mode="sst", data=data, btype="sej", encrypt=False)
|
||||
dec_data = self.hwcrypto.aes_hwcrypt(mode="sst", data=data, btype="sej", encrypt=False, otp=otp)
|
||||
keyinfo+="\n"
|
||||
keyinfo+="Data: " + hexlify(dec_data).decode('utf-8')
|
||||
keyinfo+="\n"
|
||||
return dec_data, keyinfo
|
||||
elif mode == "sej_sst_encrypt":
|
||||
enc_data = self.hwcrypto.aes_hwcrypt(mode="sst", data=data, btype="sej", encrypt=True)
|
||||
enc_data = self.hwcrypto.aes_hwcrypt(mode="sst", data=data, btype="sej", encrypt=True, otp=otp)
|
||||
keyinfo += "\n"
|
||||
keyinfo += "Data: " + hexlify(enc_data).decode('utf-8')
|
||||
keyinfo += "\n"
|
||||
|
|
Loading…
Reference in a new issue