sign_file.py
#!/usr/bin/env python
import os
import sys
import struct
import hashlib
import zipfile
import time
import shutil
import paramiko
import requests
import json
import binascii
from requests.packages.urllib3.exceptions import InsecureRequestWarning
DEFAULT_CONFIG_FILE="/etc/pax_sign/sign.conf"
def get_file_mark(src_file):
filename = os.path.basename(src_file)
dict = {"monitor.fex": "monitor", "optee.fex": "optee", "u-boot.fex": "u-boot", "scp.fex": "scp",
"env.fex": "env", "verity_block.fex": "verity_block", "boot-resource.fex": "bootloader",
"toc0.fex": "toc0", "toc1.fex": "toc1", "recovery.img": "recovery", "boot.img": "boot",
"tempboot.img": "boot","recovery.fex": "recovery", "boot.fex": "boot"}
# print "filename:%s, dictname:%s" % (filename,dict[filename])
# print dict.keys()
list_dict = dict.keys()
if filename in list_dict:
# print "filename:%s, dictname:%s" % (filename, dict[filename])
mark = dict[filename]
else:
print "#####can not find file %s####" % filename
mark = None
return mark
def pack_file(src_file, file_tail=None):
f = open(src_file,"rb+")
f_content = f.read()
f.close()
h = hashlib.new("sha256")
mark = get_file_mark(src_file)
if mark is not None:
h.update(f_content + mark)
else:
h.update(f_content)
digest = h.digest()
# print (digest)
file_tail = b"PAX-QCM-AFW-HSET"
if "2.7" in sys.version:
format_byte = "\x01"
SourceType_byte = "\x24"
time_byte = time.strftime("%Y%m%d%H%M%S", time.localtime())
MechineCode_byte = "\x0088888888"
head_byte = "\x00"
tail_byte = "\xbc"
pad_byte = "\xbb"
# 256 - head(1) - format(1) - SourceType(1) - time(14) - MechineCode(8) - hash(32) - tail(1)
pad_length = 198
digest_byte = digest
pad_string = ""
for i in range(pad_length):
pad_string = pad_string + pad_byte
pack_format = "ccc14s8s" + str(pad_length) + "s" + "32sc"
pack_content = struct.pack(pack_format, head_byte, format_byte, SourceType_byte, time_byte, MechineCode_byte,
pad_string, digest_byte, tail_byte)
else:
format_byte = 0x01
SourceType_byte = 0x24
time_str = time.strftime("%Y%m%d%H%M%S", time.localtime())
time_byte = time_str.encode("ascii")
MechineCode_byte = b"\x0088888888"
head_byte = 0
tail_byte = 0xbc
pad_byte = "bb"
# 256 - head(1) - format(1) - SourceType(1) - time(14) - MechineCode(8) - hash(32) - tail(1)
pad_length = 198
pad_string = "bb"
for i in range(pad_length):
pad_string = pad_string + pad_byte
pad_string = bytearray.fromhex(pad_string)
pack_format = "BBB14s8s" + str(pad_length) + "s" + "32sB"
pack_content = struct.pack(pack_format,head_byte,format_byte,SourceType_byte,time_byte,MechineCode_byte,pad_string,digest,tail_byte)
print (pack_content)
return pack_content
def sign_file(src_data):
tools = NewTools(DEFAULT_CONFIG_FILE)
data = tools.sign(src_data)
return data
def pack_and_sign_file(src_file):
pack_data = pack_file(src_file)
signed_data = sign_file(pack_data)
if signed_data is None:
print ("sing file"+ src_file + "error......")
sys.exit(-1)
filesize = os.path.getsize(src_file)
f_src = open(src_file,"ab+")
mark = get_file_mark(src_file)
# f_src_content = f_src.read()
if is_system_partition(src_file):
print ("#### is system_ext.img file###")
signtail = struct.pack("<III16s", 256, 0, filesize, "SIGNED_VER:00001")
save_system_sign_data(signed_data + signtail)
else:
if mark is not None:
signtail = struct.pack("<III16s", 256, 0, filesize + len(mark), "SIGNED_VER:00001")
f_src.write(mark +signed_data + signtail)
else:
signtail = struct.pack("<III16s", 256, 0, filesize, "SIGNED_VER:00001")
f_src.write(signed_data + signtail)
f_src.close()
def is_system_partition(file):
filename = os.path.basename(file)
if filename == 'system_ext.img':
return True
else:
return False
def save_system_sign_data(data):
file = open("system_verity.fex", "wb+")
file.write(data)
file.close()
class NewTools (object):
''' sign file by https ,use the new hms sign server'''
def __init__(self, config_file=None):
if config_file is None:
config_file = DEFAULT_CONFIG_FILE
file = open(config_file, "r")
file_content = file.read()
str = json.loads(file_content)
# print (str)
self.server_url = str['server_url']
self.cert_path = str['cert_path']
def sign(self, data=None):
if data is None:
return None;
ascii_data = binascii.b2a_hex(data)
src_json_data = {'data' : ascii_data}
# print (src_json_data)
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
ret = requests.post(self.server_url, data=src_json_data, cert=self.cert_path, verify=False)
# print (ret.json())
ret_json_data = ret.json()
if ret_json_data['success'] is True:
# print (ret_json_data['data'])
signed_data = binascii.a2b_hex(ret_json_data['data'])
else:
signed_data = None
print (ret_json_data['message'])
return signed_data
if __name__ == '__main__':
print (sys.argv)
input_file_list = sys.argv[1:]
input_file_list.sort()
for input_file in input_file_list:
pack_and_sign_file(input_file)