207 lines
6.4 KiB
Python
Executable File
207 lines
6.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# Copyright (C) 2021 Amlogic, Inc. All rights reserved.
|
|
#
|
|
# This source code is subject to the terms and conditions defined in the
|
|
# file 'LICENSE' which is part of this source code package.
|
|
|
|
ALGO = 'gen-prot-aes128'
|
|
MRK_NAME = 'DGPK2'
|
|
EK3 = 'a1f9288d5e382b34a2897e9194ee2911'
|
|
EK2 = '754ac2fdb002e3fa13407d3367ce293d'
|
|
#EK1 = '8b8f5a227bb1c1487d21a0fd6d842833'
|
|
|
|
TARGET_NAME = 'dac'
|
|
MAX_IDX = 100000000
|
|
DERIVED_FILE_NUM = 0
|
|
|
|
def get_args():
|
|
from argparse import ArgumentParser
|
|
|
|
parser = ArgumentParser()
|
|
parser.add_argument('--soc', type = str, required = True, help = 'soc')
|
|
parser.add_argument('--key_tool', type = str, required = True, help = 'vendor key tool path')
|
|
parser.add_argument('--pfpk_hmac_generator', type = str, required = True, help = 'pfpk hmac generator path')
|
|
parser.add_argument('--dgpk2', type = str, default = '', help = 'dgpk2 file or directory')
|
|
parser.add_argument('--pfid', type = str, default = '', help = 'pfid file or directory')
|
|
parser.add_argument('--pfpk_hmac', type = str, default = '', help = 'pfpk_hmac file or directory')
|
|
parser.add_argument('--nonce', type = str, default = '', help = 'nonce file or nonce hex string')
|
|
parser.add_argument('--segid', type = str, default = '', help = 'segid file or segid hex string')
|
|
parser.add_argument('--enhance', nargs = '?', default = None, const = True, help = 'enable security enhanced mode')
|
|
parser.add_argument('--stage', type = str, default = '2', help = 'boot stage string')
|
|
parser.add_argument('--out_dir', type = str, required = True, help = 'output directory')
|
|
return parser.parse_args()
|
|
|
|
def derive_one_dac(file_dgpk2, file_pfid, out_dir, idx, key_tool, soc, pfpk_hmac_generator, nonce, segid, stage, enhance):
|
|
import os
|
|
import sys
|
|
import binascii
|
|
import hmac
|
|
import hashlib
|
|
|
|
if int(idx) > MAX_IDX:
|
|
print('the number of files exceeds the limit')
|
|
sys.exit(1)
|
|
|
|
f = open(file_dgpk2, 'rb')
|
|
mrk = f.read()
|
|
f.close()
|
|
|
|
f = open(file_pfid, 'rb')
|
|
ek1 = f.read()
|
|
f.close()
|
|
|
|
if os.path.isfile(segid):
|
|
f = open(segid, 'rb')
|
|
segid = f.read()
|
|
f.close()
|
|
else:
|
|
segid = binascii.unhexlify(segid)
|
|
if len(segid) == 4:
|
|
ek1 = ek1[:4] + segid + ek1[8:]
|
|
elif len(segid):
|
|
print('segid length error')
|
|
sys.exit(1)
|
|
|
|
if os.path.isfile(nonce):
|
|
f = open(nonce, 'rb')
|
|
nonce = f.read()
|
|
f.close()
|
|
else:
|
|
nonce = binascii.unhexlify(nonce)
|
|
|
|
# due to the other para aren't supported, can only use "SC2"
|
|
cmd = key_tool + ' ' + ALGO + ' --chipset=SC2' \
|
|
+ ' --mrk=' + bytes.decode(binascii.b2a_hex(mrk)) \
|
|
+ ' --mrk-name=' + MRK_NAME + ' --boot-stage=' + stage \
|
|
+ ' --ek3=' + EK3 + ' --ek2=' + EK2 \
|
|
+ ' --ek1=' + bytes.decode(binascii.b2a_hex(ek1))
|
|
pfpk = os.popen(cmd).read()[:32]
|
|
|
|
if enhance is True:
|
|
cmd = pfpk_hmac_generator + ' -p ' + pfpk + ' -e '
|
|
else:
|
|
cmd = pfpk_hmac_generator + ' -p ' + pfpk
|
|
|
|
pfpk_hmac = binascii.unhexlify((os.popen(cmd).read())[:64])
|
|
|
|
dac = hmac.HMAC(pfpk_hmac, ek1 + nonce, hashlib.sha256).digest()
|
|
|
|
file_dac = out_dir + '/' + soc + '_' + TARGET_NAME + '_' + idx + '.bin'
|
|
f = open(file_dac, 'wb')
|
|
f.write(dac)
|
|
f.close()
|
|
|
|
global DERIVED_FILE_NUM
|
|
DERIVED_FILE_NUM = DERIVED_FILE_NUM + 1
|
|
print(os.path.abspath(file_dac) + ' derived successfully')
|
|
|
|
def derive_one_dac_by_pfpk_hmac(file_pfpk_hmac, file_pfid, out_dir, idx, soc, nonce, segid):
|
|
import os
|
|
import sys
|
|
import binascii
|
|
import hmac
|
|
import hashlib
|
|
|
|
if int(idx) > MAX_IDX:
|
|
print('the number of files exceeds the limit')
|
|
sys.exit(1)
|
|
|
|
f = open(file_pfpk_hmac, 'rb')
|
|
pfpk_hmac = f.read()
|
|
f.close()
|
|
|
|
f = open(file_pfid, 'rb')
|
|
ek1 = f.read()
|
|
f.close()
|
|
|
|
if os.path.isfile(segid):
|
|
f = open(segid, 'rb')
|
|
segid = f.read()
|
|
f.close()
|
|
else:
|
|
segid = binascii.unhexlify(segid)
|
|
if len(segid) == 4:
|
|
ek1 = ek1[:4] + segid + ek1[8:]
|
|
elif len(segid):
|
|
print('segid length error')
|
|
sys.exit(1)
|
|
|
|
if os.path.isfile(nonce):
|
|
f = open(nonce, 'rb')
|
|
nonce = f.read()
|
|
f.close()
|
|
else:
|
|
nonce = binascii.unhexlify(nonce)
|
|
|
|
dac = hmac.HMAC(pfpk_hmac, ek1 + nonce, hashlib.sha256).digest()
|
|
|
|
file_dac = out_dir + '/' + soc + '_' + TARGET_NAME + '_' + idx + '.bin'
|
|
f = open(file_dac, 'wb')
|
|
f.write(dac)
|
|
f.close()
|
|
|
|
global DERIVED_FILE_NUM
|
|
DERIVED_FILE_NUM = DERIVED_FILE_NUM + 1
|
|
print(os.path.abspath(file_dac) + ' derived successfully')
|
|
|
|
def main():
|
|
import os
|
|
import sys
|
|
|
|
args = get_args()
|
|
|
|
if not os.path.exists(args.key_tool):
|
|
print(args.key_tool + ' not exist')
|
|
sys.exit(1)
|
|
|
|
if not os.path.exists(args.pfpk_hmac):
|
|
if not os.path.exists(args.pfpk_hmac_generator):
|
|
print(args.pfpk_hmac_generator + ' not exist')
|
|
sys.exit(1)
|
|
if not os.path.exists(args.dgpk2):
|
|
print('dgpk2 not exist')
|
|
sys.exit(1)
|
|
if not os.path.exists(args.pfid):
|
|
print('pfid not exist')
|
|
sys.exit(1)
|
|
else:
|
|
if not os.path.exists(args.pfid):
|
|
print('pfid not exist')
|
|
sys.exit(1)
|
|
if os.path.exists(args.dgpk2):
|
|
print(args.dgpk2 + ' is not necessary')
|
|
sys.exit(1)
|
|
|
|
if not os.path.exists(args.out_dir):
|
|
os.mkdir(args.out_dir)
|
|
|
|
if os.path.isfile(args.dgpk2) and os.path.isfile(args.pfid):
|
|
derive_one_dac(args.dgpk2, args.pfid, args.out_dir, '000000001', args.key_tool, args.soc, args.pfpk_hmac_generator, args.nonce, args.segid, args.stage, args.enhance)
|
|
elif os.path.isdir(args.dgpk2) and os.path.isdir(args.pfid):
|
|
for parent, dnames, fnames in os.walk(args.dgpk2):
|
|
for fname in fnames:
|
|
idx = fname[-13 : -4]
|
|
file_pfid = args.pfid + '/' + args.soc + '_pfid_' + idx + '.bin'
|
|
file_dgpk2 = os.path.join(parent, fname)
|
|
if os.path.exists(file_pfid):
|
|
derive_one_dac(file_dgpk2, file_pfid, args.out_dir, idx, args.key_tool, args.soc, args.pfpk_hmac_generator, args.nonce, args.segid, args.stage, args.enhance)
|
|
elif os.path.isfile(args.pfpk_hmac) and os.path.isfile(args.pfid):
|
|
derive_one_dac_by_pfpk_hmac(args.pfpk_hmac, args.pfid, args.out_dir, '000000001', args.soc, args.nonce, args.segid)
|
|
elif os.path.isdir(args.pfpk_hmac) and os.path.isdir(args.pfid):
|
|
for parent, dnames, fnames in os.walk(args.pfpk_hmac):
|
|
for fname in fnames:
|
|
idx = fname[-13 : -4]
|
|
file_pfid = args.pfid + '/' + args.soc + '_pfid_' + idx + '.bin'
|
|
file_pfpk_hmac = os.path.join(parent, fname)
|
|
if os.path.exists(file_pfid):
|
|
derive_one_dac_by_pfpk_hmac(file_pfpk_hmac, file_pfid, args.out_dir, idx, args.soc, args.nonce, args.segid)
|
|
else:
|
|
print('input parameter error')
|
|
sys.exit(1)
|
|
|
|
print(str(DERIVED_FILE_NUM) + ' ' + TARGET_NAME + ' files derived successfully')
|
|
|
|
if __name__ == '__main__':
|
|
main()
|