rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame^] | 1 | #!/usr/bin/env python |
| 2 | # -*- coding: UTF-8 -*- |
| 3 | """ |
| 4 | This module supports image signing, including single bin and multi bin. |
| 5 | Multi bin means a composite image composed of multiple sub-images. |
| 6 | """ |
| 7 | import sys |
| 8 | import os |
| 9 | import struct |
| 10 | import re |
| 11 | import subprocess |
| 12 | import ntpath |
| 13 | import shutil |
| 14 | import stat |
| 15 | import lib.mkimghdr |
| 16 | import lib.getPublicKey |
| 17 | import lib.cert |
| 18 | import cert_gen |
| 19 | |
| 20 | CERT1_REPLACE_TARGET = r"(\s)*pubk2" |
| 21 | CERT2_REPLACE_HASH = r"(\s)*imgHash EXTERNAL_BITSTRING" |
| 22 | CERT2_REPLACE_HEADER_HASH = r"(\s)*imgHdrHash EXTERNAL_BITSTRING" |
| 23 | CERT2_REPLACE_IMG_HASH_MULTI = r"(\s)*imgHash_Multi EXTERNAL_BITSTRING" |
| 24 | CERT2_REPLACE_SOCID = r"(\s)*socid PRINTABLESTRING" |
| 25 | CERT1MD_REPLACE_TARGET = r"(\s)*pubkHash EXTERNAL_BITSTRING" |
| 26 | SW_ID_REPLACE_TARGET = r"(\s)*swID INTEGER" |
| 27 | IMG_VER_REPLACE_TARGET = r"(\s)*imgVer INTEGER" |
| 28 | IMG_GROUP_REPLACE_TARGET = r"(\s)*imgGroup INTEGER" |
| 29 | MKIMAGE_HDR_MAGIC = 0x58881688 |
| 30 | MKIMAGE_HDR_FMT = "<2I 32s 2I 8I" |
| 31 | BOOTIMG_HDR_MAGIC = "ANDROID" |
| 32 | BOOTIMG_HDR_FMT = "<8c 10I 16c 512c 8I 1024c I Q I I Q" |
| 33 | CCCI_HDR_FMT = "<8c 10I 16c 512c 8I" |
| 34 | DTBO_HDR_MAGIC = 0xD7B7AB1E |
| 35 | DTBO_HDR_FMT = ">8I" |
| 36 | |
| 37 | class Sign(object): |
| 38 | """ |
| 39 | Sign is used to pass parameter to module 'sign'. |
| 40 | """ |
| 41 | def __init__(self): |
| 42 | """ |
| 43 | initialization of arguments |
| 44 | """ |
| 45 | self.args = {} |
| 46 | self.context = {} |
| 47 | |
| 48 | self.args['type'] = 0 |
| 49 | self.args['img'] = 0 |
| 50 | self.args['privk'] = 0 |
| 51 | self.args['pubk'] = 0 |
| 52 | self.args['cert1'] = 0 |
| 53 | self.args['swID'] = 0 |
| 54 | self.args['ver'] = 0 |
| 55 | self.args['name'] = '' |
| 56 | self.args['group'] = 0 |
| 57 | self.args['root_key_padding'] = 0 |
| 58 | self.args['getHashList'] = 0 |
| 59 | self.args['platform'] = 'NOT_SET' |
| 60 | self.args['project'] = 'NOT_SET' |
| 61 | self.args['env_cfg'] = os.path.join(os.path.dirname(__file__), \ |
| 62 | 'env.cfg') |
| 63 | self.args['socid'] = '0' |
| 64 | |
| 65 | return |
| 66 | |
| 67 | def reset(self): |
| 68 | """ |
| 69 | reset all arguments |
| 70 | """ |
| 71 | self.__init__() |
| 72 | |
| 73 | def get_arg(self, field_name): |
| 74 | """ |
| 75 | get value of field and returns 'NOT_SET' if it's not defined |
| 76 | """ |
| 77 | try: |
| 78 | return self.args[field_name] |
| 79 | except KeyError, error: |
| 80 | print 'KeyError: ' + str(error) |
| 81 | return 'NOT_SET' |
| 82 | |
| 83 | def set_context(self): |
| 84 | """ |
| 85 | Set temporary path for certificate generation. |
| 86 | """ |
| 87 | img_name = self.args['name'] |
| 88 | if self.args['img'] != 0: |
| 89 | package_name = os.path.splitext(os.path.basename(self.args['img']))[0] |
| 90 | else: |
| 91 | package_name = '' |
| 92 | |
| 93 | print '==============================' |
| 94 | print 'env_cfg parsing' |
| 95 | print '==============================' |
| 96 | cfg_file = open(self.args['env_cfg'], 'r') |
| 97 | cfg_file_dir = os.path.dirname(os.path.abspath(self.args['env_cfg'])) |
| 98 | for line in cfg_file.readlines(): |
| 99 | line = line.strip() |
| 100 | if line: |
| 101 | elements = line.split('=') |
| 102 | field = elements[0].strip() |
| 103 | value = elements[1].strip() |
| 104 | value = value.replace("${PLATFORM}", self.get_arg('platform')) |
| 105 | value = value.replace("${PROJECT}", self.get_arg('project')) |
| 106 | if field == 'out_path': |
| 107 | self.context['out'] = os.environ.get('PRODUCT_OUT') |
| 108 | if self.context['out'] is None: |
| 109 | print 'Use out path in env.cfg' |
| 110 | self.context['out'] = os.path.join(cfg_file_dir, value) |
| 111 | else: |
| 112 | print 'Use out path in Android' |
| 113 | self.context['out_path'] = os.path.join(self.context['out'], "resign") |
| 114 | elif field == 'x509_template_path': |
| 115 | x509_template_path = os.path.join(cfg_file_dir, value) |
| 116 | elif field == 'mkimage_tool_path': |
| 117 | mkimage_tool_path = os.path.join(cfg_file_dir, value) |
| 118 | else: |
| 119 | print 'ignored: ' + field |
| 120 | print '==============================' |
| 121 | |
| 122 | self.context['bin_path'] = os.path.join(self.context['out_path'], "bin") |
| 123 | self.context['tmpcert_name'] = os.path.join(self.context['out_path'], \ |
| 124 | "cert", \ |
| 125 | package_name, \ |
| 126 | img_name, \ |
| 127 | "tmp.der") |
| 128 | |
| 129 | #tool path |
| 130 | mkimage_config = os.path.join(mkimage_tool_path, "img_hdr.cfg") |
| 131 | cert_out = os.path.join(self.context['out_path'], "cert", package_name, img_name) |
| 132 | |
| 133 | self.context['mkimage_config'] = mkimage_config |
| 134 | |
| 135 | mkimage_config_out = "" |
| 136 | if self.args['type'] == "cert1md": |
| 137 | cert1md_tmp = os.path.join(cert_out, "cert1md", "intermediate") |
| 138 | cert1md_name = os.path.join(cert_out, "cert1md", "cert1md.der") |
| 139 | cert1md_hash_path = os.path.join(cert1md_tmp, "hash") |
| 140 | cert1md_config = os.path.join(x509_template_path, "cert1md.cfg") |
| 141 | cert1md_config_out = os.path.join(cert1md_tmp, "cert1md.cfg") |
| 142 | mkimage_config_out = os.path.join(cert1md_tmp, "img_hdr.cfg") |
| 143 | self.context['cert1md_name'] = cert1md_name |
| 144 | self.context['cert1md_config'] = cert1md_config |
| 145 | self.context['cert1md_config_out'] = cert1md_config_out |
| 146 | self.context['cert1md_hash_path'] = cert1md_hash_path |
| 147 | elif self.args['type'] == "cert1": |
| 148 | cert1_tmp = os.path.join(cert_out, "cert1", "intermediate") |
| 149 | cert1_name = os.path.join(cert_out, "cert1", "cert1.der") |
| 150 | cert1_config = os.path.join(x509_template_path, "cert1.cfg") |
| 151 | cert1_config_out = os.path.join(cert1_tmp, "cert1.cfg") |
| 152 | mkimage_config_out = os.path.join(cert1_tmp, "img_hdr.cfg") |
| 153 | self.context['cert1_name'] = cert1_name |
| 154 | self.context['cert1_config'] = cert1_config |
| 155 | self.context['cert1_config_out'] = cert1_config_out |
| 156 | elif self.args['type'] == "cert2": |
| 157 | cert2_tmp = os.path.join(cert_out, "cert2", "intermediate") |
| 158 | cert2_name = os.path.join(cert_out, "cert2", "cert2.der") |
| 159 | cert2_hash_path = os.path.join(cert2_tmp, "hash") |
| 160 | cert2_config = os.path.join(x509_template_path, "cert2.cfg") |
| 161 | cert2_config_out = os.path.join(cert2_tmp, "cert2.cfg") |
| 162 | dm_cert = os.path.join(cert2_tmp, "dm_cert.der") |
| 163 | bin_tmp_path = os.path.join(cert2_tmp, "tmp_bin") |
| 164 | sig_path = os.path.join(self.context['out'], "sig", package_name) |
| 165 | mkimage_config_out = os.path.join(cert2_tmp, "img_hdr.cfg") |
| 166 | self.context['bin_tmp_path'] = bin_tmp_path |
| 167 | self.context['cert2_name'] = cert2_name |
| 168 | self.context['cert2_config'] = cert2_config |
| 169 | self.context['cert2_config_out'] = cert2_config_out |
| 170 | self.context['cert2_hash_path'] = cert2_hash_path |
| 171 | self.context['dm_cert'] = dm_cert |
| 172 | self.context['sig_path'] = sig_path |
| 173 | |
| 174 | self.context['mkimage_config_out'] = mkimage_config_out |
| 175 | return |
| 176 | |
| 177 | def __create_out_dir(self, path): |
| 178 | """ |
| 179 | create output folder |
| 180 | """ |
| 181 | dir_path = os.path.dirname(path) |
| 182 | print "Create dir:" + dir_path |
| 183 | |
| 184 | try: |
| 185 | os.makedirs(dir_path) |
| 186 | except OSError, error: |
| 187 | if error.errno != os.errno.EEXIST: |
| 188 | raise |
| 189 | |
| 190 | def __create_abs_dir(self, path): |
| 191 | """ |
| 192 | create output folder based on absolute path |
| 193 | """ |
| 194 | dir_path = os.path.abspath(path) |
| 195 | print "Create dir:" + dir_path |
| 196 | |
| 197 | try: |
| 198 | os.makedirs(dir_path) |
| 199 | except OSError, error: |
| 200 | if error.errno != os.errno.EEXIST: |
| 201 | raise |
| 202 | |
| 203 | def __create_folder(self): |
| 204 | """ |
| 205 | Create output folder for certificate generation. |
| 206 | """ |
| 207 | mkimage_config_out = self.context['mkimage_config_out'] |
| 208 | bin_path = self.context['bin_path'] |
| 209 | |
| 210 | self.__create_out_dir(mkimage_config_out) |
| 211 | self.__create_abs_dir(bin_path) |
| 212 | |
| 213 | if self.args['type'] == "cert1md": |
| 214 | cert1md_name = self.context['cert1md_name'] |
| 215 | cert1md_hash_path = self.context['cert1md_hash_path'] |
| 216 | self.__create_out_dir(cert1md_name) |
| 217 | self.__create_abs_dir(cert1md_hash_path) |
| 218 | elif self.args['type'] == "cert1": |
| 219 | cert1_name = self.context['cert1_name'] |
| 220 | cert1_config_out = self.context['cert1_config_out'] |
| 221 | self.__create_out_dir(cert1_name) |
| 222 | self.__create_out_dir(cert1_config_out) |
| 223 | elif self.args['type'] == "cert2": |
| 224 | cert2_name = self.context['cert2_name'] |
| 225 | cert2_hash_path = self.context['cert2_hash_path'] |
| 226 | sig_path = self.context['sig_path'] |
| 227 | bin_tmp_path = self.context['bin_tmp_path'] |
| 228 | self.__create_out_dir(cert2_name) |
| 229 | self.__create_abs_dir(cert2_hash_path) |
| 230 | self.__create_abs_dir(sig_path) |
| 231 | self.__create_abs_dir(bin_tmp_path) |
| 232 | return |
| 233 | |
| 234 | def gen_cert(self, cert_config, privk_key, cert_der, root_key_padding): |
| 235 | """ |
| 236 | Generate certificate based on the configuration given. |
| 237 | """ |
| 238 | cert_gen_args = cert_gen.CertGenArgs() |
| 239 | cert_gen_args.config_file = cert_config |
| 240 | cert_gen_args.prvk_file_path = privk_key |
| 241 | #root key padding will be set to 'legacy' by default |
| 242 | if root_key_padding != 0: |
| 243 | cert_gen_args.root_key_padding = root_key_padding |
| 244 | cert_gen_args.x509cert_file = cert_der |
| 245 | cert_gen.cert_gen_op(cert_gen_args) |
| 246 | |
| 247 | def gen_cert1(self): |
| 248 | """ |
| 249 | Generate cert1, which is key certificate for images |
| 250 | other than modem image. |
| 251 | """ |
| 252 | cert1_config = self.context['cert1_config'] |
| 253 | cert1_config_out = self.context['cert1_config_out'] |
| 254 | #copy cert1 config |
| 255 | shutil.copy2(cert1_config, cert1_config_out) |
| 256 | sw_id = self.args['swID'] |
| 257 | img_ver = self.args['ver'] |
| 258 | img_group = self.args['group'] |
| 259 | |
| 260 | cert1_name = self.context['cert1_name'] |
| 261 | |
| 262 | if self.args['root_key_padding'] == 0: |
| 263 | root_key_padding = 'legacy' |
| 264 | else: |
| 265 | root_key_padding = self.args['root_key_padding'] |
| 266 | print "root_key_padding = " + root_key_padding |
| 267 | |
| 268 | if int(sw_id) != 0: |
| 269 | fill_cert_config(cert1_config_out, sw_id, SW_ID_REPLACE_TARGET) |
| 270 | if int(img_ver) != 0: |
| 271 | fill_cert_config(cert1_config_out, img_ver, IMG_VER_REPLACE_TARGET) |
| 272 | if int(img_group) != 0: |
| 273 | fill_cert_config(cert1_config_out, img_group, IMG_GROUP_REPLACE_TARGET) |
| 274 | |
| 275 | fill_cert_config(cert1_config_out, self.args['pubk'], CERT1_REPLACE_TARGET) |
| 276 | #gen cert |
| 277 | self.gen_cert(cert1_config_out, \ |
| 278 | self.args['privk'], \ |
| 279 | cert1_name, \ |
| 280 | root_key_padding) |
| 281 | cert1_img_type = 0x2 << 24 |
| 282 | add_mkimg_header(cert1_name, 0, cert1_img_type, "cert1", self.context) |
| 283 | print "output path:" + cert1_name |
| 284 | return |
| 285 | |
| 286 | def gen_cert1md(self): |
| 287 | """ |
| 288 | Generate cert1md, which is key certificate for modem image. |
| 289 | """ |
| 290 | img_file = self.args['img'] |
| 291 | cert_privk = self.args['privk'] |
| 292 | cert1md_hash_path = self.context['cert1md_hash_path'] |
| 293 | cert1md_config = self.context['cert1md_config'] |
| 294 | cert1md_config_out = self.context['cert1md_config_out'] |
| 295 | |
| 296 | if self.args['root_key_padding'] == 0: |
| 297 | root_key_padding = 'legacy' |
| 298 | else: |
| 299 | root_key_padding = self.args['root_key_padding'] |
| 300 | print "root_key_padding = " + root_key_padding |
| 301 | |
| 302 | print img_file |
| 303 | #check is Raw |
| 304 | is_raw, is_md, hdr_size = check_is_raw(img_file) |
| 305 | |
| 306 | if is_raw == 0: |
| 307 | print "Is not raw image" |
| 308 | return |
| 309 | |
| 310 | if is_md < 1: |
| 311 | print "Wrong MD image type" |
| 312 | return |
| 313 | |
| 314 | cert1md_name = self.context['cert1md_name'] |
| 315 | |
| 316 | #SV5 Image(MD) |
| 317 | split_header, split_image = img_split(img_file, cert1md_hash_path, hdr_size) |
| 318 | key_hash_tmp = os.path.join(cert1md_hash_path, "key_tmp.hash") |
| 319 | key_hash = os.path.join(cert1md_hash_path, "key.hash") |
| 320 | header_hash = os.path.join(cert1md_hash_path, "header.hash") |
| 321 | |
| 322 | #get md key |
| 323 | md_key = get_md_key(split_image, is_md, self.context) |
| 324 | #gen header hash |
| 325 | lib.cert.hash_gen(split_header, header_hash) |
| 326 | #gen key hash |
| 327 | lib.cert.hash_gen(md_key, key_hash_tmp) |
| 328 | #Endiness conversion |
| 329 | endiness_convert(key_hash_tmp, key_hash) |
| 330 | |
| 331 | #fill config |
| 332 | shutil.copy2(cert1md_config, cert1md_config_out) |
| 333 | fill_cert_config(cert1md_config_out, key_hash, CERT1MD_REPLACE_TARGET) |
| 334 | fill_cert_config(cert1md_config_out, self.args['pubk'], CERT1_REPLACE_TARGET) |
| 335 | |
| 336 | sw_id = self.args['swID'] |
| 337 | img_ver = self.args['ver'] |
| 338 | img_group = self.args['group'] |
| 339 | if int(sw_id) != 0: |
| 340 | fill_cert_config(cert1md_config_out, sw_id, SW_ID_REPLACE_TARGET) |
| 341 | if int(img_ver) != 0: |
| 342 | fill_cert_config(cert1md_config_out, img_ver, IMG_VER_REPLACE_TARGET) |
| 343 | if int(img_group) != 0: |
| 344 | fill_cert_config(cert1md_config_out, img_group, IMG_GROUP_REPLACE_TARGET) |
| 345 | #gen cert |
| 346 | self.gen_cert(cert1md_config_out, cert_privk, cert1md_name, root_key_padding) |
| 347 | #add mkimage header on cert1md |
| 348 | |
| 349 | cert1md_img_type = 0x2 << 24 | 0x1 |
| 350 | add_mkimg_header(cert1md_name, 0, cert1md_img_type, "cert1md", self.context) |
| 351 | print "output path:" + cert1md_name |
| 352 | |
| 353 | def gen_cert2(self): |
| 354 | """ |
| 355 | Generate cert2, which is content certificate. |
| 356 | """ |
| 357 | img_file = self.args['img'] |
| 358 | cert1 = self.args['cert1'] |
| 359 | cert_privk = self.args['privk'] |
| 360 | img_name = self.args['name'] |
| 361 | img_ver = self.args['ver'] |
| 362 | socid = self.args['socid'] |
| 363 | is_img_hash_list = 0 |
| 364 | is_raw = 0 |
| 365 | is_boot = 0 |
| 366 | is_dtbo = 0 |
| 367 | |
| 368 | if self.get_arg('getHashList') is '1': |
| 369 | is_img_hash_list = 1 |
| 370 | |
| 371 | img_array = [] |
| 372 | size_array = [] |
| 373 | offset_array = [] |
| 374 | img_name_array = [] |
| 375 | |
| 376 | bin_path = self.context['bin_path'] |
| 377 | bin_tmp_path = self.context['bin_tmp_path'] |
| 378 | cert2_name = self.context['cert2_name'] |
| 379 | cert2_config = self.context['cert2_config'] |
| 380 | cert2_config_out = self.context['cert2_config_out'] |
| 381 | cert2_hash_path = self.context['cert2_hash_path'] |
| 382 | dm_cert = self.context['dm_cert'] |
| 383 | sig_path = self.context['sig_path'] |
| 384 | out = self.context['out'] |
| 385 | |
| 386 | is_raw, is_md, hdr_size = check_is_raw(img_file) |
| 387 | if not is_raw: |
| 388 | is_boot, boot_img_size, hdr_size = check_is_boot(img_file) |
| 389 | |
| 390 | if is_boot: |
| 391 | has_dm_cert = get_vboot10_cert(img_file, boot_img_size, self.context) |
| 392 | |
| 393 | if (not is_raw) and (not is_boot): |
| 394 | is_dtbo, dtbo_img_size, hdr_size = check_is_dtbo(img_file) |
| 395 | |
| 396 | if is_raw: |
| 397 | img_array, \ |
| 398 | size_array, \ |
| 399 | offset_array, \ |
| 400 | img_name_array = parse_multi_bin(img_file, img_name, self.context) |
| 401 | if img_array is None: |
| 402 | return |
| 403 | elif is_boot: |
| 404 | img_array.append(os.path.join(bin_tmp_path, "tmp.bin")) |
| 405 | size_array.append(boot_img_size) |
| 406 | offset_array.append(0) |
| 407 | img_name_array.append(img_name) |
| 408 | elif is_dtbo: |
| 409 | img_array.append(os.path.join(bin_tmp_path, "tmp.bin")) |
| 410 | size_array.append(dtbo_img_size) |
| 411 | offset_array.append(0) |
| 412 | img_name_array.append(img_name) |
| 413 | elif not is_img_hash_list: |
| 414 | print "wrong image format" |
| 415 | return |
| 416 | |
| 417 | if is_img_hash_list: |
| 418 | print "get pure image hash..." |
| 419 | self.gen_img_hash_list(img_file, cert1, cert_privk, img_name, img_ver) |
| 420 | return |
| 421 | |
| 422 | get_pure_img(img_file, img_array, size_array, offset_array) |
| 423 | print "bin_number:" + str(len(img_array)) |
| 424 | #Get hash from image |
| 425 | i = 0 |
| 426 | img_list_end = 0 |
| 427 | for img in img_array: |
| 428 | if i == len(img_array) - 1: |
| 429 | img_list_end = 1 |
| 430 | |
| 431 | if is_raw == 1 or is_boot == 1 or is_md == 1 or is_md == 2 or is_dtbo: |
| 432 | #Raw Image |
| 433 | if img_name_array[i] == img_name: |
| 434 | split_header, split_image = img_split(img, cert2_hash_path, hdr_size) |
| 435 | |
| 436 | image_hash = os.path.join(cert2_hash_path, "image.hash") |
| 437 | header_hash = os.path.join(cert2_hash_path, "header.hash") |
| 438 | |
| 439 | #gen header hash |
| 440 | lib.cert.hash_gen(split_header, header_hash) |
| 441 | #gen image hash |
| 442 | lib.cert.hash_gen(split_image, image_hash) |
| 443 | |
| 444 | #if exist DM cert, append it after hash calculate |
| 445 | if is_boot == 1 and has_dm_cert == 1: |
| 446 | append_file(img, dm_cert) |
| 447 | |
| 448 | #cat cert1 |
| 449 | append_file(img, cert1) |
| 450 | |
| 451 | #fill cert2 config |
| 452 | shutil.copy2(cert2_config, cert2_config_out) |
| 453 | fill_cert_config(cert2_config_out, image_hash, CERT2_REPLACE_HASH) |
| 454 | fill_cert_config(cert2_config_out, header_hash, CERT2_REPLACE_HEADER_HASH) |
| 455 | fill_cert_config(cert2_config_out, socid.upper(), CERT2_REPLACE_SOCID) |
| 456 | |
| 457 | if int(img_ver) != 0: |
| 458 | fill_cert_config(cert2_config_out, img_ver, IMG_VER_REPLACE_TARGET) |
| 459 | #gen cert2 |
| 460 | self.gen_cert(cert2_config_out, cert_privk, cert2_name, 0) |
| 461 | #add mkimage header on cert2 |
| 462 | cert2_img_type = 0x2 << 24 | 0x2 |
| 463 | add_mkimg_header(cert2_name, \ |
| 464 | img_list_end, \ |
| 465 | cert2_img_type, \ |
| 466 | "cert2", \ |
| 467 | self.context) |
| 468 | #cat cert2 |
| 469 | append_file(img, cert2_name) |
| 470 | #cat sig file |
| 471 | sig_file = os.path.join(sig_path, img_name + ".sig") |
| 472 | print img_ver |
| 473 | print "sig:" + sig_file |
| 474 | shutil.copy2(cert1, sig_file) |
| 475 | append_file(sig_file, cert2_name) |
| 476 | |
| 477 | i += 1 |
| 478 | |
| 479 | img_name = ntpath.split(img_file)[1] |
| 480 | img_name = img_name.split(".")[0] + "-verified." + img_name.split(".")[1] |
| 481 | final_bin = os.path.join(bin_tmp_path, img_name) |
| 482 | |
| 483 | #cat all bin to img_array[0] |
| 484 | cat_img(img_array, final_bin) |
| 485 | |
| 486 | #Post Process |
| 487 | shutil.copy2(final_bin, os.path.join(bin_path, img_name)) |
| 488 | shutil.copy2(os.path.join(bin_path, img_name), os.path.join(out, img_name)) |
| 489 | print "output path:" + os.path.join(out, img_name) |
| 490 | return |
| 491 | |
| 492 | def gen_img_hash_list(self, img_file, cert1, cert_privk, img_name, img_ver): |
| 493 | """ |
| 494 | Generate image hash list. This is a verified boot mechanism |
| 495 | for images that are too big to fit into DRAM at once. In this |
| 496 | case, image is split into 128MB chunks and sent to DA one by one. |
| 497 | DA will receive a signed image hash list and verifies it before |
| 498 | flashing. After that, DA will calculate hash on receiving a chunk |
| 499 | and compares it against the hash in signed image hash list. |
| 500 | """ |
| 501 | data_size = 128 * 1048576 |
| 502 | |
| 503 | img_size = os.path.getsize(img_file) |
| 504 | print "img_size => "+ str(img_size) |
| 505 | file1 = open(img_file, 'rb') |
| 506 | package_num = (img_size + (data_size - 1)) / data_size |
| 507 | print "package_num => "+ str(package_num) |
| 508 | print "get " + img_name + " hash list..." |
| 509 | |
| 510 | bin_tmp_path = self.context['bin_tmp_path'] |
| 511 | cert2_name = self.context['cert2_name'] |
| 512 | cert2_config = self.context['cert2_config'] |
| 513 | cert2_config_out = self.context['cert2_config_out'] |
| 514 | cert2_hash_path = self.context['cert2_hash_path'] |
| 515 | sig_path = self.context['sig_path'] |
| 516 | out = self.context['out'] |
| 517 | |
| 518 | for i in range(package_num): |
| 519 | div_out = os.path.join(bin_tmp_path, img_name + "_" + str(i) + ".bin") |
| 520 | div_hash_out = os.path.join(cert2_hash_path, img_name + "_" + str(i) + ".hash") |
| 521 | output_file = open(div_out, 'wb') |
| 522 | content = file1.read(data_size) |
| 523 | output_file.write(content) |
| 524 | output_file.close() |
| 525 | lib.cert.hash_gen(div_out, div_hash_out) |
| 526 | file1.close() |
| 527 | |
| 528 | img_hash_file = os.path.join(cert2_hash_path, img_name + "_total.hash") |
| 529 | file2 = open(img_hash_file, 'wb') |
| 530 | for i in range(package_num): |
| 531 | hash_file = open(os.path.join(cert2_hash_path, img_name + "_" + str(i) + ".hash"), 'rb') |
| 532 | img_hash = hash_file.read() |
| 533 | file2.write(img_hash) |
| 534 | file2.close() |
| 535 | |
| 536 | shutil.copy2(cert2_config, cert2_config_out) |
| 537 | |
| 538 | fill_cert_config(cert2_config_out, img_hash_file, CERT2_REPLACE_IMG_HASH_MULTI) |
| 539 | if int(img_ver) != 0: |
| 540 | fill_cert_config(cert2_config_out, img_ver, IMG_VER_REPLACE_TARGET) |
| 541 | #gen cert2 |
| 542 | self.gen_cert(cert2_config_out, cert_privk, cert2_name, 0) |
| 543 | img_list_end = 1 |
| 544 | #add mkimage header on cert2 |
| 545 | cert2_img_type = 0x2 << 24 | 0x2 |
| 546 | add_mkimg_header(cert2_name, img_list_end, cert2_img_type, "cert2", self.context) |
| 547 | sig_file = os.path.join(sig_path, img_name + ".sig") |
| 548 | shutil.copy2(cert1, sig_file) |
| 549 | append_file(sig_file, cert2_name) |
| 550 | shutil.copy2(sig_file, os.path.join(out, img_name + ".sig")) |
| 551 | |
| 552 | return |
| 553 | |
| 554 | def sign_op(self): |
| 555 | """ |
| 556 | perform image signing |
| 557 | """ |
| 558 | self.set_context() |
| 559 | |
| 560 | if self.args['type'] == "cert1": |
| 561 | self.__create_folder() |
| 562 | self.gen_cert1() |
| 563 | elif self.args['type'] == "cert2": |
| 564 | self.__create_folder() |
| 565 | self.gen_cert2() |
| 566 | elif self.args['type'] == "cert1md": |
| 567 | self.__create_folder() |
| 568 | self.gen_cert1md() |
| 569 | else: |
| 570 | print "wrong cert type !" |
| 571 | |
| 572 | return |
| 573 | |
| 574 | def dump(self): |
| 575 | """ |
| 576 | dump parameters |
| 577 | """ |
| 578 | print 'cert_type = ' + self.get_arg(self.args['type']) |
| 579 | print 'platform = ' + self.get_arg(self.args['platform']) |
| 580 | print 'project = ' + self.get_arg(self.args['project']) |
| 581 | print 'img = ' + self.get_arg(self.args['img']) |
| 582 | print 'name = ' + self.get_arg(self.args['name']) |
| 583 | print 'cert1_path = ' + self.get_arg(self.args['cert1']) |
| 584 | print 'root_prvk = ' + self.get_arg(self.args['privk']) |
| 585 | print 'img_pubk = ' + self.get_arg(self.args['pubk']) |
| 586 | print 'group = ' + self.get_arg(self.args['group']) |
| 587 | print 'ver = ' + self.get_arg(self.args['ver']) |
| 588 | print 'root_padding = ' + self.get_arg(self.args['root_key_padding']) |
| 589 | print 'getHashList = ' + self.get_arg(self.args['getHashList']) |
| 590 | print 'env_cfg = ' + self.get_arg(self.args['env_cfg']) |
| 591 | return |
| 592 | |
| 593 | def parse_multi_bin(img_file, target_img_name, context): |
| 594 | """ |
| 595 | we may concatenate multiple images to form a composite image. |
| 596 | This function is used to parse the composite image to get |
| 597 | information of sub-image with name target_img_name. |
| 598 | """ |
| 599 | #parse bin |
| 600 | img_size = 0 |
| 601 | index = 0 |
| 602 | file1 = open(img_file, 'rb') |
| 603 | last_pos = 0 |
| 604 | pre_pos = 0 |
| 605 | |
| 606 | img_array = [] |
| 607 | size_array = [] |
| 608 | offset_array = [] |
| 609 | img_name_array = [] |
| 610 | |
| 611 | file_size = os.path.getsize(img_file) |
| 612 | print "file_size: "+ str(hex(file_size)) |
| 613 | |
| 614 | first_img = 1 |
| 615 | final_size = 0 |
| 616 | match_target = 0 |
| 617 | img_name = 0 |
| 618 | |
| 619 | bin_tmp_path = context['bin_tmp_path'] |
| 620 | |
| 621 | while True: |
| 622 | file1.seek(last_pos) |
| 623 | header_size = struct.calcsize(MKIMAGE_HDR_FMT) |
| 624 | fin = file1.read(header_size) |
| 625 | unpack_array = struct.unpack(MKIMAGE_HDR_FMT, fin) |
| 626 | file1.seek(last_pos) |
| 627 | |
| 628 | magic_number = unpack_array[0] |
| 629 | dsize = unpack_array[1] |
| 630 | hdr_size = unpack_array[6] |
| 631 | align_size = unpack_array[10] |
| 632 | img_type = unpack_array[8] |
| 633 | |
| 634 | if ~cmp(magic_number, int(MKIMAGE_HDR_MAGIC)) == 0: |
| 635 | print "wrong image header magic" |
| 636 | sys.exit() |
| 637 | |
| 638 | # include header + image + padding size to 16 bytes align |
| 639 | img_size = (dsize + hdr_size + (align_size - 1)) / align_size * align_size |
| 640 | print "img-" + str(index) + " size:" + hex(img_size) |
| 641 | |
| 642 | img_type_byte3 = (img_type >> 24) & 0xFF |
| 643 | |
| 644 | if img_type_byte3 != 2: |
| 645 | # image not cert |
| 646 | pre_img_name = img_name |
| 647 | img_name = unpack_array[2].rstrip('\t\r\n\0') |
| 648 | if target_img_name == img_name: |
| 649 | print "Target image, remove cert for replace" |
| 650 | is_target = 1 |
| 651 | match_target = 1 |
| 652 | else: |
| 653 | print "Not target image, retain cert" |
| 654 | is_target = 0 |
| 655 | is_raw = 1 |
| 656 | else: |
| 657 | #image is cert |
| 658 | is_raw = 0 |
| 659 | |
| 660 | if is_raw and first_img == 0: |
| 661 | print "add index" + str(index) + " image" |
| 662 | img_str = os.path.join(bin_tmp_path, "tmp_" + str(index) + ".bin") |
| 663 | img_array.append(img_str) |
| 664 | size_array.append(final_size) |
| 665 | offset_array.append(pre_pos) |
| 666 | img_name_array.append(pre_img_name) |
| 667 | pre_pos = last_pos |
| 668 | final_size = 0 |
| 669 | index += 1 |
| 670 | |
| 671 | first_img = 0 |
| 672 | |
| 673 | if is_target: |
| 674 | if is_raw: |
| 675 | final_size = img_size |
| 676 | else: |
| 677 | print "is cert, discard it" |
| 678 | else: |
| 679 | final_size += img_size |
| 680 | |
| 681 | last_pos += img_size |
| 682 | |
| 683 | if last_pos >= file_size: |
| 684 | print "add index" + str(index) + " image, this is final image" |
| 685 | img_str = os.path.join(bin_tmp_path, "tmp_" + str(index) + ".bin") |
| 686 | img_array.append(img_str) |
| 687 | size_array.append(final_size) |
| 688 | offset_array.append(pre_pos) |
| 689 | img_name_array.append(img_name) |
| 690 | pre_pos = last_pos |
| 691 | final_size = 0 |
| 692 | break |
| 693 | |
| 694 | file1.close() |
| 695 | if match_target == 0: |
| 696 | print "img name not match,exit!!" |
| 697 | return None, None, None, None |
| 698 | return img_array, size_array, offset_array, img_name_array |
| 699 | |
| 700 | def check_is_raw(img_file): |
| 701 | """ |
| 702 | check whether image is raw image format, which includes |
| 703 | images with mkimage header and modem image. |
| 704 | """ |
| 705 | is_raw = 0 |
| 706 | is_md = 0 |
| 707 | print img_file |
| 708 | file1 = open(img_file, 'rb') |
| 709 | header_size = struct.calcsize(MKIMAGE_HDR_FMT) |
| 710 | fin = file1.read(header_size) |
| 711 | |
| 712 | unpack_array = struct.unpack(MKIMAGE_HDR_FMT, fin) |
| 713 | file1.close() |
| 714 | |
| 715 | hdr_size = unpack_array[6] |
| 716 | img_type = unpack_array[8] |
| 717 | |
| 718 | if cmp(unpack_array[0], int(MKIMAGE_HDR_MAGIC)) == 0: |
| 719 | img_type_byte0 = img_type & 0xFF |
| 720 | img_type_byte3 = (img_type >> 24) & 0xFF |
| 721 | |
| 722 | if img_type == 0: |
| 723 | print "Raw IMG" |
| 724 | is_raw = 1 |
| 725 | elif img_type_byte3 == 1: |
| 726 | if img_type_byte0 == 0: |
| 727 | print "MD IMG:LTE" |
| 728 | is_raw = 1 |
| 729 | is_md = 1 |
| 730 | elif img_type_byte0 == 1: |
| 731 | print "MD IMG:C2K" |
| 732 | is_raw = 1 |
| 733 | is_md = 2 |
| 734 | else: |
| 735 | print "Not Raw Img" |
| 736 | is_raw = 0 |
| 737 | return is_raw, is_md, hdr_size |
| 738 | |
| 739 | def get_vboot10_cert(img_file, img_size, context): |
| 740 | """ |
| 741 | parse certificate that follows boot image on vboot1.0 |
| 742 | """ |
| 743 | has_dm_cert = 0 |
| 744 | dm_cert = context['dm_cert'] |
| 745 | file_size = os.path.getsize(img_file) |
| 746 | if file_size <= img_size + 4: |
| 747 | return has_dm_cert |
| 748 | |
| 749 | file1 = open(img_file, 'rb') |
| 750 | fin = file1.read(img_size) |
| 751 | fin = file1.read(4) |
| 752 | |
| 753 | unpack_array = struct.unpack("<4c", fin) |
| 754 | |
| 755 | if ord(unpack_array[0]) == 0x30: |
| 756 | cert_size = (ord(unpack_array[2]) << 8) + ord(unpack_array[3]) + 4 |
| 757 | print hex(cert_size) |
| 758 | file2 = open(dm_cert, 'wb') |
| 759 | file1.seek(img_size) |
| 760 | file2.write(file1.read(cert_size)) |
| 761 | file2.close() |
| 762 | has_dm_cert = 1 |
| 763 | padding_file(dm_cert, 16) |
| 764 | file1.close() |
| 765 | return has_dm_cert |
| 766 | |
| 767 | |
| 768 | def check_is_md(img_file): |
| 769 | """ |
| 770 | check whether it's modem image. |
| 771 | """ |
| 772 | #parse bin |
| 773 | file1 = open(img_file, 'rb') |
| 774 | header_size = struct.calcsize(CCCI_HDR_FMT) |
| 775 | fin = file1.read(header_size) |
| 776 | unpack_array = struct.unpack(CCCI_HDR_FMT, fin) |
| 777 | file1.close() |
| 778 | magic_str = "" |
| 779 | for i in range(0, 7): |
| 780 | magic_str = magic_str + unpack_array[i] |
| 781 | return 0 |
| 782 | |
| 783 | def check_is_boot(img_file): |
| 784 | """ |
| 785 | check whether it's boot/recovery image. |
| 786 | """ |
| 787 | #parse bin |
| 788 | img_size = 0 |
| 789 | is_boot = 0 |
| 790 | hdr_size = 0 |
| 791 | |
| 792 | file1 = open(img_file, 'rb') |
| 793 | header_size = struct.calcsize(BOOTIMG_HDR_FMT) |
| 794 | |
| 795 | fin = file1.read(header_size) |
| 796 | unpack_array = struct.unpack(BOOTIMG_HDR_FMT, fin) |
| 797 | file1.close() |
| 798 | magic_str = "" |
| 799 | for i in range(0, 7): |
| 800 | magic_str = magic_str + unpack_array[i] |
| 801 | |
| 802 | if cmp(magic_str, BOOTIMG_HDR_MAGIC) == 0: |
| 803 | print "Is Boot Img" |
| 804 | page_size = unpack_array[15] |
| 805 | hdr_size = page_size |
| 806 | kernel_size = (unpack_array[8] + (page_size - 1)) / page_size * page_size |
| 807 | ramdisk_size = (unpack_array[10] + (page_size - 1)) / page_size * page_size |
| 808 | #recovery dtbo image |
| 809 | dtbo_size = (unpack_array[1578] + (page_size - 1)) / page_size * page_size |
| 810 | #dtb image |
| 811 | dtb_size = (unpack_array[1581] + (page_size - 1)) / page_size * page_size |
| 812 | print "Header size:" + `hex(header_size)` |
| 813 | print "Kernel size:" + `hex(kernel_size)` |
| 814 | print "Ramdisk size:" + `hex(ramdisk_size)` |
| 815 | print "DTBO size:" + `hex(dtbo_size)` |
| 816 | print "dtb size:" + `hex(dtb_size)` |
| 817 | print "page size:" + `hex(unpack_array[15])` |
| 818 | img_size = (kernel_size + ramdisk_size + hdr_size + dtbo_size + dtb_size + (16 - 1)) / 16 * 16 |
| 819 | print "Total Size(include header and padding):" + `hex(img_size)` |
| 820 | print hex(img_size) |
| 821 | is_boot = 1 |
| 822 | else: |
| 823 | print "Not Boot Img" |
| 824 | |
| 825 | return is_boot, img_size, hdr_size |
| 826 | |
| 827 | def check_is_dtbo(img_file): |
| 828 | """ |
| 829 | check whether it's dtbo image. |
| 830 | """ |
| 831 | #parse bin |
| 832 | img_size = 0 |
| 833 | is_dtbo = 0 |
| 834 | hdr_size = 0 |
| 835 | file1 = open(img_file, 'rb') |
| 836 | header_size = struct.calcsize(DTBO_HDR_FMT) |
| 837 | |
| 838 | fin = file1.read(header_size) |
| 839 | unpack_array = struct.unpack(DTBO_HDR_FMT, fin) |
| 840 | file1.close() |
| 841 | |
| 842 | if unpack_array[0] == DTBO_HDR_MAGIC: |
| 843 | print "Is DTBO Img" |
| 844 | hdr_size = unpack_array[2] |
| 845 | img_size = unpack_array[1] |
| 846 | print "Header size:" + `hex(hdr_size)` |
| 847 | print "Image size:" + `hex(img_size)` |
| 848 | print "Total Size" + `hex(unpack_array[1])` |
| 849 | is_dtbo = 1 |
| 850 | else: |
| 851 | print "Not dtbo Img" |
| 852 | |
| 853 | return is_dtbo, img_size, hdr_size |
| 854 | |
| 855 | def fill_cert_config(cert_path, replace_str, tgt_line_pattern): |
| 856 | """ |
| 857 | We provide certificate configuration template and could |
| 858 | generate cerificate based on the configuration. Before that, |
| 859 | you need to fill up the configuration template so certificate |
| 860 | generation engine knows how to generate certificate. |
| 861 | """ |
| 862 | os.chmod(cert_path, stat.S_IWRITE + stat.S_IREAD) |
| 863 | |
| 864 | file1 = open(cert_path, 'r') |
| 865 | lines = file1.readlines() |
| 866 | file1.close() |
| 867 | |
| 868 | file2 = open(cert_path, 'w') |
| 869 | |
| 870 | format1 = re.compile(tgt_line_pattern) |
| 871 | for line in lines: |
| 872 | if format1.match(line): |
| 873 | print line |
| 874 | line2 = line.split("::=")[0] + "::= " + replace_str + "\n" |
| 875 | print line2 |
| 876 | file2.write(line2) |
| 877 | else: |
| 878 | file2.write(line) |
| 879 | |
| 880 | def padding_file(input_file, align_num): |
| 881 | """ |
| 882 | Fill 0 to make input_file size multiple of align_num. |
| 883 | """ |
| 884 | filesize = os.stat(input_file).st_size |
| 885 | file1 = open(input_file, 'ab+') |
| 886 | padding = filesize % align_num |
| 887 | if padding != 0: |
| 888 | padding = align_num - padding |
| 889 | for _ in range(padding): |
| 890 | file1.write("\x00") |
| 891 | file1.close() |
| 892 | |
| 893 | def append_file(img_file, cert_file): |
| 894 | """ |
| 895 | Append cert_file to the end of img_file. |
| 896 | """ |
| 897 | padding_file(img_file, 16) |
| 898 | file1 = open(img_file, 'ab+') |
| 899 | file2 = open(cert_file, 'rb') |
| 900 | file1.write(file2.read()) |
| 901 | file1.close() |
| 902 | file2.close() |
| 903 | |
| 904 | def get_pure_img(img_file, img_array, size_array, offset_array): |
| 905 | """ |
| 906 | Put sub-image data into array for composite image. |
| 907 | """ |
| 908 | index = 0 |
| 909 | file2 = open(img_file, 'rb') |
| 910 | for sub_img in img_array: |
| 911 | img_size = size_array[index] |
| 912 | offset = offset_array[index] |
| 913 | file2.seek(offset) |
| 914 | file1 = open(sub_img, 'wb+') |
| 915 | file1.write(file2.read(img_size)) |
| 916 | file1.close() |
| 917 | index += 1 |
| 918 | file2.close() |
| 919 | |
| 920 | def backup_file(tmp_file, target_file, backup_file_path): |
| 921 | """ |
| 922 | Backup target_file to backup_file_path |
| 923 | """ |
| 924 | if backup_file_path != "": |
| 925 | shutil.move(target_file, backup_file_path) |
| 926 | shutil.move(tmp_file, target_file) |
| 927 | |
| 928 | def cat_img(img_array, final_bin): |
| 929 | """ |
| 930 | Concatenate data in img_array to form final_bin, |
| 931 | which is a composite image. |
| 932 | """ |
| 933 | file1 = open(final_bin, 'wb') |
| 934 | index = 0 |
| 935 | for img in img_array: |
| 936 | file2 = open(img, 'rb') |
| 937 | file1.write(file2.read()) |
| 938 | file2.close() |
| 939 | index += 1 |
| 940 | file1.close() |
| 941 | |
| 942 | def add_mkimg_header(cert_name, img_list_end, img_type, img_name, context): |
| 943 | """ |
| 944 | mkimage header is the header for Mediatek proprietary images. |
| 945 | This function is used to generate mkimage header for |
| 946 | certificate files. |
| 947 | |
| 948 | """ |
| 949 | mkimage_config = context['mkimage_config'] |
| 950 | mkimage_config_out = context['mkimage_config_out'] |
| 951 | tmpcert_name = context['tmpcert_name'] |
| 952 | file1 = open(mkimage_config, 'r') |
| 953 | file2 = open(mkimage_config_out, 'w+') |
| 954 | format1 = re.compile("IMG_LIST_END") |
| 955 | format2 = re.compile("IMG_TYPE") |
| 956 | format3 = re.compile("NAME") |
| 957 | for line in file1: |
| 958 | if format1.match(line): |
| 959 | end = line.split("=")[1] |
| 960 | line2 = line.replace(end, str(img_list_end)) |
| 961 | file2.write(line2 + "\n") |
| 962 | elif format2.match(line): |
| 963 | end = line.split("=")[1] |
| 964 | line2 = line.replace(end, str(img_type)) |
| 965 | file2.write(line2 + "\n") |
| 966 | elif format3.match(line): |
| 967 | end = line.split("=")[1] |
| 968 | line2 = line.replace(end, str(img_name)) |
| 969 | file2.write(line2 + "\n") |
| 970 | else: |
| 971 | file2.write(line) |
| 972 | |
| 973 | file1.close() |
| 974 | file2.close() |
| 975 | |
| 976 | img_hdr = lib.mkimghdr.mkimage_hdr() |
| 977 | img_hdr.update_mkimage_hdr(cert_name, mkimage_config_out) |
| 978 | img_hdr.pack() |
| 979 | img_hdr.output(cert_name, tmpcert_name) |
| 980 | shutil.move(tmpcert_name, cert_name) |
| 981 | |
| 982 | def get_md_key(md_img, is_md, context): |
| 983 | """ |
| 984 | Get modem public key from modem image |
| 985 | """ |
| 986 | found = 0 |
| 987 | cert1md_hash_path = context['cert1md_hash_path'] |
| 988 | md_key_path = os.path.join(cert1md_hash_path, "md_key.bin") |
| 989 | |
| 990 | if is_md == 1: |
| 991 | md1_handler = lib.getPublicKey.md1_image() |
| 992 | found = md1_handler.parse(md_img) |
| 993 | if found: |
| 994 | md1_handler.output(md_img, md_key_path) |
| 995 | print "output file done" |
| 996 | elif is_md == 2: |
| 997 | md3_handler = lib.getPublicKey.md3_image() |
| 998 | found = md3_handler.parse(md_img) |
| 999 | if found: |
| 1000 | md3_handler.output(md_img, md_key_path) |
| 1001 | print "output file done" |
| 1002 | else: |
| 1003 | print "wrong md type!!!" |
| 1004 | |
| 1005 | return md_key_path |
| 1006 | |
| 1007 | def img_split(img, split_path, hdr_size): |
| 1008 | """ |
| 1009 | split image into header and image body |
| 1010 | """ |
| 1011 | split_header = os.path.join(split_path, "header.bin") |
| 1012 | split_image = os.path.join(split_path, "image.bin") |
| 1013 | |
| 1014 | file1 = open(img, 'rb') |
| 1015 | file2 = open(split_header, 'wb') |
| 1016 | file2.write(file1.read(hdr_size)) |
| 1017 | file2.close() |
| 1018 | file2 = open(split_image, 'wb') |
| 1019 | file2.write(file1.read()) |
| 1020 | file2.close() |
| 1021 | file1.close() |
| 1022 | padding_file(split_image, 16) |
| 1023 | |
| 1024 | return split_header, split_image |
| 1025 | |
| 1026 | def endiness_convert(in_file, out_file): |
| 1027 | """ |
| 1028 | Converts endian of in_file and save result to out_file. |
| 1029 | """ |
| 1030 | endian = sys.byteorder |
| 1031 | if endian == "little": |
| 1032 | file1 = open(out_file, "wb") |
| 1033 | file2 = open(in_file, "rb") |
| 1034 | from array import array |
| 1035 | for _ in range(8, 0, -1): |
| 1036 | tmp = array("B", file2.read(4)) |
| 1037 | tmp.reverse() |
| 1038 | tmp.tofile(file1) |
| 1039 | file2.close() |
| 1040 | file1.close() |
| 1041 | |
| 1042 | def fill_arg_dict(input_string, key, args): |
| 1043 | """ |
| 1044 | Fill up argument dictionary from input parameters |
| 1045 | """ |
| 1046 | prefix = input_string.split("=")[0].strip() |
| 1047 | fmt = re.compile(key, re.I) |
| 1048 | if fmt.search(prefix): |
| 1049 | val = input_string.split("=")[1].strip() |
| 1050 | args[key] = val |
| 1051 | print key + ": " + val |
| 1052 | print args[key] |
| 1053 | return args |
| 1054 | |
| 1055 | def parse_arg(argv): |
| 1056 | """ |
| 1057 | Parse input arguments and save the result into argument dictionary. |
| 1058 | """ |
| 1059 | args = {'type': 0, \ |
| 1060 | 'img': 0, \ |
| 1061 | 'privk': 0, \ |
| 1062 | 'pubk': 0, \ |
| 1063 | 'cert1': 0, \ |
| 1064 | 'swID': 0, \ |
| 1065 | 'ver': 0, \ |
| 1066 | 'name': '', \ |
| 1067 | 'group': 0, \ |
| 1068 | 'root_key_padding': 0, \ |
| 1069 | 'getHashList': 0, \ |
| 1070 | 'env_cfg': 0, \ |
| 1071 | 'platform': 'NOT_SET', \ |
| 1072 | 'project': 'NOT_SET', \ |
| 1073 | 'socid': '0'} |
| 1074 | for input_string in argv: |
| 1075 | for key in args: |
| 1076 | args = fill_arg_dict(input_string, key, args) |
| 1077 | input_wrong = 0 |
| 1078 | |
| 1079 | #check input |
| 1080 | if args['type'] == "cert1": |
| 1081 | if args['privk'] == "" or args['pubk'] == "": |
| 1082 | print "wrong cert1 input" |
| 1083 | input_wrong = 1 |
| 1084 | elif args['type'] == "cert2": |
| 1085 | if args['privk'] == "" or args['cert1'] == "" or args['img'] == "" or args['name'] == "": |
| 1086 | print "wrong cert2 input" |
| 1087 | elif args['type'] == "cert1md": |
| 1088 | if args['img'] == "" or args['privk'] == "": |
| 1089 | print "wrong cert1md input" |
| 1090 | else: |
| 1091 | print "wrong cert type!" |
| 1092 | input_wrong = 1 |
| 1093 | if input_wrong == 1: |
| 1094 | help_menu() |
| 1095 | sys.exit() |
| 1096 | |
| 1097 | if args['env_cfg'] == 0: |
| 1098 | #env_cfg is not given, we set it to env.cfg in path of this tool |
| 1099 | args['env_cfg'] = os.path.join(os.path.dirname(__file__), 'env.cfg') |
| 1100 | return args |
| 1101 | |
| 1102 | def help_menu(): |
| 1103 | """ |
| 1104 | Print usage for this tool. |
| 1105 | """ |
| 1106 | print "Gen Cert1:" |
| 1107 | print " usage: python sign.py type=cert1 privk=[cert1_privk.pem] pubk=[cert2_pubk.pem]" |
| 1108 | print " optional: swID=[number] ver=[number] group=[number] " |
| 1109 | print " output: cert1" |
| 1110 | print "Gen Cert2 and append cert1,cert2 to the image:" |
| 1111 | print " usage: python sign.py type=cert2 img=[xxx.bin] name=[img name] cert1=[cert1.der] \ |
| 1112 | privk=[cert2_privk.pem]" |
| 1113 | print " optional:ver=number" |
| 1114 | print " output: image append with cert1 and cert2" |
| 1115 | print "Gen Cert1md:" |
| 1116 | print " usage: python sign.py type=cert1md img=[xxx.bin] privk=[cert1md_privk.pem] \ |
| 1117 | pubk=[cert2_pubk.pem]" |
| 1118 | print " output: cert1md" |
| 1119 | |
| 1120 | def main(): |
| 1121 | """ |
| 1122 | Main function when this tool is executed from command line. |
| 1123 | """ |
| 1124 | if len(sys.argv) < 3: |
| 1125 | help_menu() |
| 1126 | |
| 1127 | sign = Sign() |
| 1128 | sign.args = parse_arg(sys.argv) |
| 1129 | sign.sign_op() |
| 1130 | |
| 1131 | if __name__ == '__main__': |
| 1132 | main() |