• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# coding:utf-8
3
4#
5# Copyright (C) 2022 Huawei Technologies Co., Ltd.
6# Licensed under the Mulan PSL v2.
7# You can use this software according to the terms and conditions of the Mulan
8# PSL v2.
9# You may obtain a copy of Mulan PSL v2 at:
10#     http://license.coscl.org.cn/MulanPSL2
11# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
12# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
13# NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14# See the Mulan PSL v2 for more details.
15#
16
17import hashlib
18from ctypes import sizeof
19from ctypes import c_uint32
20from ctypes import create_string_buffer
21from ctypes import memmove
22from ctypes import byref
23import binascii
24import struct
25import logging
26import os
27import xml.etree.ElementTree as ET
28
29logging.basicConfig(level=logging.INFO,
30                    format='%(asctime)s line:%(lineno)d %(levelname)s:%(name)s:%(message)s',
31                    datefmt='%H:%M:%S'
32                    )
33
34MAX_PKGNAME_LEN = 256
35MAX_USERNAME_LEN = 256
36MAX_MODULUS_LEN = 1024
37MAX_PUB_EXP_LEN = 256
38
39
40def print_hash(byte_buf):
41    buf = [hex(int(i)) for i in byte_buf]
42    output = " ".join(buf)
43    logging.info("caller hash: %s", output)
44
45
46def check_native_ca_item(item):
47    if item.tag != "item" or len(item.attrib) != 2:
48        raise RuntimeError("invalid item attrib", item.tag, item.attrib, len(item.attrib))
49
50
51def check_app_ca_item(item):
52    if item.tag != "item" or len(item.attrib) != 3:
53        raise RuntimeError("invalid item attrib", item.tag, item.attrib, len(item.attrib))
54
55
56def check_pkgname_type(value):
57    if len(value) == 0 or len(value) > MAX_PKGNAME_LEN:
58        raise RuntimeError("invalid pkgname, the pkgname length must be in range (0, {}]".format(MAX_PKGNAME_LEN), \
59            value, len(value))
60
61
62def check_uid_type(value):
63    if int(value, 10) > 0xffffffff or int(value, 10) < 0:
64        raise RuntimeError("invalid uid, the uid value must be in [0, 0xffffffff]", value)
65
66
67def check_username_type(value):
68    if len(value) == 0 or len(value) > MAX_USERNAME_LEN:
69        raise RuntimeError("invalid username, the username length must be in range (0, {}]".format(MAX_USERNAME_LEN), \
70            value, len(value))
71
72
73def check_modulue_type(value):
74    if len(value) == 0 or (len(value) / 2) > MAX_MODULUS_LEN:
75        raise RuntimeError("invalid module, the module length must be in range (0, {}]".format(MAX_MODULUS_LEN * 2), \
76            value, len(value))
77
78
79def check_exponent_type(value):
80    if len(value) == 0 or (len(value) / 2) > MAX_PUB_EXP_LEN:
81        raise RuntimeError( \
82            "invalid exponent, the exponent length must be in range (0, {}]".format(MAX_PUB_EXP_LEN * 2), \
83            value, len(value))
84
85
86def calc_sha256(buf):
87    hash_op = hashlib.sha256()
88    hash_op.update(buf)
89    return hash_op.digest()
90
91
92def calc_cmdline_uid_hash(cmdline, uid):
93    c_uid = c_uint32(uid)
94    c_str = create_string_buffer(cmdline.encode('utf-8'), len(cmdline) + sizeof(c_uid))
95    memmove(byref(c_str, len(c_str.value)), byref(c_uid), sizeof(c_uid))
96    return calc_sha256(c_str)
97
98
99def calc_cmdline_username_hash(cmdline, username):
100    c_str = create_string_buffer((cmdline + username).encode('utf-8'), len(cmdline) + MAX_USERNAME_LEN)
101    return calc_sha256(c_str)
102
103
104def calc_app_caller_hash(app_pkg_name, app_modulus, app_public_exponent):
105    hex_modulus = binascii.a2b_hex(app_modulus)
106    hex_exponent = binascii.a2b_hex(app_public_exponent)
107    pub_key_format = "{}s{}s".format(len(hex_modulus), len(hex_exponent))
108    hex_pub_key = struct.pack(pub_key_format, hex_modulus, hex_exponent)
109    c_str = create_string_buffer((app_pkg_name).encode('utf-8'), \
110        len(app_pkg_name) + len(hex_pub_key))
111    memmove(byref(c_str, len(c_str.value)), bytes(hex_pub_key), len(hex_pub_key))
112    return calc_sha256(c_str)
113
114
115def handle_cmdline_uid_item_hash(item):
116    cmdline = ""
117    uid = 0
118    for attr in item.attrib:
119        value = item.attrib[attr]
120        if attr == "cmdline":
121            check_pkgname_type(value)
122            cmdline = value
123        elif attr == "uid":
124            check_uid_type(value)
125            uid = int(value, 10)
126        else:
127            raise RuntimeError("invalid item attr", attr)
128    caller_hash = calc_cmdline_uid_hash(cmdline, uid)
129    logging.info("cmdline: %s, uid: %s", cmdline, uid)
130    print_hash(caller_hash)
131
132
133def handle_cmdline_uid(child):
134    for item in child:
135        check_native_ca_item(item)
136        handle_cmdline_uid_item_hash(item)
137
138
139def handle_cmdline_username_item_hash(item):
140    cmdline = ""
141    username = ""
142    for attr in item.attrib:
143        value = item.attrib[attr]
144        if attr == "cmdline":
145            check_pkgname_type(value)
146            cmdline = value
147        elif attr == "username":
148            check_username_type(value)
149            username = value
150        else:
151            raise RuntimeError("invalid item attr", attr)
152    caller_hash = calc_cmdline_username_hash(cmdline, username)
153    logging.info("cmdline: %s, username: %s", cmdline, username)
154    print_hash(caller_hash)
155
156
157def handle_cmdline_username(child):
158    for item in child:
159        check_native_ca_item(item)
160        handle_cmdline_username_item_hash(item)
161
162
163def handle_app_item_hash(item):
164    pkg_name = ""
165    modulue = ""
166    exponent = ""
167    for attr in item.attrib:
168        value = item.attrib[attr]
169        if attr == "pkg_name":
170            check_pkgname_type(value)
171            pkg_name = value
172        elif attr == "modulue":
173            check_modulue_type(value)
174            modulue = value
175        elif attr == "exponent":
176            check_exponent_type(value)
177            exponent = value
178        else:
179            raise RuntimeError("invalid item attr", attr)
180    caller_hash = calc_app_caller_hash(pkg_name, modulue, exponent)
181    logging.info("pkg_name: %s, modulue:%s, exponent: %s", pkg_name, modulue, exponent)
182    print_hash(caller_hash)
183
184
185def handle_app(child):
186    for item in child:
187        check_app_ca_item(item)
188        handle_app_item_hash(item)
189
190
191def do_calc_caller_info_hash(ca_caller_info_root):
192    for child in ca_caller_info_root:
193        if child.tag == "cmdline_uid":
194            handle_cmdline_uid(child)
195        elif child.tag == "cmdline_username":
196            handle_cmdline_username(child)
197        elif child.tag == "app":
198            handle_app(child)
199        else:
200            raise RuntimeError("not support xml tag", child.tag)
201
202
203def main():
204    ca_caller_info_xml = "ca_caller_info.xml"
205    if not os.path.exists(ca_caller_info_xml):
206        raise RuntimeError("caller_info.xml file doesn't exist.")
207
208    tree = ET.parse(ca_caller_info_xml)
209    ca_caller_info_root = tree.getroot()
210
211    do_calc_caller_info_hash(ca_caller_info_root)
212
213
214if __name__ == "__main__":
215    main()