mirror of
https://github.com/openharmony/tee_tee_dev_kit.git
synced 2026-08-25 09:09:44 -04:00
a562013114
Signed-off-by: liyuxuan_hw <447978021@qq.com>
425 lines
15 KiB
Python
425 lines
15 KiB
Python
#!/usr/bin/env python
|
|
# coding:utf-8
|
|
|
|
#
|
|
# Copyright (C) 2022 Huawei Technologies Co., Ltd.
|
|
# Licensed under the Mulan PSL v2.
|
|
# You can use this software according to the terms and conditions of the Mulan
|
|
# PSL v2.
|
|
# You may obtain a copy of Mulan PSL v2 at:
|
|
# http://license.coscl.org.cn/MulanPSL2
|
|
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
|
|
# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
# NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
# See the Mulan PSL v2 for more details.
|
|
#
|
|
|
|
import string
|
|
import struct
|
|
import uuid
|
|
import os
|
|
import re
|
|
import stat
|
|
import logging
|
|
|
|
|
|
PRODUCT_TA_IMAGE = 1
|
|
PRODUCT_DYN_LIB = 2
|
|
PRODUCT_SERVICE_IMAGE = 3
|
|
PRODUCT_CLIENT_IMAGE = 4
|
|
PRODUCT_DRIVER_IMAGE = 5
|
|
logging.basicConfig(level=logging.INFO)
|
|
|
|
|
|
class PackUuid:
|
|
# Structure object to align and package the TEE_UUID
|
|
data = struct.Struct('IHH8b')
|
|
|
|
def __init__(self, data):
|
|
unpacked_data = (PackUuid.data).unpack(str.encode(data))
|
|
self.unpacked_data = unpacked_data
|
|
self.time_low = unpacked_data[0]
|
|
self.time_mid = unpacked_data[1]
|
|
self.time_hi_version = unpacked_data[2]
|
|
self.clock_seq_node = unpacked_data[3]
|
|
|
|
def print_values(self):
|
|
logging.info("ATTRIBUTE / VALUE")
|
|
for attr, value in self.__dict__.items():
|
|
logging.info(attr, value)
|
|
|
|
def get_pack_data(self):
|
|
values = [self.time_low,
|
|
self.time_mid,
|
|
self.time_hi_version,
|
|
self.clock_seq_node,
|
|
]
|
|
|
|
return (PackUuid.data).pack(*values)
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# Manifest
|
|
#----------------------------------------------------------------------------
|
|
class Manifest:
|
|
|
|
# Structure object to align and package the Manifest
|
|
data = struct.Struct('I' * 6)
|
|
|
|
def __init__(self, data):
|
|
unpacked_data = (Manifest.data).unpack(str.encode(data))
|
|
self.unpacked_data = unpacked_data
|
|
self.single_instance = unpacked_data[0]
|
|
self.multi_session = unpacked_data[1]
|
|
self.multi_command = unpacked_data[2]
|
|
self.heap_size = unpacked_data[3]
|
|
self.stack_size = unpacked_data[4]
|
|
self.instancekeepalive = unpacked_data[5]
|
|
|
|
def print_values(self):
|
|
logging.info("ATTRIBUTE / VALUE")
|
|
for attr, value in self.__dict__.items():
|
|
logging.info(attr, value)
|
|
|
|
def get_pack_data(self):
|
|
values = [self.single_instance,
|
|
self.multi_session,
|
|
self.multi_command,
|
|
self.heap_size,
|
|
self.stack_size,
|
|
self.instancekeepalive,
|
|
]
|
|
|
|
return (Manifest.data).pack(*values)
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# verify property name in manifest file
|
|
#----------------------------------------------------------------------------
|
|
def verify_property_name(str_line):
|
|
logging.info("verify property name")
|
|
alphas = string.ascii_letters + string.digits
|
|
cont = "".join([alphas, '-', '_', '.'])
|
|
if len(str_line) > 1:
|
|
if str_line[0] not in alphas:
|
|
logging.error("invalid first letter in property name")
|
|
return False
|
|
else:
|
|
for otherchar in str_line[1:]:
|
|
if otherchar not in cont:
|
|
logging.error("invalid char in property name")
|
|
return False
|
|
else:
|
|
logging.error("invalid property name")
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# verify property value in manifest file
|
|
#----------------------------------------------------------------------------
|
|
def verify_property_value(str_line):
|
|
logging.info("verify property value")
|
|
filt_letter = chr(0) + chr(10) + chr(13)
|
|
for thechar in str_line:
|
|
if thechar in filt_letter:
|
|
logging.error("invalid letter in prop value")
|
|
return False
|
|
return True
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# remove tabs and space in property value
|
|
#----------------------------------------------------------------------------
|
|
def trailing_space_tabs(str_line):
|
|
logging.info('trailing space tabs in value head and trail')
|
|
space_tabs = chr(9) + chr(32) + chr(160)
|
|
space_tabs_newlines = space_tabs + chr(10) + chr(13)
|
|
|
|
index = 0
|
|
for thechar in str_line:
|
|
if thechar in space_tabs:
|
|
index += 1
|
|
else:
|
|
break
|
|
headvalue = str_line[index:]
|
|
|
|
strlen = len(headvalue)
|
|
|
|
strlen -= 1
|
|
|
|
while strlen > 0:
|
|
if headvalue[strlen] in space_tabs_newlines:
|
|
strlen -= 1
|
|
else:
|
|
break
|
|
|
|
str_ret = headvalue[0:strlen + 1] + chr(10)
|
|
logging.info("str ret: %s", str_ret)
|
|
|
|
return str_ret
|
|
|
|
|
|
def update_target_type(target_info):
|
|
# dyn_conf_target_type is 1 means that is drv
|
|
dyn_conf_target_type = target_info.dyn_conf_target_type
|
|
service_name = target_info.service_name
|
|
target_type = target_info.target_type
|
|
service_name_len = len(service_name)
|
|
logging.info("service name: %s", service_name)
|
|
logging.info("service name len: %d", service_name_len)
|
|
|
|
max_service_len = 36
|
|
if dyn_conf_target_type == 1:
|
|
target_type = PRODUCT_DRIVER_IMAGE
|
|
if dyn_conf_target_type == 3:
|
|
target_type = PRODUCT_SERVICE_IMAGE
|
|
if dyn_conf_target_type == 4:
|
|
target_type = PRODUCT_CLIENT_IMAGE
|
|
|
|
if not re.match(r"^[A-Za-z0-9_-]*$", service_name):
|
|
logging.error("service name only can use [A-Z] [a-z] [0-9] '-' and '_'")
|
|
return (False, 0)
|
|
|
|
if service_name_len > max_service_len:
|
|
logging.error("service name len cannot larger than %s", str(max_service_len))
|
|
return (False, 0)
|
|
return (True, target_type)
|
|
|
|
|
|
class TargetInfo:
|
|
def __init__(self, dyn_conf_target_type, service_name, target_type, uuid_val):
|
|
self.dyn_conf_target_type = dyn_conf_target_type
|
|
self.service_name = service_name
|
|
self.target_type = target_type
|
|
self.uuid_val = uuid_val
|
|
|
|
|
|
def init_data_val():
|
|
#manifest default
|
|
manifest_val = Manifest('\0'*24)
|
|
manifest_val.single_instance = 1
|
|
manifest_val.multi_session = 0
|
|
manifest_val.multi_command = 0
|
|
manifest_val.instancekeepalive = 0
|
|
manifest_val.heap_size = 16384
|
|
manifest_val.stack_size = 2048
|
|
|
|
uuid_val = PackUuid('\0' * 16)
|
|
target_type = PRODUCT_TA_IMAGE
|
|
service_name = 'external_service'
|
|
dyn_conf_target_type = 0
|
|
target_info = TargetInfo(dyn_conf_target_type, service_name, target_type, uuid_val)
|
|
return manifest_val, target_info
|
|
|
|
|
|
def update_manifest_info(prop_value_v, val, prop_name_low):
|
|
prop_value_low = prop_value_v.lower()
|
|
if 'true' == prop_value_low:
|
|
val = 1
|
|
elif 'false' == prop_value_low:
|
|
val = 0
|
|
else:
|
|
logging.error("%s value error!", prop_name_low)
|
|
return val
|
|
|
|
|
|
def check_prop_info(prop_name, prop_value_v):
|
|
if verify_property_name(prop_name) is False:
|
|
logging.error("manifest format invalid, please check it")
|
|
return False
|
|
|
|
if verify_property_value(prop_value_v) is False:
|
|
logging.error("manifest format invalid, please check it")
|
|
return False
|
|
return True
|
|
|
|
|
|
class PropInfo:
|
|
def __init__(self, prop_name, prop_name_t, prop_value_t):
|
|
self.prop_name = prop_name
|
|
self.prop_name_t = prop_name_t
|
|
self.prop_value_t = prop_value_t
|
|
|
|
def get_prop_value(self):
|
|
prop_value_t = self.prop_value_t
|
|
prop_value = trailing_space_tabs(prop_value_t)
|
|
prop_len = len(prop_value)
|
|
prop_value_v = prop_value[0:prop_len - 1]
|
|
logging.info("prop value_v: %s", prop_value_v)
|
|
return prop_value, prop_value_v
|
|
|
|
|
|
def parse_prop_info(manifest_val, prop_info, mani_ext_fp, target_info):
|
|
prop_value, prop_value_v = PropInfo.get_prop_value(prop_info)
|
|
prop_name = prop_info.prop_name
|
|
prop_name_t = prop_info.prop_name_t
|
|
|
|
if not check_prop_info(prop_name, prop_value_v):
|
|
return (False, 0, 0)
|
|
|
|
# name:value to lowcase, and parse manifest
|
|
prop_name_low = prop_name.lower()
|
|
logging.info("name lower: %s", prop_name_low)
|
|
if 'gpd.ta.appid' == prop_name_low:
|
|
logging.info("compare name is srv id")
|
|
target_info.uuid_val = uuid.UUID(prop_value_v)
|
|
logging.info("uuid str %s", target_info.uuid_val)
|
|
logging.info("val fields %s", target_info.uuid_val.fields)
|
|
|
|
elif 'gpd.ta.singleinstance' == prop_name_low:
|
|
manifest_val.single_instance = update_manifest_info(prop_value_v, manifest_val.single_instance, \
|
|
prop_name_low)
|
|
elif 'gpd.ta.multisession' == prop_name_low:
|
|
manifest_val.multi_session = update_manifest_info(prop_value_v, manifest_val.multi_session, \
|
|
prop_name_low)
|
|
elif 'gpd.ta.multicommand' == prop_name_low:
|
|
manifest_val.multi_command = update_manifest_info(prop_value_v, manifest_val.multi_command, \
|
|
prop_name_low)
|
|
elif 'gpd.ta.instancekeepalive' == prop_name_low:
|
|
manifest_val.instancekeepalive = update_manifest_info(prop_value_v, manifest_val.instancekeepalive, \
|
|
prop_name_low)
|
|
elif 'gpd.ta.datasize' == prop_name_low:
|
|
manifest_val.heap_size = int(prop_value_v)
|
|
logging.info('b')
|
|
elif 'gpd.ta.stacksize' == prop_name_low:
|
|
manifest_val.stack_size = int(prop_value_v)
|
|
logging.info('b')
|
|
elif 'gpd.ta.service_name' == prop_name_low:
|
|
target_info.service_name = prop_value_v
|
|
logging.info('b')
|
|
elif 'gpd.ta.dynconf' == prop_name_low:
|
|
logging.error("gpd.ta.dynConf is reserved, cannot set")
|
|
return (False, 0, 0)
|
|
else:
|
|
logging.info('b')
|
|
#write have not paresed manifest into sample.manifest file
|
|
mani_ext_fp.write(str.encode(prop_name_t))
|
|
mani_ext_fp.write(str.encode(prop_value))
|
|
if 'gpd.ta.is_lib' == prop_name_low:
|
|
if 'true' == prop_value_v.lower():
|
|
target_info.target_type = PRODUCT_DYN_LIB
|
|
elif 'gpd.ta.target_type' == prop_name_low:
|
|
target_info.dyn_conf_target_type = int(prop_value_v)
|
|
if target_info.dyn_conf_target_type > 0xFFFF or target_info.dyn_conf_target_type < 0:
|
|
logging.error("gpd.ta.target_type must in range [0, 0xFFFF]")
|
|
return (False, 0, 0)
|
|
return (True, manifest_val, target_info)
|
|
|
|
|
|
def gen_product_name(uuid_val, target_info):
|
|
service_name = target_info.service_name
|
|
target_type = target_info.target_type
|
|
uuid_str = str(uuid_val)
|
|
product_name = str(uuid_val)
|
|
if target_type == PRODUCT_TA_IMAGE:
|
|
logging.info("product type is ta image")
|
|
product_name = "".join([uuid_str, ".sec"])
|
|
elif target_type == PRODUCT_DRIVER_IMAGE:
|
|
logging.info("product type is driver")
|
|
product_name = "".join([service_name, ".sec"])
|
|
elif target_type == PRODUCT_SERVICE_IMAGE:
|
|
logging.info("product type is service")
|
|
product_name = "".join([service_name, ".sec"])
|
|
elif target_type == PRODUCT_CLIENT_IMAGE:
|
|
logging.info("product type is client")
|
|
product_name = "".join([service_name, ".so.sec"])
|
|
elif target_type == PRODUCT_DYN_LIB:
|
|
logging.info("product type is dyn lib")
|
|
product_name = "".join([uuid_str, service_name, ".so.sec"])
|
|
else:
|
|
logging.error("invalid product type!")
|
|
return (False, 0, 0)
|
|
return (True, product_name, uuid_str)
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# verify manifest file, parse manifest file, generate a new manfiest file
|
|
#----------------------------------------------------------------------------
|
|
def parser_manifest(manifest, manifest_data_path, mani_ext):
|
|
logging.info("verify manifest")
|
|
manifest_val, target_info = init_data_val()
|
|
|
|
with open(manifest, 'r') as mani_fp:
|
|
fd_ext = os.open(mani_ext, os.O_WRONLY | os.O_CREAT, \
|
|
stat.S_IWUSR | stat.S_IRUSR)
|
|
mani_ext_fp = os.fdopen(fd_ext, "wb")
|
|
for each_line in mani_fp:
|
|
logging.info(each_line)
|
|
if each_line.startswith("#") or not each_line.strip():
|
|
continue
|
|
index = each_line.find(':', 1, len(each_line))
|
|
|
|
prop_name = each_line[0:index]
|
|
prop_name_t = each_line[0:index + 1]
|
|
prop_value_t = each_line[index + 1:]
|
|
prop_info = PropInfo(prop_name, prop_name_t, prop_value_t)
|
|
logging.info("name is: %s; value is: %s", prop_name, prop_value_t)
|
|
|
|
result, manifest_val, target_info = parse_prop_info(manifest_val, prop_info, \
|
|
mani_ext_fp, target_info)
|
|
if result is False:
|
|
mani_ext_fp.close()
|
|
return (False, 0, 0, None)
|
|
mani_ext_fp.close()
|
|
#write the whole parsed manifest into sample.manifest file
|
|
uuid_val = target_info.uuid_val
|
|
ret, target_info.target_type = update_target_type(target_info)
|
|
if ret is False:
|
|
return (False, 0, 0, None)
|
|
|
|
# get manifest string file len
|
|
manifest_str_size = os.path.getsize(mani_ext)
|
|
logging.info('manifest str size %d', manifest_str_size)
|
|
|
|
# 2> manifest + service_name
|
|
logging.info("bytes len %d", len(uuid_val.bytes_le))
|
|
logging.info("bytes len %d", len(manifest_val.get_pack_data()))
|
|
logging.info("bytes len %d", len(target_info.service_name))
|
|
|
|
# 3> unparsed manifest, string manifest
|
|
with open(mani_ext, 'rb') as string_mani_fp:
|
|
logging.info("read manifest string size %d", manifest_str_size)
|
|
manifest_string_buf = string_mani_fp.read(manifest_str_size)
|
|
logging.info("manifest strint: %s", manifest_string_buf)
|
|
|
|
#---- write manifest parse context to manifest file
|
|
fd_out = os.open(manifest_data_path, os.O_WRONLY | os.O_CREAT, \
|
|
stat.S_IWUSR | stat.S_IRUSR)
|
|
out_manifest_fp = os.fdopen(fd_out, "wb")
|
|
out_manifest_fp.write(uuid_val.bytes_le)
|
|
out_manifest_fp.write(str.encode(target_info.service_name))
|
|
out_manifest_fp.write(manifest_val.get_pack_data())
|
|
out_manifest_fp.close()
|
|
ret, product_name, uuid_str = gen_product_name(uuid_val, target_info)
|
|
if ret is False:
|
|
return (False, 0, 0, None)
|
|
|
|
return (True, product_name, uuid_str, manifest_val)
|
|
|
|
|
|
class ManifestInfo:
|
|
''' get manifest info '''
|
|
def __init__(self, ret, product_name, uuid_str, manifest_txt_exist):
|
|
self.ret = ret
|
|
self.product_name = product_name
|
|
self.uuid_str = uuid_str
|
|
self.manifest_txt_exist = manifest_txt_exist
|
|
|
|
|
|
def process_manifest_file(xml_config_path, manifest_path, \
|
|
manifest_data_path, mani_ext):
|
|
|
|
manifest_txt_exist = True
|
|
if not os.path.exists(manifest_path):
|
|
logging.info("xml trans manifest cfg")
|
|
manifest_txt_exist = False
|
|
from xml_trans_manifest import trans_xml_to_manifest
|
|
trans_xml_to_manifest(xml_config_path, manifest_path)
|
|
|
|
ret, product_name, uuid_str, manifest_val = parser_manifest(manifest_path, \
|
|
manifest_data_path, mani_ext)
|
|
manifest_info = ManifestInfo(ret, product_name, uuid_str, manifest_txt_exist)
|
|
return manifest_info, manifest_val
|