Merge pull request #696 from bkerler/newcrypto

Add full lock V3 support
This commit is contained in:
Bjoern Kerler 2023-06-12 19:32:12 +02:00 committed by GitHub
commit 305903c64d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 539 additions and 297 deletions

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2021 GPLv3 License # (c) B.Kerler 2018-2021 GPLv3 License
import logging import logging
import sys
from mtkclient.Library.utils import LogBase, logsetup from mtkclient.Library.utils import LogBase, logsetup
from mtkclient.Library.hwcrypto_gcpu import GCpu from mtkclient.Library.hwcrypto_gcpu import GCpu
@ -62,12 +63,17 @@ class hwcrypto(metaclass=LogBase):
if mode == "cbc": if mode == "cbc":
return self.sej.hw_aes128_cbc_encrypt(buf=data, encrypt=True) return self.sej.hw_aes128_cbc_encrypt(buf=data, encrypt=True)
elif mode == "sst": 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: else:
if mode == "cbc": if mode == "cbc":
return self.sej.hw_aes128_cbc_encrypt(buf=data, encrypt=False) return self.sej.hw_aes128_cbc_encrypt(buf=data, encrypt=False)
elif mode == "sst": 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": if mode == "rpmb":
return self.sej.generate_rpmb(meid=data, otp=otp) return self.sej.generate_rpmb(meid=data, otp=otp)
elif mode == "mtee": elif mode == "mtee":

View file

@ -4,8 +4,10 @@
import logging, os import logging, os
from struct import pack, unpack from struct import pack, unpack
from mtkclient.Library.utils import LogBase 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 # SEJ = Security Engine for JTAG protection
@ -16,6 +18,13 @@ def bytes_to_dwords(buf):
return res return res
class symkey:
key = None
key_len = 0x10
mode = 1
iv = None
AES_CBC_MODE = 1 AES_CBC_MODE = 1
AES_SW_KEY = 0 AES_SW_KEY = 0
AES_HW_KEY = 1 AES_HW_KEY = 1
@ -260,95 +269,6 @@ class sej(metaclass=LogBase):
# self.crypto_secure(1) # self.crypto_secure(1)
return 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): def SEJ_Run(self, data):
pdst = bytearray() pdst = bytearray()
psrc = bytes_to_dwords(data) psrc = bytes_to_dwords(data)
@ -374,6 +294,155 @@ class sej(metaclass=LogBase):
pos += 4 pos += 4
return pdst 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): def SEJ_Terminate(self):
self.reg.HACC_ACON2 = self.HACC_AES_CLR self.reg.HACC_ACON2 = self.HACC_AES_CLR
self.reg.HACC_AKEY0 = 0 self.reg.HACC_AKEY0 = 0
@ -385,10 +454,10 @@ class sej(metaclass=LogBase):
self.reg.HACC_AKEY6 = 0 self.reg.HACC_AKEY6 = 0
self.reg.HACC_AKEY7 = 0 self.reg.HACC_AKEY7 = 0
def SEJ_V3_Init(self, ben=True, iv=None): def SEJ_V3_Init(self, ben=True, iv=None, legacy=False):
if iv is None: acon_setting = self.HACC_AES_CHG_BO_OFF | self.HACC_AES_128
iv = self.g_HACC_CFG_1 if iv is not None:
acon_setting = self.HACC_AES_CHG_BO_OFF | self.HACC_AES_CBC | self.HACC_AES_128 acon_setting |= self.HACC_AES_CBC
if ben: if ben:
acon_setting |= self.HACC_AES_ENC acon_setting |= self.HACC_AES_ENC
else: else:
@ -413,34 +482,52 @@ class sej(metaclass=LogBase):
# clear HACC_ASRC/HACC_ACFG/HACC_AOUT # clear HACC_ASRC/HACC_ACFG/HACC_AOUT
self.reg.HACC_ACON2 = self.HACC_AES_CLR # 0x08 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_ACFG0 = iv[0] # g_AC_CFG
self.reg.HACC_ACFG1 = iv[1] self.reg.HACC_ACFG1 = iv[1]
self.reg.HACC_ACFG2 = iv[2] self.reg.HACC_ACFG2 = iv[2]
self.reg.HACC_ACFG3 = iv[3] self.reg.HACC_ACFG3 = iv[3]
# encrypt fix pattern 3 rounds to generate a pattern from HUID/HUK if legacy:
for i in range(0, 3): self.reg.HACC_UNK |= 2
pos = i * 4 # clear HACC_ASRC/HACC_ACFG/HACC_AOUT
self.reg.HACC_ASRC0 = self.g_CFG_RANDOM_PATTERN[pos] self.reg.HACC_ACON2 = 0x40000000 | self.HACC_AES_CLR
self.reg.HACC_ASRC1 = self.g_CFG_RANDOM_PATTERN[pos + 1] while True:
self.reg.HACC_ASRC2 = self.g_CFG_RANDOM_PATTERN[pos + 2] if self.reg.HACC_ACON2 > 0x80000000:
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 break
i += 1
if i == 20: self.reg.HACC_UNK &= 0xFFFFFFFE
self.error("SEJ Hardware seems not to be configured correctly. Results may be wrong.") self.reg.HACC_ACONK = self.HACC_AES_BK2C
self.reg.HACC_ACON2 = self.HACC_AES_CLR self.reg.HACC_ACON = acon_setting
self.reg.HACC_ACFG0 = iv[0] else:
self.reg.HACC_ACFG1 = iv[1] # The reg below needed for mtee ?
self.reg.HACC_ACFG2 = iv[2] self.reg.HACC_UNK = 1
self.reg.HACC_ACFG3 = iv[3]
self.reg.HACC_ACON = acon_setting # encrypt fix pattern 3 rounds to generate a pattern from HUID/HUK
self.reg.HACC_ACONK = 0 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): def hw_aes128_cbc_encrypt(self, buf, encrypt=True, iv=None):
if iv is None: if iv is None:
@ -454,19 +541,6 @@ class sej(metaclass=LogBase):
self.SEJ_Terminate() self.SEJ_Terminate()
return buf2 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): def sej_set_otp(self, data):
pd = bytes_to_dwords(data) pd = bytes_to_dwords(data)
self.reg.HACC_SW_OTP0 = pd[0] 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) self.sej_set_key(AES_HW_WRAP_KEY, AES_KEY_256, hw_key)
def sej_sec_cfg_sw(self, data, encrypt=True): def sej_sec_cfg_sw(self, data, encrypt=True):
"""
Left for reference - hw implementation
--------------------------------------
self.sej_set_mode(AES_CBC_MODE) self.sej_set_mode(AES_CBC_MODE)
self.sej_set_key(AES_SW_KEY, AES_KEY_256, b"1A52A367CB12C458965D32CD874B36B2") self.sej_set_key(AES_SW_KEY, AES_KEY_256, b"1A52A367CB12C458965D32CD874B36B2")
iv = bytes.fromhex("57325A5A125497661254976657325A5A") iv = bytes.fromhex("57325A5A125497661254976657325A5A")
res = self.sej_do_aes(encrypt, iv, data, len(data)) 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 return res
def xor_data(self, data): def xor_data(self, data):
@ -545,7 +627,7 @@ class sej(metaclass=LogBase):
if encrypt: if encrypt:
data = self.xor_data(bytearray(data)) data = self.xor_data(bytearray(data))
self.info("HACC init") 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") self.info("HACC run")
dec = self.SEJ_Run(data) dec = self.SEJ_Run(data)
self.info("HACC terminate") self.info("HACC terminate")
@ -623,9 +705,23 @@ class sej(metaclass=LogBase):
if otp is not None: if otp is not None:
self.sej_set_otp(otp) self.sej_set_otp(otp)
self.info("HACC init") 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") self.info("HACC run")
dec = self.SEJ_Run(bytes.fromhex("7777772E6D6564696174656B2E636F6D30313233343536373839414243444546")) dec = self.SEJ_Run(bytes.fromhex("7777772E6D6564696174656B2E636F6D30313233343536373839414243444546"))
self.info("HACC terminate") self.info("HACC terminate")
self.SEJ_Terminate() self.SEJ_Terminate()
return dec 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

View file

@ -6,7 +6,7 @@ from mtkclient.config.payloads import pathconfig
from mtkclient.Library.error import ErrorHandler from mtkclient.Library.error import ErrorHandler
from mtkclient.Library.hwcrypto import crypto_setup, hwcrypto from mtkclient.Library.hwcrypto import crypto_setup, hwcrypto
from mtkclient.Library.utils import LogBase, logsetup, find_binary 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 binascii import hexlify
from mtkclient.Library.utils import mtktee from mtkclient.Library.utils import mtktee
import hashlib import hashlib
@ -160,105 +160,10 @@ class legacyext(metaclass=LogBase):
setup.writemem = self.writemem setup.writemem = self.writemem
return hwcrypto(setup, self.loglevel, self.config.gui) 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): def seccfg(self, lockflag):
if lockflag not in ["unlock", "lock"]: if lockflag not in ["unlock", "lock"]:
return False, "Valid flags are: unlock, lock" return False, "Valid flags are: unlock, lock"
hwc = self.cryptosetup() hwc = self.cryptosetup()
sc_org = seccfg(hwc)
data, guid_gpt = self.legacy.partition.get_gpt(self.mtk.config.gpt_settings, "user") data, guid_gpt = self.legacy.partition.get_gpt(self.mtk.config.gpt_settings, "user")
seccfg_data = None seccfg_data = None
partition = None partition = None
@ -272,32 +177,29 @@ class legacyext(metaclass=LogBase):
break break
if seccfg_data is None: if seccfg_data is None:
return False, "Couldn't detect existing seccfg partition. Aborting unlock." return False, "Couldn't detect existing seccfg partition. Aborting unlock."
if seccfg_data[:4] != pack("<I", 0x4D4D4D4D): if seccfg_data[:0xC] == b"AND_SECCFG_v":
# Probe antother seccfg format sc_org = seccfgV3(hwc, self.mtk)
state, msg = self.seccfg_custom_V3(seccfg_data, lockflag, hwc, partition) if not sc_org.parse(seccfg_data):
if state: return False, "V3 Device has is either already unlocked or algo is unknown. Aborting."
return True, msg writedata = sc_org.create(lockflag)
else: else:
self.info(msg) sc_org = seccfgV4(hwc,self.mtk)
if not sc_org.parse(seccfg_data):
return False, "Unknown seccfg partition header. Aborting unlock." return False, "Error on parsing seccfg."
sc_new = seccfgV4(hwc,self.mtk)
if not sc_org.parse(seccfg_data): self.setotp(hwc)
return False, "Error on parsing seccfg." hwtype = "hw"
sc_new = seccfg(hwc) V3 = True
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
sc_new.create(sc_org=sc_org, hwtype=hwtype, V3=V3) 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: if sc_org.hash != sc_new.hash:
return False, "Device has is either already unlocked or algo is unknown. Aborting." V3=False
writedata = sc_new.create(sc_org=None, hwtype=hwtype, lockflag=lockflag, V3=V3) 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, if self.legacy.writeflash(addr=partition.sector * self.mtk.daloader.daconfig.pagesize,
length=len(writedata), length=len(writedata),
filename=None, wdata=writedata, parttype="user", display=True): 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)) open(os.path.join("logs", "hrid.txt"), "wb").write(hexlify(hrid))
""" """
if hwcode == 0x699 and self.config.chipconfig.sej_base: 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: if mtee3:
self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8')) self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8'))
self.config.hwparam.writesetting("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_addr = self.config.chipconfig.meid_addr
meid = b"".join([pack("<I", val) for val in self.readmem(meid_addr, 4)]) meid = b"".join([pack("<I", val) for val in self.readmem(meid_addr, 4)])
if meid != b"": if meid != b"":
otp = self.config.get_otp()
self.info("Generating sej rpmbkey...") self.info("Generating sej rpmbkey...")
self.setotp(hwc) 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: if rpmbkey:
self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8')) self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8'))
self.config.hwparam.writesetting("rpmbkey", hexlify(rpmbkey).decode('utf-8')) self.config.hwparam.writesetting("rpmbkey", hexlify(rpmbkey).decode('utf-8'))
retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8') retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8')
self.info("Generating sej mtee...") 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: if mtee:
self.info("MTEE : " + hexlify(mtee).decode('utf-8')) self.info("MTEE : " + hexlify(mtee).decode('utf-8'))
self.config.hwparam.writesetting("mtee", hexlify(mtee).decode('utf-8')) self.config.hwparam.writesetting("mtee", hexlify(mtee).decode('utf-8'))
retval["mtee"] = hexlify(mtee).decode('utf-8') retval["mtee"] = hexlify(mtee).decode('utf-8')
self.info("Generating sej mtee3...") 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: if mtee3:
self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8')) self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8'))
self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8')) self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8'))

View file

@ -244,6 +244,12 @@ class DAloader(metaclass=LogBase):
else: else:
return self.lft.generate_keys() return self.lft.generate_keys()
def readfuses(self):
if self.xflash:
return self.xft.readfuses()
else:
return self.lft.readfuses()
def is_patched(self): def is_patched(self):
return self.da.patch return self.da.patch

View file

@ -288,13 +288,13 @@ class PLTools(metaclass=LogBase):
self.error("Error on dumping Bootrom.") self.error("Error on dumping Bootrom.")
return False 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: if data is None:
data = bytearray() data = bytearray()
for i in range(32): for i in range(32):
data.append(self.config.meid[i % len(self.config.meid)]) data.append(self.config.meid[i % len(self.config.meid)])
if btype == "": 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 encrypted
return False return False

View file

@ -1,10 +1,15 @@
from struct import unpack, pack from struct import unpack, pack
from mtkclient.Library.utils import structhelper_io
from io import BytesIO
import hashlib 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.hwc = hwc
self.mtk = mtk
self.magic = 0x4D4D4D4D self.magic = 0x4D4D4D4D
self.seccfg_ver = None self.seccfg_ver = None
self.seccfg_size = None self.seccfg_size = None
@ -15,12 +20,18 @@ class seccfg:
self.hash = b"" self.hash = b""
def parse(self, data): def parse(self, data):
seccfg_data = unpack("<IIIIIII", data[:7 * 4]) rf = structhelper_io(BytesIO(bytearray(data)))
self.magic, self.seccfg_ver, self.seccfg_size, self.lock_state, self.critical_lock_state, \ self.magic = rf.dword()
self.sboot_runtime, self.endflag = seccfg_data self.seccfg_ver = rf.dword()
self.hash = data[7 * 4:(7 * 4) + 32] 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: if self.magic != 0x4D4D4D4D or self.endflag != 0x45454545:
self.error("Unknown seccfg structure !") self.error("Unknown V4 seccfg structure !")
return False return False
return True return True
@ -69,5 +80,191 @@ class seccfg:
enc_hash = self.hwc.sej.sej_sec_cfg_hw_V3(dec_hash, True) enc_hash = self.hwc.sej.sej_sec_cfg_hw_V3(dec_hash, True)
self.hash = enc_hash self.hash = enc_hash
data = seccfg_data + enc_hash data = seccfg_data + enc_hash
data += b"\x00" * (0x200 - len(data)) while len(data) % 0x200 != 0:
data += b"\x00"
return bytearray(data) 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())

View file

@ -29,8 +29,6 @@ except ImportError:
from struct import unpack, pack from struct import unpack, pack
from io import BytesIO from io import BytesIO
from io import BytesIO
class mtktee: class mtktee:
magic = None magic = None
hdrlen = None hdrlen = None
@ -805,7 +803,7 @@ def write_object(definition, *args):
return obj 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 Call in a loop to create terminal progress bar
@params: @params:

View file

@ -6,7 +6,7 @@ from mtkclient.config.brom_config import efuse
from mtkclient.Library.error import ErrorHandler, ErrorCodes_XFlash from mtkclient.Library.error import ErrorHandler, ErrorCodes_XFlash
from mtkclient.Library.hwcrypto import crypto_setup, hwcrypto from mtkclient.Library.hwcrypto import crypto_setup, hwcrypto
from mtkclient.Library.utils import LogBase, progress, logsetup, find_binary 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 binascii import hexlify
from mtkclient.Library.utils import mtktee from mtkclient.Library.utils import mtktee
import json import json
@ -372,11 +372,11 @@ class xflashext(metaclass=LogBase):
hwc = self.cryptosetup() hwc = self.cryptosetup()
if self.config.chipconfig.meid_addr: if self.config.chipconfig.meid_addr:
meid = self.config.get_meid() meid = self.config.get_meid()
otp = self.config.get_otp()
if meid != b"\x00" * 16: if meid != b"\x00" * 16:
# self.config.set_meid(meid) # self.config.set_meid(meid)
self.info("Generating sej rpmbkey...") self.info("Generating sej rpmbkey...")
self.setotp(hwc) rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp)
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej")
if rpmbkey is not None: if rpmbkey is not None:
if self.cmd(XCmd.CUSTOM_SET_RPMB_KEY): if self.cmd(XCmd.CUSTOM_SET_RPMB_KEY):
self.xsend(rpmbkey) self.xsend(rpmbkey)
@ -503,8 +503,6 @@ class xflashext(metaclass=LogBase):
def seccfg(self, lockflag): def seccfg(self, lockflag):
if lockflag not in ["unlock", "lock"]: if lockflag not in ["unlock", "lock"]:
return False, "Valid flags are: 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") data, guid_gpt = self.xflash.partition.get_gpt(self.mtk.config.gpt_settings, "user")
seccfg_data = None seccfg_data = None
partition = None partition = None
@ -522,23 +520,29 @@ class xflashext(metaclass=LogBase):
return False, "Couldn't detect existing seccfg partition. Aborting unlock." return False, "Couldn't detect existing seccfg partition. Aborting unlock."
if seccfg_data[:4] != pack("<I", 0x4D4D4D4D): if seccfg_data[:4] != pack("<I", 0x4D4D4D4D):
return False, "Unknown seccfg partition header. Aborting unlock." return False, "Unknown seccfg partition header. Aborting unlock."
hwc = self.cryptosetup()
if not sc_org.parse(seccfg_data): if seccfg_data[:0xC] == b"AND_SECCFG_v":
return False, "Error on parsing seccfg" sc_org = seccfgV3(hwc, self.mtk)
sc_new = seccfg(hwc) if not sc_org.parse(seccfg_data):
self.setotp(hwc) return False, "V3 Device has is either already unlocked or algo is unknown. Aborting."
hwtype = "hw" writedata = sc_org.create(lockflag)
V3 = True else:
sc_new.create(sc_org=sc_org, hwtype=hwtype, V3=V3) sc_org = seccfgV4(hwc, self.mtk)
if sc_org.hash != sc_new.hash: if not sc_org.parse(seccfg_data):
V3 = False 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) 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: if sc_org.hash != sc_new.hash:
return False, "Device has is either already unlocked or algo is unknown. Aborting." V3 = False
writedata = sc_new.create(sc_org=None, hwtype=hwtype, lockflag=lockflag, V3=V3) 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, if self.xflash.writeflash(addr=partition.sector * self.mtk.daloader.daconfig.pagesize,
length=len(writedata), length=len(writedata),
filename=None, wdata=writedata, parttype="user", display=True): filename=None, wdata=writedata, parttype="user", display=True):
@ -569,13 +573,27 @@ class xflashext(metaclass=LogBase):
return data return data
return None 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): def generate_keys(self):
hwc = self.cryptosetup() hwc = self.cryptosetup()
meid = self.config.get_meid() meid = self.config.get_meid()
socid = self.config.get_socid() socid = self.config.get_socid()
hwcode = self.config.get_hwcode() hwcode = self.config.get_hwcode()
cid = self.config.get_cid() cid = self.config.get_cid()
otp = self.config.get_otp()
retval = {} 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: if meid is not None:
self.info("MEID : " + hexlify(meid).decode('utf-8')) self.info("MEID : " + hexlify(meid).decode('utf-8'))
retval["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.config.set_meid(meid)
self.info("Generating sej rpmbkey...") self.info("Generating sej rpmbkey...")
self.setotp(hwc) 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: if rpmbkey:
self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8')) self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8'))
self.config.hwparam.writesetting("rpmbkey", hexlify(rpmbkey).decode('utf-8')) self.config.hwparam.writesetting("rpmbkey", hexlify(rpmbkey).decode('utf-8'))
retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8') retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8')
self.info("Generating sej mtee...") 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: if mtee:
self.config.hwparam.writesetting("mtee", hexlify(mtee).decode('utf-8')) self.config.hwparam.writesetting("mtee", hexlify(mtee).decode('utf-8'))
self.info("MTEE : " + hexlify(mtee).decode('utf-8')) self.info("MTEE : " + hexlify(mtee).decode('utf-8'))
retval["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: if mtee3:
self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8')) self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8'))
self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8')) self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8'))

View file

@ -66,6 +66,7 @@ class Mtk_Config(metaclass=LogBase):
self.hwparam_path = "logs" self.hwparam_path = "logs"
self.sram = None self.sram = None
self.dram = None self.dram = None
self.otp = None
if loglevel == logging.DEBUG: if loglevel == logging.DEBUG:
logfilename = os.path.join("logs", "log.txt") logfilename = os.path.join("logs", "log.txt")
fh = logging.FileHandler(logfilename) fh = logging.FileHandler(logfilename)
@ -108,6 +109,22 @@ class Mtk_Config(metaclass=LogBase):
self.meid = meid self.meid = meid
self.hwparam.writesetting("meid", hexlify(meid).decode('utf-8')) 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): def get_meid(self):
if self.meid is None: if self.meid is None:
if self.peek is not None: if self.peek is not None:

8
stage2
View file

@ -444,25 +444,25 @@ class Stage2(metaclass=LogBase):
retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8') retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8')
return retval, keyinfo return retval, keyinfo
if mode == "sej_aes_decrypt": 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+="\n"
keyinfo+="Data: " + hexlify(dec_data).decode('utf-8') keyinfo+="Data: " + hexlify(dec_data).decode('utf-8')
keyinfo+="\n" keyinfo+="\n"
return dec_data, keyinfo return dec_data, keyinfo
elif mode == "sej_aes_encrypt": 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+="\n"
keyinfo+="Data: " + hexlify(enc_data).decode('utf-8') keyinfo+="Data: " + hexlify(enc_data).decode('utf-8')
keyinfo+="\n" keyinfo+="\n"
return enc_data, keyinfo return enc_data, keyinfo
elif mode == "sej_sst_decrypt": 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+="\n"
keyinfo+="Data: " + hexlify(dec_data).decode('utf-8') keyinfo+="Data: " + hexlify(dec_data).decode('utf-8')
keyinfo+="\n" keyinfo+="\n"
return dec_data, keyinfo return dec_data, keyinfo
elif mode == "sej_sst_encrypt": 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 += "\n"
keyinfo += "Data: " + hexlify(enc_data).decode('utf-8') keyinfo += "Data: " + hexlify(enc_data).decode('utf-8')
keyinfo += "\n" keyinfo += "\n"