def _post_process(self, image, pil_splitter_path, meta_build_path): ''' Replacement tags in postsign commands for images. ''' TAG_OUTPUT_DIR = '$(OUTPUT_DIR)' TAG_PIL_SPLITTER = '$(PIL_SPLITTER)' TAG_IMAGE_FILE = '$(IMAGE_FILE)' REPL_META_PATH = '$(META_BUILD)' if image.pil_split: image_file = image.image_under_operation self._pil_split(image_file, os.path.splitext(image_file)[0]) if image.post_process_commands: # Ensure pil splitter is available if pil_splitter_path.find(REPL_META_PATH) != -1: if not meta_build_path: raise RuntimeError('Metabuild path is not available for pil splitter') pil_splitter_path = pil_splitter_path.replace(REPL_META_PATH, meta_build_path) if not c_path.validate_file(pil_splitter_path): raise RuntimeError('Cannot access pil splitter at: ' + pil_splitter_path) # Run all the commands for cmd in [c.strip() for c in image.post_process_commands.split()]: # Perform any needed replacements cmd = cmd.replace(TAG_OUTPUT_DIR, os.path.dirname(image.image_under_operation)) cmd = cmd.replace(TAG_PIL_SPLITTER, pil_splitter_path) cmd = cmd.replace(TAG_IMAGE_FILE, image.image_under_operation) logger.info('Running postsign command: ' + cmd) err = os.system(cmd) logger.info('Result: ' + str(err))
def _validate_sign(self, image, parsegen): if parsegen.is_signed(): signer = Signer(image.config) if signer.validate(parsegen): logger.info('Image ' + image.image_under_operation + ' signature is valid') else: raise RuntimeError('Image ' + image.image_under_operation + ' signature is not valid') else: raise RuntimeError('Image ' + image.image_under_operation + ' is not signed')
def chipset(self, chipset): # Log if the chipset is changed try: selected_chipset = self.chipset if selected_chipset: logger.note('Switching chipset from "' + selected_chipset + '" to "' + chipset + '"') except Exception: pass # Update the config path based on the given chipset config_path = self._config_dir_obj.get_chipset_config_path(chipset) if config_path is None: raise RuntimeError('Config file is not found for chipset: ' + str(chipset)) self.config_path = config_path logger.info('Chipset is set to: ' + chipset)
def sign(self, signingpackage_fname, outputdir): signaturepackage_binary = None cmds = self._getCmds(signingpackage_fname, outputdir) cass_server = self.cass_signer_attributes.server.host if self.cass_signer_attributes.server else "default CASS server" logger.info("Connecting to {0}".format(cass_server)) output = self._executeCmds(cmds) logger.debug(output) signaturepackage_filepath = os.path.join(outputdir, self.SIGNATUREPACKPAGE_RELPATH) if os.path.isfile(signaturepackage_filepath): logger.info("Signature package retrieved from server.") signaturepackage_binary = c_misc.load_data_from_file(signaturepackage_filepath) #clean up path, filename = os.path.split(signaturepackage_filepath) shutil.rmtree(path) return signaturepackage_binary
def sign(self, binary_to_sign, imageinfo, debug_dir=None): ''' This function returns a SignerOutput object which has all the security assets generated by the signer. ''' self._signer_impl.validate_inputs(imageinfo.signing_attributes, imageinfo.general_properties) hasher = Hasher() hmacParams = signerutils.get_hmac_params_from_config(imageinfo.signing_attributes) hash_to_sign=hasher.qcom_hmac(binary_to_sign, hmacParams) signer_output = self._signer_impl.sign(hash_to_sign, imageinfo, binary_to_sign, debug_dir) #print certificate properties attestation_cert_obj = Certificate(signer_output.attestation_cert) logger.info('\nAttestation Certificate Properties:\n' + str(attestation_cert_obj)) return signer_output
def _generate_signing_package(self, hash_to_sign, signing_attributes, cass_signer_attributes, image_path, signingpackage_fname, binary_to_sign): signingpackage = SigningPackage(secimage.__version__) signingrequest = signingpackage.createSigningRequest("image_to_sign=%s" % image_path) hexbindigest = binascii.b2a_hex(hash_to_sign) logger.debug("Digest to sign (hexbinary)= [%s]" % hexbindigest) signingrequest.setDigest(hexbindigest) signingrequest.setCapability(cass_signer_attributes.capability) signingrequest.setSigningAttribute(Certificate.SIGNATTR_SW_SIZE, "0x%.8X" % len(binary_to_sign)) hmac_params = signerutils.get_hmac_params_from_config(signing_attributes) signingrequest.setSigningAttribute(Certificate.SIGNATTR_HW_ID, "0x%s" % hmac_params.msm_id_str) signingrequest.setSigningAttribute(Certificate.SIGNATTR_SW_ID, signing_attributes.sw_id) signingrequest.setSigningAttribute(Certificate.SIGNATTR_MODEL_ID, signing_attributes.model_id) signingrequest.setSigningAttribute(Certificate.SIGNATTR_OEM_ID, signing_attributes.oem_id) if signing_attributes.debug: signingrequest.setSigningAttribute(Certificate.SIGNATTR_DEBUG, signing_attributes.debug) if signing_attributes.app_id: signingrequest.setSigningAttribute(Certificate.SIGNATTR_APP_ID, signing_attributes.app_id) if signing_attributes.crash_dump: signingrequest.setSigningAttribute(Certificate.SIGNATTR_CRASH_DUMP, signing_attributes.crash_dump) if self._is_tcg_supported(signing_attributes) is True: signingrequest.setSigningAttribute(Certificate.SIGNATTR_TCG_MIN, signing_attributes.tcg_min) signingrequest.setSigningAttribute(Certificate.SIGNATTR_TCG_MAX, signing_attributes.tcg_max) else: #opendsp does not CASS_SIGNATTR_USE_EXP3 currently if signing_attributes.exponent == 3: signingrequest.setSigningAttribute(self.CASS_SIGNATTR_USE_EXP3, 'TRUE') elif signing_attributes.exponent == 65537: signingrequest.setSigningAttribute(self.CASS_SIGNATTR_USE_EXP3, 'FALSE') else: raise RuntimeError, "Exponent value of {0} is invalid!".format(signing_attributes.exponent) # Set signature algorithm to SHA256 by default signingrequest.setSigningAttribute(Certificate.SIGNATTR_SHA256, 'TRUE') pathname, fname = os.path.split(signingpackage_fname) c_path.create_dir(pathname) signingpackage.toxml() signingpackage.saveToFile(signingpackage_fname) logger.info("Signing package created. Digest = [%s]" % signingpackage.getDigest()) return signingpackage
def mini_build_path(self, mini_build_path): # Log if the mini_build_path is changed selected_mini_build_path = self.mini_build_path if selected_mini_build_path: logger.note('Switching mini_build_path: ' + '\n' ' ' + 'from: ' + selected_mini_build_path + '\n' ' ' + ' to: ' + mini_build_path) # Update the mini_build_path self._stager.mini_build_path = mini_build_path logger.info('Minimized Build is set to: ' + mini_build_path) # Clear the output dir setting try: self._stager.output_dir = '' except Exception: pass
def config_path(self, config_path): # Log if the config_path is changed try: selected_config_path = self.config_path if selected_config_path: logger.note('Switching config_path: ' + '\n' ' ' + 'from: ' + selected_config_path + '\n' ' ' + ' to: ' + config_path) except Exception: pass # Update the config_path self._img_config_parser = ConfigParser(config_path) logger.info('Config path is set to: ' + config_path) # Reset the stager at this point if self._stager is not None: logger.note('Resetting image list due to config path change.') self._stager = None
def _sign_image(self, image, parsegen): logger.info('Resigning signed' if parsegen.is_signed() else 'Signing' ' image: ' + image.image_under_operation) c_path.create_debug_dir(image.dest_image.debug_dir_signer) signer = Signer(image.config) # TODO: a sanity check here # data_to_sign = parsegen.data_to_sign # if data_to_sign != parsegen.data_to_sign: # raise RuntimeError('Data to sign is changing') sign_assets = signer.sign(parsegen.data_to_sign, image, image.dest_image.debug_dir_signer) # Dump any debug information self.dump_signer_debug_data(image, sign_assets) parsegen.data_signature = sign_assets.signature parsegen.cert_chain = sign_assets.cert_chain
def output_dir(self, output_dir): # Log if the output_dir is changed try: selected_output_dir = self.output_dir if selected_output_dir: logger.note('Switching output_dir: ' + '\n' ' ' + 'from: ' + selected_output_dir + '\n' ' ' + ' to: ' + output_dir) except Exception: pass # Update the output_dir self._stager.output_dir = output_dir logger.info('Output dir is set to: ' + output_dir) # Clear the minimized build setting try: self._stager.mini_build_path = '' except Exception: pass
def _process(idx, image, sign_attr, integrity_check, sign, encrypt, decrypt, val_image, val_integrity_check, val_sign, val_encrypt): assert isinstance(image, ImageInfo) logger.info( '------------------------------------------------------') status_string = ('Processing ' + str(idx + 1) + '/' + str(total_image_count) + ': ' + image.image_under_operation) logger.info(status_string + '\n') # Send a progress notification to the toplevel progress.status = status_string progress.cur = idx progress.cur_stage = 0 file_logger_id = None image.authority = self.authority try: # Create the required directory structure for this image image_output_dir = image.dest_image.image_dir try: c_path.create_dir(image_output_dir) except Exception as e: raise RuntimeError('Could not create output directory: ' + image_output_dir + '\n' ' ' + 'Error: ' + str(e)) # Enable/Disable debug image.dest_image.debug_enable = self.debug c_path.create_debug_dir(image.dest_image.debug_dir) # Set the root cert hash image.validation_root_cert_hash = root_cert_hash # Enable file logging to the directory file_logger_id = logger.add_file_logger( c_path.join(image_output_dir, 'SecImage_log.txt'), logger.verbosity) # Create the security policies list for this image security_policy_list = create_security_policy_list(image) # Parsegen object parsegen = None # For secure operations if integrity_check or sign or encrypt or decrypt: parsegen = self._process_secure_operation( image, progress, security_policy_list, sign_attr, integrity_check, sign, encrypt, decrypt) # For validation if val_image or val_integrity_check or val_sign or val_encrypt: # Bypass validation when encrypted key provide is configured as UIE server because decryption will always fail if parsegen is not None and parsegen.is_encrypted( ) and encrypted_key_provider_id_supported( image.general_properties.UIE_key): logger.warning( "Skipping validation because encrypted key provider is configured as UIE server" ) else: parsegen = self._process_validation( image, progress, security_policy_list, val_image, val_integrity_check, val_sign, val_encrypt) # Print the image data if parsegen is not None: logger.info('\n' + str(parsegen)) # Set overall processing to true if not ((val_image and image.status.validate_parsegen.state == StatusInfo.ERROR) or (val_integrity_check and image.status.validate_integrity_check.state == StatusInfo.ERROR) or (val_sign and image.status.validate_sign.state == StatusInfo.ERROR) or (val_encrypt and image.status.validate_encrypt.state == StatusInfo.ERROR)): image.status.overall.state = StatusInfo.SUCCESS except RemoteSignerNote as e: logger.info('NOTE: ' + str(e), color=logger.YELLOW) except Exception: logger.error(traceback.format_exc()) logger.error(sys.exc_info()[1]) finally: if file_logger_id is not None: logger.removeFileLogger(file_logger_id) logger.info( '------------------------------------------------------\n')
def print_summary(args, image_info_list): """Prints the summary of the actions performed by SecImage""" actions = [] # Check which actions were performed if args.integrity_check: actions.append('integrity_check') if args.sign: actions.append('sign') if args.encrypt: actions.append('encrypt') if args.validate: actions.append('validate') if not actions: return # Figure out the output directory output_print = (('Output is saved at: ' + args.output_dir + '\n') if args.output_dir else ('Minimized build was updated at: ' + args.mini_build + '\n') if args.mini_build else '\n') # Log the actions and output directory logger.info('SUMMARY:' + '\n' + 'Following actions were performed: "' + ', '.join(actions) + '"' + '\n' + output_print) # Table information summary_table = TablePrinter([1]) # summary_table = TablePrinter([0]) COLUMN_IDX = 0 COLUMN_SIGN_ID = 1 COLUMN_PARSE = 2 COLUMN_INTEGRITY_CHECK = 3 COLUMN_SIGN = 4 COLUMN_ENCRYPT = 5 COLUMN_VAL_PARSE = 6 COLUMN_VAL_INTEGRITY_CHECK = 7 COLUMN_VAL_SIGN = 8 COLUMN_VAL_ENCRYPT = 9 # First row summary_table.insert_data(0, COLUMN_IDX, 'Idx') summary_table.insert_data(0, COLUMN_SIGN_ID, 'SignId') summary_table.insert_data(0, COLUMN_PARSE, 'Parse') summary_table.insert_data(0, COLUMN_INTEGRITY_CHECK, 'Integrity') summary_table.insert_data(0, COLUMN_SIGN, 'Sign') summary_table.insert_data(0, COLUMN_ENCRYPT, 'Encrypt') summary_table.insert_data(0, COLUMN_VAL_PARSE, 'Validate', column_end=COLUMN_VAL_ENCRYPT) # Second row summary_table.insert_data(1, COLUMN_VAL_PARSE, 'Parse') summary_table.insert_data(1, COLUMN_VAL_INTEGRITY_CHECK, 'Integrity') summary_table.insert_data(1, COLUMN_VAL_SIGN, 'Sign') summary_table.insert_data(1, COLUMN_VAL_ENCRYPT, 'Encrypt') # Data rows for idx, image in enumerate(image_info_list): idx += 2 summary_table.insert_data(idx, COLUMN_IDX, str(idx - 1) + '.') summary_table.insert_data(idx, COLUMN_SIGN_ID, image.sign_id) summary_table.insert_data(idx, COLUMN_PARSE, image.status.parsegen.state) summary_table.insert_data(idx, COLUMN_INTEGRITY_CHECK, image.status.integrity_check.state) summary_table.insert_data(idx, COLUMN_SIGN, image.status.sign.state) summary_table.insert_data(idx, COLUMN_ENCRYPT, image.status.encrypt.state) summary_table.insert_data(idx, COLUMN_VAL_PARSE, image.status.validate_parsegen.state) summary_table.insert_data(idx, COLUMN_VAL_INTEGRITY_CHECK, image.status.validate_integrity_check.state) summary_table.insert_data(idx, COLUMN_VAL_SIGN, image.status.validate_sign.state) summary_table.insert_data(idx, COLUMN_VAL_ENCRYPT, image.status.validate_encrypt.state) # TODO: put the error and image paths logger.info(summary_table.get_data())
def _process_secure_operation(self, image, progress, security_policy_list, sign_attr, i_integrity_check, i_sign, i_encrypt, i_decrypt, idx=0, prefix_override=None): from imageinfo import ImageInfo, StatusInfo # Check bounds if len(security_policy_list) == 0: raise RuntimeError('Security policy list must not be empty.') elif len(security_policy_list) <= idx: raise RuntimeError( 'Security policy list length must be more than index.') # Get the current security policy file_type = security_policy_list[idx].file_type integrity_check = security_policy_list[ idx].integrity_check and i_integrity_check sign = security_policy_list[idx].sign and i_sign encrypt = security_policy_list[idx].encrypt and i_encrypt decrypt = security_policy_list[idx].encrypt and i_decrypt # Create the encryptor object encdec = None if image.general_properties.selected_encryptor: c_path.create_debug_dir(image.dest_image.debug_dir_encdec) encdec = get_encdec(image, False) # Create the parsegen object file_type_backup = image.image_type.file_type encdec_backup = image.encdec image.image_type.file_type = file_type image.encdec = encdec try: parsegen = self._status_updater(self._create_parsegen_obj, image.status.parsegen, progress, True, image, False, sign, prefix_override, sign_attr) finally: image.image_type.file_type = file_type_backup image.encdec = encdec_backup # Validate the authority settings self.validate_authority_settings( self.authority, image.general_properties.secboot_version, image.general_properties.qti_sign, image.general_properties.oem_sign, image.general_properties.num_root_certs, encrypt) # Do not allow signed unencrypted elf images to be encrypted as the # Sign will not longer match the encrypted image's tosign if parsegen.file_type() == 'elf' and parsegen.is_signed( ) and not sign and not parsegen.is_encrypted() and encrypt: raise RuntimeError( 'Cannot encrypt a signed unencrypted image without resigning ' 'as the sign no longer matches the format change.') # Set the security mechanisms parsegen.integrity_check = security_policy_list[ idx].integrity_check and (parsegen.contains_integrity_check() or integrity_check) parsegen.sign = security_policy_list[idx].sign and ( parsegen.is_signed() or sign) parsegen.encrypt = security_policy_list[idx].encrypt and ( False if decrypt else (parsegen.is_encrypted() or encrypt)) # Get blob if populating encryption parameters: if encrypt: if encdec is None: raise RuntimeError('Encryptor is not set') parsegen.encryption_params = encdec.get_encryption_parameters_blob( ) # check if input image is a TA, if yes re-initialize encdec object with updated bitmap for manifest segment if int(image.signing_attributes.sw_id, 16) == 0xC: non_encrypt_segment_found, encrypted_segments_indices = self._get_encrypted_segments_index_list( parsegen._elf_parsegen.phdrs) if non_encrypt_segment_found and len( encrypted_segments_indices) > 0: logger.info( "Re-initializing encdec object for updated segment bitmap" ) encdec = get_encdec(image, False, encrypted_segments_indices) parsegen.encryption_params = encdec.get_encryption_parameters_blob( ) parsegen.encdec = encdec elif parsegen.encryption_params and parsegen.encdec is not None: parsegen.encdec.update_encryption_parameters( parsegen.encryption_params) # Dump any debug data self.dump_parsegen_debug_data(image, parsegen) # If the security policy list contains more formats, call them if idx < len(security_policy_list) - 1: data = parsegen.get_wrapped_data() import tempfile tmp_fd = tempfile.NamedTemporaryFile(delete=False) tmp_fd.close() store_data_to_file(tmp_fd.name, data) # Backup the source path here src_image_dir_base = image.src_image.image_dir_base src_image_dir_ext = image.src_image.image_dir_ext src_image_name = image.src_image.image_name image.src_image.image_dir_base = os.path.dirname(tmp_fd.name) image.src_image.image_dir_ext = '' image.src_image.image_name = os.path.basename(tmp_fd.name) # Override debug dumped file prefix prefix_override = SecImageCore._get_prefix_override( prefix_override, file_type) try: data = self._process_secure_operation( image, progress, security_policy_list, sign_attr, i_integrity_check, i_sign, i_encrypt, i_decrypt, idx + 1, prefix_override) finally: image.src_image.image_dir_base = src_image_dir_base image.src_image.image_dir_ext = src_image_dir_ext image.src_image.image_name = src_image_name os.remove(tmp_fd.name) parsegen.set_wrapped_data(data) # Sign the image if sign: self._status_updater(self._sign_image, image.status.sign, progress, True, image, parsegen) # Package and generate the output image file data = parsegen.get_data() if integrity_check: image.status.integrity_check.state = StatusInfo.SUCCESS if encrypt: image.status.encrypt.state = StatusInfo.SUCCESS if idx != 0: return data if decrypt: encryption_params_backup = parsegen.encryption_params parsegen.encryption_params = '' try: store_data_to_file(image.dest_image.decrypted_file, parsegen.get_data()) finally: parsegen.encryption_params = encryption_params_backup else: store_data_to_file(image.dest_image.image_path, data) logger.info(('Signed ' if sign else '') + ('& ' if sign and encrypt else '') + ('Encrypted ' if encrypt else '') + 'image is stored at ' + image.dest_image.image_path) image.image_under_operation = image.dest_image.image_path # Do any post processing self._status_updater(self._post_process, image.status.postprocess, progress, True, image, image.config.post_process.pil_splitter, getattr(self._stager, '_meta_build_path', None)) return parsegen
def reset_workspace(self, chipset=None, oem=True, qc=True, ui=True, user=True): """Resets the :meth:`workspace` for the chipset that is provided. :meth:`config_dir` is searched for the files for the chipset. If the files are found in the config_dir, they are copied to the workspace, otherwise an exception is raised. :param str chipset: The chipset to reset in the workspace. :param bool oem: If the oem file should be updated. :param bool qc: If the qc file should be updated. :param bool ui: If the ui file should be updated. :param bool user: If the user file should be updated. :raise RuntimeError: If files for the chipset are not found in the the config_dir """ if chipset is None: chipset = self.chipset # Look for the config files in the config_dir try: template_oem, template_qc, template_ui, template_user = self._config_dir_obj.get_chipset_config_paths( chipset) except Exception as e: logger.warning( 'Template config files not found for copying to workspace for chipset: ' + chipset + '\n' ' ' + 'Error: ' + str(e)) raise # Create the directory in the workspace for this chipset self._workspace_dir_obj.create_chipset_dir(chipset) workspace_chipset_dir = self._workspace_dir_obj.get_chipset_dir( chipset) if not oem: # Copy the OEM template file logger.info( 'Copying template OEM config file to workspace for chipset: ' + chipset) shutil.copy(template_oem, workspace_chipset_dir) logger.note('OEM config file created at: ' + workspace_chipset_dir) if not qc: # Copy the QC template file logger.info( 'Copying template QC config file to workspace for chipset: ' + chipset) shutil.copy(template_qc, workspace_chipset_dir) logger.note('QC config file created at: ' + workspace_chipset_dir) if not ui: # Copy the UI template file logger.info( 'Copying template UI config file to workspace for chipset: ' + chipset) shutil.copy(template_ui, workspace_chipset_dir) logger.note('UI config file created at: ' + workspace_chipset_dir) if not user: # Copy the USER template file logger.info( 'Copying template USER config file to workspace for chipset: ' + chipset) shutil.copy(template_user, workspace_chipset_dir) logger.note('USER config file created at: ' + workspace_chipset_dir)
def _validate_encrypt(self, image, parsegen): if parsegen.is_encrypted(): logger.info('Image ' + image.image_under_operation + ' is encrypted') else: raise CustomError('Image ' + image.image_under_operation + ' is not encrypted')
def _validate_tcg_raw(self, tcg_min_attest, tcg_max_attest, tcg_min_ca, tcg_max_ca): tcg_ok = False if (self.config.general_properties.num_certs_in_certchain == 2) and \ (self.config.signing.signature_format == "opendsp"): logger.info("2-level certificate chain is not supported for opendsp signature") return False if tcg_min_attest is not None: assert(isinstance(tcg_min_attest, BaseAttribute)) if tcg_max_attest is not None: assert(isinstance(tcg_max_attest, BaseAttribute)) if tcg_min_ca is not None: assert(isinstance(tcg_min_ca, BaseAttribute)) if tcg_max_ca is not None: assert(isinstance(tcg_max_ca, BaseAttribute)) if ((tcg_min_attest is None) and (tcg_max_attest is None) and (tcg_min_ca is None) and (tcg_max_ca is None)): # This is ok. No TCGs in attest cert. tcg_ok = True logger.debug("\nNo TCGs found in Attestation cert or CA cert. This is OK.") elif ((tcg_min_attest is not None) and (tcg_max_attest is not None) and (tcg_min_ca is None) and (tcg_max_ca is None)): logger.info("\nTCGs found in Attestation cert, but not in CA cert. This is invalid.") elif ((tcg_min_attest is None) and (tcg_max_attest is None) and (tcg_min_ca is not None) and (tcg_max_ca is not None)): logger.info("\nNo TCGs found in Attestation cert, but there are TCGs in CA cert. This is invalid.") elif ((tcg_min_attest is not None) and (tcg_max_attest is not None) and (tcg_min_ca is not None) and (tcg_max_ca is not None)): if (tcg_min_ca.value <= tcg_min_attest.value <= tcg_max_attest.value <= tcg_max_ca.value): tcg_ok = True logger.debug("\nTCG values fall within CA constraints.") else: logger.info("\nTCG values are outside the CA constraints.") else: logger.info("\nInvalid TCG values") tcg_log_mesg = "\nAttestation cert : tcg_min={0} tcg_max={1}". \ format(tcg_min_attest, tcg_max_attest) + \ "\nCA cert (allowed): tcg_min={0} tcg_max={1}\n". \ format(tcg_min_ca, tcg_max_ca) if (tcg_ok is False): logger.info(tcg_log_mesg) else: logger.debug(tcg_log_mesg) return tcg_ok
def create_subject_params_attest(self, in_params): def create_ou_field_from_hex_list(ou_num, ou_name, hex_list, remove_0x, max_num_items_in_ou): item_length = 0 ou_field = str(ou_num) for val in hex_list: item_length = len(val)-2 if remove_0x else len(val) ou_field += " " + (val[2:] if remove_0x else val) # fill remainder of OU field with zeros zeros = (" " + "0" * item_length) * (max_num_items_in_ou - len(hex_list)) ou_field += zeros ou_field += " " + ou_name return ou_field # GET SIGNING ATTRIBUTE DATA num_root_certs = int(self.signing_attributes.num_root_certs) if self.signing_attributes.num_root_certs is not None else None debug_val = int(self.signing_attributes.debug, 16) if self.signing_attributes.debug is not None else None debug_serials = self.signing_attributes.debug_serials.serial if self.signing_attributes.debug_serials is not None else [] oem_id = int(self.signing_attributes.oem_id, 16) & 0xFFFF model_id = int(self.signing_attributes.model_id, 16) & 0xFFFF app_id = int(self.signing_attributes.app_id, 16) if self.signing_attributes.app_id is not None else None crash_dump = int(self.signing_attributes.crash_dump, 16) if self.signing_attributes.crash_dump is not None else None rot_en = int(self.signing_attributes.rot_en, 16) if self.signing_attributes.rot_en is not None else None mask_soc_hw_version = int(self.signing_attributes.mask_soc_hw_version, 16) if self.signing_attributes.mask_soc_hw_version is not None else None in_use_soc_hw_version = self.signing_attributes.in_use_soc_hw_version if self.signing_attributes.in_use_soc_hw_version is not None else None soc_vers = self.signing_attributes.soc_vers use_serial_number_in_signing = self.signing_attributes.use_serial_number_in_signing if self.signing_attributes.use_serial_number_in_signing is not None else None oem_id_independent = self.signing_attributes.oem_id_independent if self.signing_attributes.oem_id_independent is not None else None revocation_enablement = int(self.signing_attributes.revocation_enablement, 16) if self.signing_attributes.revocation_enablement is not None else None activation_enablement = int(self.signing_attributes.activation_enablement, 16) if self.signing_attributes.activation_enablement is not None else None if self._is_oid_supported(self.signing_attributes) is True: if self.validate_oid_from_config(self.certs_info.ca.cert_path, self.signing_attributes) is False: raise ConfigError('{0} min and max are not set correctly in configuration.' \ 'Signing will not continue.'.format(self.signing_attributes.object_id.name) ) self.certs[self.ATTEST].extfile = self._generate_attestation_certificate_extensions( self.openssl_info.attest_ca_xts, self.signing_attributes.object_id.name, self.signing_attributes.object_id.min, self.signing_attributes.object_id.max) else: self.certs[self.ATTEST].extfile = self.openssl_info.attest_ca_xts # Get the binary to sign length if self.data_to_sign_len is None: if self.hash_to_sign is not None: self.data_to_sign_len = len(self.hash_to_sign) else: raise RuntimeError('Length of binary could not be computed') logger.info('Generating new Attestation certificate and a random key') hmac_params = HMAC() hmac_params.init_from_config(self.signing_attributes) certificate_ou_sw_id = '01 ' + '%.16X' % hmac_params.sw_id + ' SW_ID' certificate_ou_hw_id = '02 ' + '%.16X' % hmac_params.msm_id + ' HW_ID' certificate_ou_oem_id = '04 ' + '%0.4X' % oem_id + ' OEM_ID' certificate_ou_sw_size = '05 ' + '%0.8X' % self.data_to_sign_len + ' SW_SIZE' certificate_ou_model_id = '06 ' + '%0.4X' % model_id + ' MODEL_ID' certificate_hash_alg = certificate_hash_alg_map[self.signing_attributes.hash_algorithm] certificate_ou = [ certificate_ou_sw_id, certificate_ou_hw_id, certificate_ou_oem_id, certificate_ou_sw_size, certificate_ou_model_id, certificate_hash_alg ] # Optional attributes if debug_val is not None: certificate_ou_debug_id = '03 ' + '%0.16X' % debug_val + ' DEBUG' certificate_ou.append(certificate_ou_debug_id) if app_id is not None: certificate_app_id = '08 ' + '%0.16X' % app_id + ' APP_ID' certificate_ou.append(certificate_app_id) if crash_dump is not None: certificate_crash_dump = '09 ' + '%0.16X' % crash_dump + ' CRASH_DUMP' certificate_ou.append(certificate_crash_dump) if rot_en is not None: certificate_rot_en = '10 ' + '%0.16X' % rot_en + ' ROT_EN' certificate_ou.append(certificate_rot_en) if mask_soc_hw_version is not None: certificate_mask_soc_hw_version = '12 ' + '%0.4X' % mask_soc_hw_version + ' MASK_SOC_HW_VERSION' certificate_ou.append(certificate_mask_soc_hw_version) if in_use_soc_hw_version == 1: certificate_in_use_soc_hw_version = '13 ' + '%0.4X' % in_use_soc_hw_version + ' IN_USE_SOC_HW_VERSION' certificate_ou.append(certificate_in_use_soc_hw_version) if use_serial_number_in_signing == 1: certificate_use_serial_number_in_signing = '14 ' + '%0.4X' % use_serial_number_in_signing + ' USE_SERIAL_NUMBER_IN_SIGNING' certificate_ou.append(certificate_use_serial_number_in_signing) if oem_id_independent == 1: certificate_oem_id_independent = '15 ' + '%0.4X' % oem_id_independent + ' OEM_ID_INDEPENDENT' certificate_ou.append(certificate_oem_id_independent) # multiple debug serial use case certificate_ou_sn_list = [] for index in xrange(0, len(debug_serials), 6): serial_sublist = debug_serials[index: index+6] certificate_ou_sn_list.append(create_ou_field_from_hex_list(16, "SN", serial_sublist, True, 6)) certificate_ou_sn_list.reverse() certificate_ou.extend(certificate_ou_sn_list) # multiple soc hw version use case if soc_vers: if self.padding != self.PAD_PSS: logger.warning("soc_vers should be used with RSAPSS") certificate_ou.append(create_ou_field_from_hex_list(11, "SOC_VERS", soc_vers, True, 10)) # IOT MRC use case if num_root_certs > 1 and self.config.metadata.chipset in IOT_MRC_CHIPSETS: certificate_root_cert_sel = '17 ' + '%0.4X' % self.signing_attributes.mrc_index + ' ROOT_CERT_SEL' certificate_ou.append(certificate_root_cert_sel) if revocation_enablement is not None and revocation_enablement != 0: certificate_revocation_enablement = '18 ' + '%0.16X' % revocation_enablement + ' REVOCATION_ENABLEMENT' certificate_ou.append(certificate_revocation_enablement) if activation_enablement is not None and activation_enablement != 0: certificate_activation_enablement = '19 ' + '%0.16X' % activation_enablement + ' ACTIVATION_ENABLEMENT' certificate_ou.append(certificate_activation_enablement) # Handle OU property binding params = dict(in_params) if 'OU' in params.keys(): if type(params['OU']) == list: for item in params['OU']: certificate_ou.append(item) else: certificate_ou.append(params['OU']) params['OU'] = certificate_ou return params
def process(self, verify_setup=False, integrity_check=False, sign=False, encrypt=False, decrypt=False, val_image=False, val_integrity_check=False, val_sign=False, val_encrypt=False, progress_cb=PROGRESS_CB_PYPASS): """Performs the secure-image related operations specified from the params. :param bool verify_setup: Verify that the configuration of the object is correct and return. This will ignore any other params. :param bool integrity_check: Add integrity check to the image. :param bool sign: Sign the images. (Re-sign if image is already signed) :param bool encrypt: Encrypt the images. (Re-encrypt if image is already encrypted) :param bool val_image: Validate the integrity of the image against the config file. :param bool val_integrity_check: Validate the integrity check in the image. :param bool val_sign: Validate that the image is signed and validate the integrity of the signing related data. :param bool val_encrypt: Validate that the image is encrypted and validate the integrity of the encryption related data. :param cb progress_cb: Callback method to get a status update during processing. Callback method should have this format: :: def progress_cb(status_string, progress_percent): \""" :param str status_string: the current status. :param int progress_percent: the progress (in percent) \""" ... """ # Ensure that one or more image files is provided for processing if self._stager is None or not self.image_path_list: raise RuntimeError('Please specify one or more images for processing') # Ensure the correct set of operations is provided if not (verify_setup or integrity_check or sign or encrypt or decrypt or val_image or val_integrity_check or val_sign or val_encrypt): raise RuntimeError('Please specify one or more operations to perform.') if verify_setup: logger.note('The inputs provided (config, cmd args) are valid.') return # Start processing images total_images = len(self.image_info_list) progress = ProgressNotifier(total_images, progress_cb, PROGRESS_TOTAL_STAGES) for idx, image in enumerate(self.image_info_list): assert isinstance(image, ImageInfo) logger.info('------------------------------------------------------') status_string = ('Processing ' + str(idx + 1) + '/' + str(total_images) + ': ' + image.image_under_operation) logger.info(status_string + '\n') # Send a progress notification to the toplevel progress.status = status_string progress.cur = idx progress.cur_stage = 0 file_logger_id = None try: # Create the required directory structure for this image image_output_dir = image.dest_image.image_dir try: c_path.create_dir(image_output_dir) except Exception as e: raise RuntimeError('Could not create output directory: ' + image_output_dir + '\n' ' ' + 'Error: ' + str(e)) # Enable/Disable debug image.dest_image.debug_enable = self.debug c_path.create_debug_dir(image.dest_image.debug_dir) # Enable file logging to the directory file_logger_id = logger.add_file_logger(c_path.join(image_output_dir, 'SecImage_log.txt'), logger.verbosity) # Create the security policies list for this image security_policy_list = create_security_policy_list(image) # Parsegen object parsegen = None # For secure operations if integrity_check or sign or encrypt or decrypt: parsegen = self._process_secure_operation(image, progress, security_policy_list, integrity_check, sign, encrypt, decrypt) # For validation if val_image or val_integrity_check or val_sign or val_encrypt: parsegen = self._process_validation(image, progress, security_policy_list, val_image, val_integrity_check, val_sign, val_encrypt) # Print the image data if parsegen is not None: logger.info('\n' + str(parsegen)) # Set overall processing to true if not ((val_image and image.status.validate_parsegen.state == StatusInfo.ERROR) or (val_integrity_check and image.status.validate_integrity_check.state == StatusInfo.ERROR) or (val_sign and image.status.validate_sign.state == StatusInfo.ERROR) or (val_encrypt and image.status.validate_encrypt.state == StatusInfo.ERROR)): image.status.overall.state = StatusInfo.SUCCESS except Exception: logger.debug(traceback.format_exc()) logger.error(sys.exc_info()[1]) if file_logger_id is not None: logger.removeFileLogger(file_logger_id) logger.info('------------------------------------------------------\n') progress.complete()
def main(args, return_isc=False): """Parses the command line arguments, performs any basic operations based on the parsed arguments and starts processing using the isc module. """ # Log to file flids = logger.log_to_file(SECIMAGE_TOOL_NAME, args.output_dir) try: # Print the tool's launch command logged_args = CoreOptionParser.mask_private_args( sys.argv, args._c_spec_override_prefix) logger.info('\n\n SecImage launched as: "' + ' '.join(logged_args) + '"\n') # Initialize SecImageCore isc = SecImageCore(debug=args.debug) # Configure image signer if args.image_file or ( args.meta_build and not SecImageCore.meta_supports_sign_id(args.meta_build)): if args.chipset: isc.set_chipset(args.chipset, args._c_overrides, args._c_spec_overrides) elif args.config_path: isc.set_config_path(args.config_path, args._c_overrides, args._c_spec_overrides) if args.qti_signing: isc.authority = AUTHORITY_QTI # Set the input if args.image_file: isc.set_image_path(args.image_file, args.sign_id, args.m_gen, args.m_image_file) elif args.meta_build: isc.set_meta_build_path( args.meta_build, [] if args.sign_id is None else [args.sign_id], args.m_gen) # Set the output if args.mini_build: isc.mini_build_path = args.mini_build elif args.output_dir: isc.output_dir = args.output_dir # Process the images isc.process(verify_setup=args.verify_inputs, sign_attr=args.sign_attr, integrity_check=args.integrity_check, sign=args.sign, encrypt=args.encrypt, decrypt=args.decrypt, no_op=args.no_op, val_image=args.validate, val_integrity_check=args.validate, val_sign=args.validate, val_encrypt=args.validate, m_sign_attr=args.m_sign_attr, m_integrity_check=args.m_integrity_check, m_sign=args.m_sign, m_encrypt=args.m_encrypt, m_decrypt=args.m_decrypt, m_val_image=args.m_validate, m_val_integrity_check=args.m_validate, m_val_sign=args.m_validate, m_val_encrypt=args.m_validate, gen_multi_image=args.m_gen, root_cert_hash=args.rch) # Print the summary print_summary(args, isc.image_info_list, isc.multi_image_imageinfo_dict.values()) if return_isc: return isc else: return isc.image_info_list finally: # Clear all log handlers logger.removeFileLogger(flids)
def process(self, verify_setup=False, sign=False, encrypt=False, decrypt=False, val_image=False, val_sign=False, val_encrypt=False, progress_cb=PROGRESS_CB_PYPASS): """Performs the secure-image related operations specified from the params. :param bool verify_setup: Verify that the configuration of the object is correct and return. This will ignore any other params. :param bool sign: Sign the images. (Re-sign if image is already signed) :param bool encrypt: Encrypt the images. (Re-encrypt if image is already encrypted) :param bool val_image: Validate the integrity of the image against the config file. :param bool val_sign: Validate that the image is signed and validate the integrity of the signing related data. :param bool val_encrypt: Validate that the image is encrypted and validate the integrity of the encryption related data. :param cb progress_cb: Callback method to get a status update during processing. Callback method should have this format: :: def progress_cb(status_string, progress_percent): \""" :param str status_string: the current status. :param int progress_percent: the progress (in percent) \""" ... """ # Ensure that one or more image files is provided for processing if self._stager is None or not self.image_path_list: raise RuntimeError( 'Please specify one or more images for processing') # Ensure the correct set of operations is provided if not (verify_setup or sign or encrypt or val_image or val_sign or val_encrypt or decrypt): raise RuntimeError( 'Please specify one or more operations to perform.') if verify_setup: logger.note('The inputs provided (config, cmd args) are valid.') return # Start processing images total_images = len(self.image_info_list) progress = ProgressNotifier(total_images, progress_cb, PROGRESS_TOTAL_STAGES) for idx, image in enumerate(self.image_info_list): assert isinstance(image, ImageInfo) logger.info( '------------------------------------------------------') status_string = ('Processing ' + str(idx + 1) + '/' + str(total_images) + ': ' + image.image_under_operation) logger.info(status_string + '\n') # Send a progress notification to the toplevel progress.status = status_string progress.cur = idx progress.cur_stage = 0 try: # Create the required directory structure for this image image_output_dir = image.dest_image.image_dir try: c_path.create_dir(image_output_dir) except Exception as e: raise RuntimeError('Could not create output directory: ' + image_output_dir + '\n' ' ' + 'Error: ' + str(e)) # Enable/Disable debug image.dest_image.debug_enable = self.debug c_path.create_debug_dir(image.dest_image.debug_dir) # Create the encryptor object if encrypt or decrypt or val_encrypt: try: c_path.create_debug_dir( image.dest_image.debug_dir_encdec) encdec = get_encdec(image) except Exception: if not val_encrypt: raise else: encdec = None # Create the parsegen object image.encdec = encdec parsegen = self._status_updater(self._create_parsegen_obj, image.status.parsegen, image) progress.push() # Set the security mechanisms parsegen.sign = parsegen.is_signed() or sign parsegen.encrypt = parsegen.is_encrypted() or encrypt # If encrypt: if encrypt: parsegen.encryption_params = encdec.get_encryption_parameters_blob( ) # Dump any debug data self.dump_parsegen_debug_data(image, parsegen) # Sign the image if sign: self._status_updater(self._sign_image, image.status.sign, image, parsegen) progress.push() # Package and generate the output file if sign or encrypt: store_data_to_file(image.dest_image.image_path, parsegen.get_data()) if encrypt: image.status.encrypt.state = StatusInfo.SUCCESS logger.info(('Signed ' if sign else '') + ('& ' if sign and encrypt else '') + ('Encrypted ' if encrypt else '') + 'image is stored at ' + image.dest_image.image_path) image.image_under_operation = image.dest_image.image_path # Do any post processing self._status_updater( self._post_process, image.status.postprocess, image, image.config.post_process.pil_splitter, getattr(self._stager, '_meta_build_path', None)) progress.push() # Print the image data logger.info('\n' + str(parsegen)) # Decrypt the image if decrypt: store_data_to_file(image.dest_image.decrypted_file, parsegen.get_data(encrypt=False)) # Validate parsegen if val_image: self._validate_parsegen(image, parsegen) progress.push() # Validate sign if val_sign: self._validate_sign(image, parsegen) progress.push() # Validate encrypt if val_encrypt: self._validate_encrypt(image, parsegen) progress.push() # Set overall processing to true image.status.overall.state = StatusInfo.SUCCESS except Exception: logger.debug(traceback.format_exc()) logger.error(sys.exc_info()[1]) logger.info( '------------------------------------------------------\n') progress.complete()
def _generate_new_blob(self, config, debug_dir, encrypted_segments_indices=None): is_enc_key_provider = False if self.key_service.using_encrypted_key_provider(): # UIE_key value was set to an encrypted key provider value. ex: "encrypted_qti" or "encrypted_oem" logger.info( "Attempting to retrieve encrypted L2, encrypted L3, and clear L3 keys from encrypted key provider..." ) self.l1_key = None self.l2_key = None # get the encrypted key provider encrypted_key_provider_class = get_encrypted_key_provider( self.key_service.get_encrypted_key_provider_id()) is_enc_key_provider = True if encrypted_key_provider_class.is_qti(): sa = config.signing_attributes encrypted_key_provider = encrypted_key_provider_class( sa.UIE_capability, sa.UIE_server_url, sa.UIE_server_cert_path) else: encrypted_key_provider = encrypted_key_provider_class() # get the encrypted keys and clear l3 key from the encrypted key provider self.encrypted_l2 = encrypted_key_provider.get_encrypted_l2_key() self.encrypted_l3 = encrypted_key_provider.get_encrypted_l3_key() self.l3_key = encrypted_key_provider.get_clear_l3_key() logger.info( "Encrypted L2, encrypted L3, and clear L3 keys were successfully retrieved from encrypted key provider." ) logger.debug("Encrypted L2 Key: \n" + hexdump(self.encrypted_l2)) logger.debug("Encrypted L3 Key: \n" + hexdump(self.encrypted_l3)) elif self.key_service.get_l1_key( ) is not None and self.key_service.get_l2_key( ) is None and self.key_service.get_l3_key( ) is None and self.key_service.no_enc_keys_provided(): # only l1 key is provided locally. l2 and l3 keys will be set to randomly generated values logger.debug( "Clear L1 key was provided locally but clear L2 and clear L3 keys were not. Generating random values for clear L2 and clear L3 keys..." ) self.l1_key = self.key_service.get_l1_key() self.l2_key = KeyService.get_new_random_clear_key() self.l3_key = KeyService.get_new_random_clear_key() logger.debug("L1 Key: \n" + hexdump(self.l1_key)) logger.debug("L2 Key: \n" + hexdump(self.l2_key)) logger.debug("L3 Key: \n" + hexdump(self.l3_key)) self.encrypted_l2 = None self.encrypted_l3 = None elif self.key_service.all_clear_keys_provided( ) and self.key_service.no_enc_keys_provided(): # all 3 clear keys are provided locally logger.debug( "Clear L1 key, clear L2 key, and clear L3 keys were provided locally." ) self.l1_key = self.key_service.get_l1_key() self.l2_key = self.key_service.get_l2_key() self.l3_key = self.key_service.get_l3_key() logger.debug("L1 Key: \n" + hexdump(self.l1_key)) logger.debug("L2 Key: \n" + hexdump(self.l2_key)) logger.debug("L3 Key: \n" + hexdump(self.l3_key)) self.encrypted_l2 = None self.encrypted_l3 = None elif self.key_service.all_enc_keys_provided( ) and self.key_service.get_l3_key( ) is not None and self.key_service.get_l1_key( ) is None and self.key_service.get_l2_key() is None: # encrypted l2, encrypted l3, and clear l3 are provided locally logger.debug( "Encrypted L2 key, encrypted L3 key, and clear L3 keys were provided locally." ) self.l1_key = None self.l2_key = None self.l3_key = self.key_service.get_l3_key() self.encrypted_l2 = self.key_service.get_encrypted_l2_key() self.encrypted_l3 = self.key_service.get_encrypted_l3_key() logger.debug("Encrypted L2 Key: \n" + hexdump(self.encrypted_l2)) logger.debug("Encrypted L3 Key: \n" + hexdump(self.encrypted_l3)) logger.debug("L3 Key: \n" + hexdump(self.l3_key)) else: raise EncryptionParameters_1_0_L2_1_0.InvalidKeyComboException( "The found key configuration is not allowed.\n \ Supported configurations: \n \ #1 clear L1 key \n \ #2 clear L1, L2, and L3 key \n \ #3 encrypted L2, encrypted L3, and clear L3 key \n \ #4 specify an encrypted key provider.\n \ If required files are provided, ensure that the corresponding config file \n \ contains the correct METACONFIG tags and values.") encryption_params_hdr = EncryptionParamsInfoHdr_1_0() encryption_params_hdr.add_encryption_param_section() eps_hdr = EncryptionParamsSectionHdr_1_0( root_key_type=config.signing_attributes.UIE_root_key_type) eps_body = self._get_encryption_params_section_body_class()( self.image_id, l1_key=self.l1_key, l2_key=self.l2_key, l3_key=self.l3_key, enc_l2_key=self.encrypted_l2, enc_l3_key=self.encrypted_l3, is_enc_key_provider=is_enc_key_provider, debug_dir=debug_dir, encrypted_segments_indices=encrypted_segments_indices) self.l3_image_iv = eps_body.get_image_iv() self.encryption_params_blob = encryption_params_hdr.get_header_blob() + \ eps_hdr.get_header_blob() + \ eps_body.get_binary_blob() logger.debug("Encryption Params: \n" + hexdump(self.encryption_params_blob)) return self.encryption_params_blob, self.l1_key
def _print_attestation_cert_props(self, attestation_cert, parsegen=None): # Print certificate properties (to make tests pass and give good debug information) if (hasattr(parsegen, "get_hash_segment_metadata") and parsegen.get_hash_segment_metadata() is None): logger.info('\nAttestation Certificate Properties:\n' + str(Certificate(attestation_cert)))
def generate(self): """Generate the secdat file based on the configs which have been setup. :param str secdat: the path to the secdat file to be generated. """ retval_gen, reterr_gen = self._verify_generate() if not retval_gen: raise RuntimeError(reterr_gen) # Get the version from config file ucp = self._config_parser ucp_file_version = ucp.get_secdat_file_version() ucp_fuse_version = ucp.get_secdat_fuse_version() ucp_file_info = ucp.get_secdat_file_info() version_dir = self.get_version_dir(ucp_file_version) #-------------------------------------------------------------------------------------------------------- # Setting input_secdat path: # @ if input given as -s # @ if sec.dat exists in the keyprovision_output #-------------------------------------------------------------------------------------------------------- in_secdat = None # Checking self secdat if in_secdat is None: try: in_secdat = self.secdat except Exception: pass # Checking common secdat if in_secdat is None: common_secdat = c_path.join(self.output_dir, defines.COMMON_DIR, version_dir, defines.SEC_DAT) if os.path.isfile(common_secdat): in_secdat = common_secdat # Create list of output secdat out_secdats = [] IO = namedtuple('IO', 'in_data out_path') out_secdats.append( IO( None, c_path.join(self.output_dir, self.FEATURE_DIR, version_dir, defines.SEC_DAT))) out_secdats.append( IO( load_data_from_file(in_secdat) if in_secdat else None, c_path.join(self.output_dir, defines.COMMON_DIR, version_dir, defines.SEC_DAT))) # Generate the secdats: for secdat in out_secdats: out_dir = os.path.dirname(secdat.out_path) c_path.create_dir(out_dir) secdat_obj = secdat_pg(self.SECDAT_SEGMENT_TYPE, secdat.in_data) secdat_obj.data_model = self.data_model secdat_obj.write(secdat.out_path, ucp_file_version, ucp_fuse_version, ucp_file_info) dump_debug_data_model(self.data_model, out_dir, self.debug, self.TOOL_NAME) dump_debug_secdat(secdat_obj, out_dir, self.debug) logger.info('Secdat generated at: ' + secdat.out_path) self.secdat = c_path.join(self.output_dir, self.FEATURE_DIR, version_dir, defines.SEC_DAT)
def _print_attestation_cert_props(self, attestation_cert, parsegen=None): logger.info('\nAttestation Certificate Properties:\n' + str(CertificateBase(attestation_cert)))
def _sign(self, hash_to_sign, cert_config, signing_attributes, general_properties, binary_to_sign): openssl_config_file_paths = self.config.signing.signer_attributes.local_signer_attributes.openssl_config_inputs self._validate_config(cert_config, general_properties, openssl_config_file_paths) # Obtain all the information from the signing_attributes if signing_attributes.debug is not None: debug_val = int(signing_attributes.debug, 16) else: debug_val = None msm_part = int(signing_attributes.msm_part, 16) oem_id = int(signing_attributes.oem_id, 16) model_id = int(signing_attributes.model_id, 16) num_certs_in_certchain = general_properties.num_certs_in_certchain app_id = int(signing_attributes.app_id, 16) if signing_attributes.app_id is not None else None crash_dump = int(signing_attributes.crash_dump, 16) if signing_attributes.crash_dump is not None else None # Create the crypto_params_dict self.certconfig_parser = CertConfigParser(cert_config, signing_attributes, general_properties) crypto_params_dict = self.certconfig_parser.get_crypto_params() hmac_params = signerutils.get_hmac_params_from_config(signing_attributes) # Create the attestation_certificate_key_pair attestation_certificate_key_pair = None root_certificate_params = crypto_params_dict['root_certificate_properties'] root_certificate_params_is_valid, generate_new_root_certificate = self._validate_certificate_params_dict(root_certificate_params) if root_certificate_params_is_valid: if generate_new_root_certificate: logger.info('Generating new Root certificate and a random key') generated_root_key_pair = crypto_functions.gen_rsa_key_pair(general_properties.key_size, key_exponent=signing_attributes.exponent) root_cert, root_key_pair = crypto_functions.create_root_certficate(root_certificate_params, generated_root_key_pair, 7300, openssl_config_file_paths.openssl_configfile_path, 1) else: logger.info('Using a predefined Root certificate and a predefined key') logger.info('Key Used: '+ root_certificate_params['private_key_path']) logger.info('Certificate Used: '+ root_certificate_params['certificate_path']) root_cert, root_key_pair = self._get_certificate_and_key_pair_from_files(root_certificate_params) else: logger.error("Root certificate params are invalid! Please check config file.") raise RuntimeError("Root certificate params are invalid! Please check config file.") if num_certs_in_certchain > 2: logger.debug("Generating Attestation CA certificate, since certchain size is greater than 2") attestation_ca_certificate_params = crypto_params_dict['attest_ca_certificate_properties'] attestation_ca_params_is_valid, generate_new_attestation_ca = self._validate_certificate_params_dict(attestation_ca_certificate_params) if attestation_ca_params_is_valid: if generate_new_attestation_ca: logger.info('Generating new Attestation CA certificate and a random key') generated_attestation_ca__key_pair = crypto_functions.gen_rsa_key_pair(general_properties.key_size, key_exponent=signing_attributes.exponent) attestation_ca_certificate, attestation_ca_certificate_key_pair = crypto_functions.create_certificate(attestation_ca_certificate_params, generated_attestation_ca__key_pair, root_cert, root_key_pair, days=7300, configfile=openssl_config_file_paths.openssl_configfile_path, serial_num=1, extfile_name=openssl_config_file_paths.ca_certificate_extensions_path) else: logger.info('Using a predefined Attestation CA certificate and a predefined key') logger.info('Key Used: '+ attestation_ca_certificate_params['private_key_path']) logger.info('Certificate Used: '+ attestation_ca_certificate_params['certificate_path']) attestation_ca_certificate, attestation_ca_certificate_key_pair = self._get_certificate_and_key_pair_from_files(attestation_ca_certificate_params) else: logger.error("Attestation CA certificate params are invalid! Please check config file.") raise RuntimeError("Attestation CA certificate params are invalid! Please check config file.") attestation_certificate_params = crypto_params_dict['attest_certificate_properties'] attestation_certificate_params_is_valid, generate_new_attestation_certificate = self._validate_certificate_params_dict(attestation_certificate_params) if attestation_certificate_params_is_valid: if generate_new_attestation_certificate: logger.info('Generating new Attestation certificate and a random key') certificate_ou_sw_id ="01 " + hmac_params.sw_id_str + " SW_ID" certificate_ou_hw_id ="02 " + hmac_params.msm_id_str + " HW_ID" certificate_ou_oem_id ="04 " + "%0.4X" % oem_id + " OEM_ID" certificate_ou_sw_size ="05 " + "%0.8X" % len(binary_to_sign) + " SW_SIZE" certificate_ou_model_id ="06 " + "%0.4X" % model_id + " MODEL_ID" certificate_hash_alg = "07 0001 SHA256" certificate_ou = [ certificate_ou_sw_id, certificate_ou_hw_id, certificate_ou_oem_id, certificate_ou_sw_size, certificate_ou_model_id, certificate_hash_alg ] #Optional attributes if debug_val is not None: certificate_ou_debug_id ="03 " + "%0.16X" % debug_val + " DEBUG" certificate_ou.append(certificate_ou_debug_id) if app_id is not None: certificate_app_id = "08 " + "%0.16X" % app_id + " APP_ID" certificate_ou.append(certificate_app_id) if crash_dump is not None: certificate_crash_dump = "09 " + "%0.16X" % crash_dump + " CRASH_DUMP" certificate_ou.append(certificate_crash_dump) if 'OU' in attestation_certificate_params.keys(): if type(attestation_certificate_params['OU'])==list: for item in attestation_certificate_params['OU']: certificate_ou.append(item) else: certificate_ou.append(attestation_certificate_params['OU']) attestation_certificate_params['OU']=certificate_ou if attestation_certificate_key_pair is None: attestation_certificate_key_pair = crypto_functions.gen_rsa_key_pair(key_exponent=signing_attributes.exponent, key_size_in_bits = general_properties.key_size) if num_certs_in_certchain > 2: #sign the attestation cert with the attestation_ca_cert attestation_certificate, attestation_certificate_key_pair = crypto_functions.create_certificate(attestation_certificate_params, attestation_certificate_key_pair, attestation_ca_certificate, attestation_ca_certificate_key_pair, days=7300, configfile=openssl_config_file_paths.openssl_configfile_path, serial_num=1, extfile_name=openssl_config_file_paths.attestation_certificate_extensions_path) else: #sign the attestation cert with the root cert attestation_certificate, attestation_certificate_key_pair = crypto_functions.create_certificate(attestation_certificate_params, attestation_certificate_key_pair, root_cert, root_key_pair, days=7300, configfile=openssl_config_file_paths.openssl_configfile_path, serial_num=1, extfile_name=openssl_config_file_paths.attestation_certificate_extensions_path) attestation_certificate = crypto_functions.cert_pem_to_der(attestation_certificate) else: #generate_new_attestation_certificate == False logger.info('Using a predefined Attestation certificate and a predefined key') logger.info('Key Used: '+ attestation_certificate_params['private_key_path']) logger.info('Certificate Used: '+ attestation_certificate_params['certificate_path']) attestation_certificate, attestation_certificate_key_pair = self._get_certificate_and_key_pair_from_files(attestation_certificate_params) attestation_certificate = crypto_functions.cert_pem_to_der(attestation_certificate) # Since the get_hmac_params_from_certificate_chain always works with the first cert in the cert chain, # this function will work for a single der certificate as well. hmac_params = crypto_functions.get_hmacparams_from_certificate_chain(attestation_certificate) hasher = Hasher() hash_to_sign=hasher.qcom_hmac(binary_to_sign, hmac_params) signature = crypto_functions.encrypt_with_private_key(hash_to_sign, attestation_certificate_key_pair['private_key']) else: logger.error("Attestation certificate params are invalid! Please check config file.") raise RuntimeError("Attestation certificate params are invalid! Please check config file.") if num_certs_in_certchain > 2: attestation_ca_certificate = crypto_functions.cert_pem_to_der(attestation_ca_certificate) else: attestation_ca_certificate = None root_cert = crypto_functions.cert_pem_to_der(root_cert) root_cert_list = self.certconfig_parser.get_rootcerts() certificate_list = self._get_certificate_list(general_properties.num_root_certs, num_certs_in_certchain, attestation_certificate, attestation_ca_certificate, root_cert, root_cert_list) cert_chain=crypto_functions.create_certificate_chain(certificate_list) signer_output = SignerOutput() signer_output.root_cert = root_cert signer_output.attestation_ca_cert = attestation_ca_certificate signer_output.attestation_cert = attestation_certificate signer_output.signature = signature signer_output.cert_chain = cert_chain signer_output.root_cert_list = root_cert_list signer_output.attestation_key = attestation_certificate_key_pair['private_key'] return signer_output
def create_subject_params_attest(self, in_params): # Set exfile self.certs[self.ATTEST].extfile = self.openssl_info.attest_ca_xts # GET SIGNING ATTRIBUTE DATA num_root_certs = (int(self.signing_attributes.num_root_certs) if self.signing_attributes.num_root_certs is not None else None) debug_val = (int(self.signing_attributes.debug, 16) if self.signing_attributes.debug is not None else None) oem_id = int(self.signing_attributes.oem_id, 16) & 0xFFFF model_id = int(self.signing_attributes.model_id, 16) & 0xFFFF in_use_soc_hw_version = (self.signing_attributes.in_use_soc_hw_version if self.signing_attributes.in_use_soc_hw_version is not None else None) use_serial_number_in_signing = ( self.signing_attributes.use_serial_number_in_signing if self.signing_attributes.use_serial_number_in_signing is not None else None) # Get the binary to sign length if self.data_to_sign_len is None: if self.hash_to_sign is not None: self.data_to_sign_len = len(self.hash_to_sign) else: raise RuntimeError('Length of binary could not be computed') logger.info('Generating new Attestation certificate and a random key') hmac_params = HMAC() hmac_params.init_from_config(self.signing_attributes) certificate_ou_sw_id = '01 ' + '%.16X' % hmac_params.sw_id + ' SW_ID' certificate_ou_hw_id = '02 ' + '%.16X' % hmac_params.msm_id + ' HW_ID' certificate_ou_oem_id = '04 ' + '%0.4X' % oem_id + ' OEM_ID' certificate_ou_sw_size = '05 ' + '%0.8X' % self.data_to_sign_len + ' SW_SIZE' certificate_ou_model_id = '06 ' + '%0.4X' % model_id + ' MODEL_ID' certificate_hash_alg = self.SHA_OU_MAP[ self.signing_attributes.hash_algorithm] certificate_ou = [ certificate_ou_sw_id, certificate_ou_hw_id, certificate_ou_oem_id, certificate_ou_sw_size, certificate_ou_model_id, certificate_hash_alg ] # Optional attributes if debug_val is not None: certificate_ou_debug_id = '03 ' + '%0.16X' % debug_val + ' DEBUG' certificate_ou.append(certificate_ou_debug_id) if in_use_soc_hw_version == 1: certificate_in_use_soc_hw_version = '13 ' + '%0.4X' % in_use_soc_hw_version + ' IN_USE_SOC_HW_VERSION' certificate_ou.append(certificate_in_use_soc_hw_version) if use_serial_number_in_signing == 1: certificate_use_serial_number_in_signing = '14 ' + '%0.4X' % use_serial_number_in_signing +\ ' USE_SERIAL_NUMBER_IN_SIGNING' certificate_ou.append(certificate_use_serial_number_in_signing) # Handle OU property binding params = dict(in_params) if 'OU' in params.keys(): if type(params['OU']) == list: for item in params['OU']: certificate_ou.append(item) else: certificate_ou.append(params['OU']) # Add OU fields params['OU'] = certificate_ou logger.info("Adding OU fields to attest certificate.") return params
def sign_hash(self, hash_to_sign, imageinfo, binary_to_sign=None, debug_dir=None, sha_algo=None, binary_to_sign_len=None): # Check that openssl is available try: crypto_functions.are_available([crypto_functions.MOD_OPENSSL]) except Exception as e: raise RuntimeError('Cannot sign: ' + str(e)) # abstract some of the image information signing_attributes = imageinfo.signing_attributes general_properties = imageinfo.general_properties # GET OPENSSL DATA openssl_configfile = self.openssl_info.openssl_config openssl_attest_ca_xts = self.openssl_info.attest_ca_xts openssl_ca_cert_xts = self.openssl_info.ca_cert_xts # GET SIGNING ATTRIBUTE DATA debug_val = int(signing_attributes.debug, 16) if signing_attributes.debug is not None else None oem_id = int(signing_attributes.oem_id, 16) & 0xFFFF model_id = int(signing_attributes.model_id, 16) & 0xFFFF num_certs_in_certchain = general_properties.num_certs_in_certchain app_id = int(signing_attributes.app_id, 16) if signing_attributes.app_id is not None else None crash_dump = int( signing_attributes.crash_dump, 16) if signing_attributes.crash_dump is not None else None rot_en = int(signing_attributes.rot_en, 16) if signing_attributes.rot_en is not None else None mask_soc_hw_version = int( signing_attributes.mask_soc_hw_version, 16) if signing_attributes.mask_soc_hw_version is not None else None in_use_soc_hw_version = signing_attributes.in_use_soc_hw_version if signing_attributes.in_use_soc_hw_version is not None else None use_serial_number_in_signing = signing_attributes.use_serial_number_in_signing if signing_attributes.use_serial_number_in_signing is not None else None # GET CERTIFICATE INFORMATION cert_dict = {} cert_dict['id'] = imageinfo.cert_config cert_dict['chip'] = self.config.metadata.chipset cert_dict['keysize'] = general_properties.key_size cert_dict['exponent'] = general_properties.exponent cert_dict['mrc_index'] = general_properties.mrc_index # Can't use imageinfo.data_prov_basepath because MockImage can't use it cert_dict['dp_path'] = self.config.data_provisioning.base_path self.cert_data_object = CertData(cert_dict) crypto_params_dict = self.cert_data_object.get_crypto_params() # Create the attestation_certificate_key_pair attestation_certificate_key_pair = None root_certificate_params = crypto_params_dict[ 'root_certificate_properties'] root_certificate_params_is_valid, generate_new_root_certificate = self._validate_certificate_params_dict( root_certificate_params) if root_certificate_params_is_valid: if generate_new_root_certificate: logger.info('Generating new Root certificate and a random key') generated_root_key_pair = crypto_functions.gen_rsa_key_pair( general_properties.key_size, key_exponent=signing_attributes.exponent) root_cert, root_key_pair = crypto_functions.create_root_certficate( root_certificate_params, generated_root_key_pair, 7300, openssl_configfile, 1) else: logger.info( 'Using a predefined Root certificate and a predefined key') logger.info('Key Used: ' + root_certificate_params['private_key_path']) logger.info('Certificate Used: ' + root_certificate_params['certificate_path']) root_cert, root_key_pair = self._get_certificate_and_key_pair_from_files( root_certificate_params) else: logger.error( "Root certificate params are invalid! Please check config file." ) raise RuntimeError( "Root certificate params are invalid! Please check config file." ) if num_certs_in_certchain > 2: logger.debug( "Generating Attestation CA certificate, since certchain size is greater than 2" ) attestation_ca_certificate_params = crypto_params_dict[ 'attest_ca_certificate_properties'] attestation_ca_params_is_valid, generate_new_attestation_ca = self._validate_certificate_params_dict( attestation_ca_certificate_params) if attestation_ca_params_is_valid: if generate_new_attestation_ca: logger.info( 'Generating new Attestation CA certificate and a random key' ) generated_attestation_ca__key_pair = crypto_functions.gen_rsa_key_pair( general_properties.key_size, key_exponent=signing_attributes.exponent) attestation_ca_certificate, attestation_ca_certificate_key_pair = \ crypto_functions.create_certificate(attestation_ca_certificate_params, generated_attestation_ca__key_pair, root_cert, root_key_pair, days=7300, configfile=openssl_configfile, serial_num=1, extfile_name=openssl_ca_cert_xts) else: logger.info( 'Using a predefined Attestation CA certificate and a predefined key' ) logger.info( 'Key Used: ' + attestation_ca_certificate_params['private_key_path']) logger.info( 'Certificate Used: ' + attestation_ca_certificate_params['certificate_path']) attestation_ca_certificate, attestation_ca_certificate_key_pair = self._get_certificate_and_key_pair_from_files( attestation_ca_certificate_params) else: logger.error( "Attestation CA certificate params are invalid! Please check config file." ) raise RuntimeError( "Attestation CA certificate params are invalid! Please check config file." ) attestation_certificate_params = crypto_params_dict[ 'attest_certificate_properties'] attestation_certificate_params_is_valid, generate_new_attestation_certificate = self._validate_certificate_params_dict( attestation_certificate_params) if attestation_certificate_params_is_valid: if generate_new_attestation_certificate: # TCG support if self._is_oid_supported(signing_attributes) is True: if self.validate_oid_from_config( attestation_ca_certificate_params[ 'certificate_path'], signing_attributes) is False: raise ConfigError("{0} min and max are not set correctly in configuration."\ "Signing will not continue.".format(signing_attributes.object_id.name) ) attestation_certificate_extensions_path = self._generate_attestation_certificate_extensions( openssl_attest_ca_xts, signing_attributes.object_id.name, signing_attributes.object_id.min, signing_attributes.object_id.max) else: attestation_certificate_extensions_path = openssl_attest_ca_xts # Get the binary to sign length if binary_to_sign_len is None: if binary_to_sign is not None: binary_to_sign_len = len(binary_to_sign) else: raise RuntimeError( 'Length of binary could not be computed') logger.info( 'Generating new Attestation certificate and a random key') hmac_params = signerutils.get_hmac_params_from_config( signing_attributes) certificate_ou_sw_id = "01 " + hmac_params.sw_id_str + " SW_ID" certificate_ou_hw_id = "02 " + hmac_params.msm_id_str + " HW_ID" certificate_ou_oem_id = "04 " + "%0.4X" % oem_id + " OEM_ID" certificate_ou_sw_size = "05 " + "%0.8X" % binary_to_sign_len + " SW_SIZE" certificate_ou_model_id = "06 " + "%0.4X" % model_id + " MODEL_ID" certificate_hash_alg = SHA1_OU_STRING if sha_algo == 'sha1' else SHA256_OU_STRING certificate_ou = [ certificate_ou_sw_id, certificate_ou_hw_id, certificate_ou_oem_id, certificate_ou_sw_size, certificate_ou_model_id, certificate_hash_alg ] # Optional attributes if debug_val is not None: certificate_ou_debug_id = "03 " + "%0.16X" % debug_val + " DEBUG" certificate_ou.append(certificate_ou_debug_id) if app_id is not None: certificate_app_id = "08 " + "%0.16X" % app_id + " APP_ID" certificate_ou.append(certificate_app_id) if crash_dump is not None: certificate_crash_dump = "09 " + "%0.16X" % crash_dump + " CRASH_DUMP" certificate_ou.append(certificate_crash_dump) if rot_en is not None: certificate_rot_en = "10 " + "%0.16X" % rot_en + " ROT_EN" certificate_ou.append(certificate_rot_en) if mask_soc_hw_version is not None: certificate_mask_soc_hw_version = "12 " + "%0.4X" % mask_soc_hw_version + " MASK_SOC_HW_VERSION" certificate_ou.append(certificate_mask_soc_hw_version) if in_use_soc_hw_version == 1: certificate_in_use_soc_hw_version = "13 " + "%0.4X" % in_use_soc_hw_version + " IN_USE_SOC_HW_VERSION" certificate_ou.append(certificate_in_use_soc_hw_version) if use_serial_number_in_signing is not None: certificate_use_serial_number_in_signing = "14 " + "%0.4X" % use_serial_number_in_signing + " USE_SERIAL_NUMBER_IN_SIGNING" certificate_ou.append( certificate_use_serial_number_in_signing) if 'OU' in attestation_certificate_params.keys(): if type(attestation_certificate_params['OU']) == list: for item in attestation_certificate_params['OU']: certificate_ou.append(item) else: certificate_ou.append( attestation_certificate_params['OU']) attestation_certificate_params['OU'] = certificate_ou if attestation_certificate_key_pair is None: attestation_certificate_key_pair = crypto_functions.gen_rsa_key_pair( key_exponent=signing_attributes.exponent, key_size_in_bits=general_properties.key_size) if num_certs_in_certchain > 2: # sign the attestation cert with the attestation_ca_cert attestation_certificate, attestation_certificate_key_pair = \ crypto_functions.create_certificate(attestation_certificate_params, attestation_certificate_key_pair, attestation_ca_certificate, attestation_ca_certificate_key_pair, days=7300, configfile=openssl_configfile, serial_num=1, extfile_name=attestation_certificate_extensions_path) else: # sign the attestation cert with the root cert attestation_certificate, attestation_certificate_key_pair = \ crypto_functions.create_certificate(attestation_certificate_params, attestation_certificate_key_pair, root_cert, root_key_pair, days=7300, configfile=openssl_configfile, serial_num=1, extfile_name=attestation_certificate_extensions_path) attestation_certificate = crypto_functions.cert_pem_to_der( attestation_certificate) # Clean temp file if self._is_oid_supported(signing_attributes) is True: c_path.clean_file(attestation_certificate_extensions_path) else: # generate_new_attestation_certificate == False logger.info( 'Using a predefined Attestation certificate and a predefined key' ) logger.info('Key Used: ' + attestation_certificate_params['private_key_path']) logger.info('Certificate Used: ' + attestation_certificate_params['certificate_path']) attestation_certificate, attestation_certificate_key_pair = self._get_certificate_and_key_pair_from_files( attestation_certificate_params) attestation_certificate = crypto_functions.cert_pem_to_der( attestation_certificate) # Since the get_hmac_params_from_certificate_chain always works with the first cert in the cert chain, # this function will work for a single der certificate as well. hmac_params = crypto_functions.get_hmacparams_from_certificate_chain( attestation_certificate) hasher = Hasher() hash_to_sign = hasher.qcom_hmac(binary_to_sign, hmac_params, sha_algo) signature = crypto_functions.encrypt_with_private_key( hash_to_sign, attestation_certificate_key_pair['private_key']) else: logger.error( "Attestation certificate params are invalid! Please check config file." ) raise RuntimeError( "Attestation certificate params are invalid! Please check config file." ) if num_certs_in_certchain > 2: attestation_ca_certificate = crypto_functions.cert_pem_to_der( attestation_ca_certificate) else: attestation_ca_certificate = None root_cert = crypto_functions.cert_pem_to_der(root_cert) root_cert_list = self.cert_data_object.get_rootcerts( general_properties.num_root_certs) certificate_list = self._get_certificate_list( general_properties.num_root_certs, num_certs_in_certchain, attestation_certificate, attestation_ca_certificate, root_cert, root_cert_list) cert_chain = crypto_functions.create_certificate_chain( certificate_list) signer_output = SignerOutput() signer_output.root_cert = root_cert signer_output.attestation_ca_cert = attestation_ca_certificate signer_output.attestation_cert = attestation_certificate signer_output.signature = signature signer_output.cert_chain = cert_chain signer_output.root_cert_list = root_cert_list signer_output.root_key = root_key_pair['private_key'] # Make sure the variable is defined try: attestation_ca_certificate_key_pair except Exception: pass else: signer_output.attestation_ca_key = attestation_ca_certificate_key_pair[ 'private_key'] signer_output.attestation_key = attestation_certificate_key_pair[ 'private_key'] return signer_output
def _process_secure_operation(self, image, progress, security_policy_list, i_integrity_check, i_sign, i_encrypt, i_decrypt, idx=0): # Check bounds if len(security_policy_list) == 0: raise RuntimeError('Security policy list must not be empty.') elif len(security_policy_list) <= idx: raise RuntimeError('Security policy list length must be more than index.') # Get the current security policy file_type = security_policy_list[idx].file_type integrity_check = security_policy_list[idx].integrity_check and i_integrity_check sign = security_policy_list[idx].sign and i_sign encrypt = security_policy_list[idx].encrypt and i_encrypt decrypt = security_policy_list[idx].encrypt and i_decrypt # Create the encryptor object encdec = None if encrypt or decrypt: c_path.create_debug_dir(image.dest_image.debug_dir_encdec) encdec = get_encdec(image) # Create the parsegen object file_type_backup = image.image_type.file_type encdec_backup = image.encdec image.image_type.file_type = file_type image.encdec = encdec try: parsegen = self._status_updater(self._create_parsegen_obj, image.status.parsegen, progress, True, image) finally: image.image_type.file_type = file_type_backup image.encdec = encdec_backup # Do not allow signed unencrypted elf images to be encrypted as the # Sign will not longer match the encrypted image's tosign if parsegen.file_type() == 'elf' and parsegen.is_signed() and not sign and not parsegen.is_encrypted() and encrypt: raise RuntimeError('Cannot encrypt a signed unencrypted image without resigning ' 'as the sign no longer matches the format change.') # Set the security mechanisms parsegen.integrity_check = security_policy_list[idx].integrity_check and (parsegen.contains_integrity_check() or integrity_check) parsegen.sign = security_policy_list[idx].sign and (parsegen.is_signed() or sign) parsegen.encrypt = security_policy_list[idx].encrypt and (False if decrypt else (parsegen.is_encrypted() or encrypt)) # If encrypt: if encrypt: parsegen.encryption_params = encdec.get_encryption_parameters_blob() # Dump any debug data self.dump_parsegen_debug_data(image, parsegen) # If the security policy list contains more formats, call them if idx < len(security_policy_list) - 1: data = parsegen.get_wrapped_data() import tempfile tmp_fd = tempfile.NamedTemporaryFile(delete=False) tmp_fd.close() store_data_to_file(tmp_fd.name, data) # Backup the source path here src_image_dir_base = image.src_image.image_dir_base src_image_dir_ext = image.src_image.image_dir_ext src_image_name = image.src_image.image_name image.src_image.image_dir_base = os.path.dirname(tmp_fd.name) image.src_image.image_dir_ext = '' image.src_image.image_name = os.path.basename(tmp_fd.name) try: data = self._process_secure_operation(image, progress, security_policy_list, i_integrity_check, i_sign, i_encrypt, i_decrypt, idx + 1) finally: image.src_image.image_dir_base = src_image_dir_base image.src_image.image_dir_ext = src_image_dir_ext image.src_image.image_name = src_image_name os.remove(tmp_fd.name) parsegen.set_wrapped_data(data) # Sign the image if sign: self._status_updater(self._sign_image, image.status.sign, progress, True, image, parsegen) # Package and generate the output image file data = parsegen.get_data() if integrity_check: image.status.integrity_check.state = StatusInfo.SUCCESS if encrypt: image.status.encrypt.state = StatusInfo.SUCCESS if idx != 0: return data if decrypt: ecryption_params_backup = parsegen.encryption_params parsegen.encryption_params = '' try: store_data_to_file(image.dest_image.decrypted_file, parsegen.get_data()) finally: parsegen.encryption_params = ecryption_params_backup else: store_data_to_file(image.dest_image.image_path, data) logger.info(('Signed ' if sign else '') + ('& ' if sign and encrypt else '') + ('Encrypted ' if encrypt else '') + 'image is stored at ' + image.dest_image.image_path) image.image_under_operation = image.dest_image.image_path # Do any post processing self._status_updater(self._post_process, image.status.postprocess, progress, True, image, image.config.post_process.pil_splitter, getattr(self._stager, '_meta_build_path', None)) return parsegen
def main(args, return_isc=False): """Parses the command line arguments, performs any basic operations based on the parsed arguments and starts processing using the isc module. """ # Log to file flids = logger.log_to_file(SECIMAGE_TOOL_NAME, args.output_dir) try: # Print the tool's launch command logged_args = CoreOptionParser.mask_private_args( sys.argv, args._c_spec_override_prefix) logger.info('\n\n SecImage v' + SECIMAGE_TOOL_VERSION + ' launched as: "' + ' '.join(logged_args) + '"\n') # Initialize SecImageCore # When args.serial_numbers is ALL, disable all serial-binding. isc = SecImageCore(debug=args.debug, verbatim_config=args.verbatim_config, disable_serial_binding=args.serial_numbers == DISABLE_SERIAL_BINDING, platform_binding=args.platform_binding) # Configure image signer if args.image_file or ( args.meta_build and not SecImageCore.meta_supports_sign_id(args.meta_build)): if args.chipset: isc.set_chipset(args.chipset, args._c_overrides, args._c_spec_overrides) elif args.config_path: isc.set_config_path(args.config_path, args._c_overrides, args._c_spec_overrides) if args.qti_signing: isc.authority = AUTHORITY_QTI # Set the input if args.image_file: isc.set_image_path(args.image_file, args.sign_id, args.m_gen, args.m_image_file) elif args.meta_build: isc.set_meta_build_path( args.meta_build, [] if args.sign_id is None else [args.sign_id], args.m_gen) # Set the output if args.mini_build: isc.mini_build_path = args.mini_build elif args.output_dir: isc.output_dir = args.output_dir # Process the images isc.process(verify_setup=args.verify_inputs, sign_attr=args.sign_attr, integrity_check=args.integrity_check, sign=args.sign, encrypt=args.encrypt, decrypt=args.decrypt, no_op=args.no_op, val_image=args.validate, val_integrity_check=args.validate, val_sign=args.validate, val_encrypt=args.validate, m_sign_attr=args.m_sign_attr, m_integrity_check=args.m_integrity_check, m_sign=args.m_sign, m_encrypt=args.m_encrypt, m_decrypt=args.m_decrypt, m_val_image=args.m_validate, m_val_integrity_check=args.m_validate, m_val_sign=args.m_validate, m_val_encrypt=args.m_validate, gen_multi_image=args.m_gen, root_cert_hash=args.rch, enforce_signed=args.enforce_signed, enforce_encrypted=args.enforce_encrypted) # Print the summary print_summary(args, isc.image_info_list, isc.multi_image_imageinfo_dict.values()) overall_status = [ image.status.overall.state == StatusInfo.SUCCESS for image in isc.image_info_list ] multi_image_status = [ m.status.overall.state == StatusInfo.SUCCESS for m in isc.multi_image_imageinfo_dict.values() ] return_code = RETURN_CODE_SUCCESS if all(overall_status + multi_image_status) else\ RETURN_CODE_FAILURE if return_isc: return return_code, isc return return_code, isc.image_info_list finally: # Clear all log handlers logger.removeFileLogger(flids)
def _generate_signing_package(self, hash_to_sign, signing_attributes, cass_signer_attributes, image_path, signingpackage_fname, binary_to_sign): signingpackage = SigningPackage(secimage.__version__) signingrequest = signingpackage.createSigningRequest( "image_to_sign=%s" % image_path) hexbindigest = binascii.b2a_hex(hash_to_sign) logger.debug("Digest to sign (hexbinary)= [%s]" % hexbindigest) signingrequest.setDigest(hexbindigest) signingrequest.setCapability(signing_attributes.cass_capability) sw_size = len(hash_to_sign) if binary_to_sign is None else len( binary_to_sign) signingrequest.setSigningAttribute(Certificate.SIGNATTR_SW_SIZE, "0x%.8X" % sw_size) hmac_params = signerutils.get_hmac_params_from_config( signing_attributes) signingrequest.setSigningAttribute(Certificate.SIGNATTR_HW_ID, "0x%s" % hmac_params.msm_id_str) signingrequest.setSigningAttribute(Certificate.SIGNATTR_SW_ID, signing_attributes.sw_id) signingrequest.setSigningAttribute(Certificate.SIGNATTR_MODEL_ID, signing_attributes.model_id) signingrequest.setSigningAttribute(Certificate.SIGNATTR_OEM_ID, signing_attributes.oem_id) if signing_attributes.debug: signingrequest.setSigningAttribute(Certificate.SIGNATTR_DEBUG, signing_attributes.debug) if signing_attributes.app_id: signingrequest.setSigningAttribute(Certificate.SIGNATTR_APP_ID, signing_attributes.app_id) if signing_attributes.crash_dump: signingrequest.setSigningAttribute(Certificate.SIGNATTR_CRASH_DUMP, signing_attributes.crash_dump) if self._is_oid_supported(signing_attributes) is True: attr_min, attr_max = Certificate.GetOIDAttrName( signing_attributes.object_id.name) # Min/max can be supplied by CASS server and is optional if signing_attributes.object_id.min: signingrequest.setSigningAttribute( attr_min, signing_attributes.object_id.min) if signing_attributes.object_id.max: signingrequest.setSigningAttribute( attr_max, signing_attributes.object_id.max) else: # opendsp does not CASS_SIGNATTR_USE_EXP3 currently if signing_attributes.exponent == 3: signingrequest.setSigningAttribute(self.CASS_SIGNATTR_USE_EXP3, 'TRUE') elif signing_attributes.exponent == 65537: signingrequest.setSigningAttribute(self.CASS_SIGNATTR_USE_EXP3, 'FALSE') else: raise RuntimeError, "Exponent value of {0} is invalid!".format( signing_attributes.exponent) # Set signature algorithm if signing_attributes.hash_algorithm and signing_attributes.hash_algorithm.lower( ) == 'sha1': signingrequest.setSigningAttribute(Certificate.SIGNATTR_SHA256, 'FALSE') elif signing_attributes.hash_algorithm is None or signing_attributes.hash_algorithm.lower( ) == 'sha256': signingrequest.setSigningAttribute(Certificate.SIGNATTR_SHA256, 'TRUE') else: raise RuntimeError, "hash algorithm value of {0} is invalid!".format( signing_attributes.hash_algorithm) pathname, fname = os.path.split(signingpackage_fname) c_path.create_dir(pathname) signingpackage.toxml() signingpackage.saveToFile(signingpackage_fname) logger.info("Signing package created.") logger.info("Signing package digest from Signing Package = [%s]" % signingpackage.getDigest()) return signingpackage
def _process_secure_operation(self, image, progress, security_policy_list, i_integrity_check, i_sign, i_encrypt, i_decrypt, idx=0): # Check bounds if len(security_policy_list) == 0: raise RuntimeError('Security policy list must not be empty.') elif len(security_policy_list) <= idx: raise RuntimeError('Security policy list length must be more than index.') # Get the current security policy file_type = security_policy_list[idx].file_type integrity_check = security_policy_list[idx].integrity_check and i_integrity_check sign = security_policy_list[idx].sign and i_sign encrypt = security_policy_list[idx].encrypt and i_encrypt decrypt = security_policy_list[idx].encrypt and i_decrypt # Create the encryptor object encdec = None if encrypt or decrypt: c_path.create_debug_dir(image.dest_image.debug_dir_encdec) encdec = get_encdec(image) # Create the parsegen object file_type_backup = image.image_type.file_type encdec_backup = image.encdec image.image_type.file_type = file_type image.encdec = encdec try: parsegen = self._status_updater(self._create_parsegen_obj, image.status.parsegen, progress, True, image) finally: image.image_type.file_type = file_type_backup image.encdec = encdec_backup # Do not allow signed unencrypted elf images to be encrypted as the # Sign will not longer match the encrypted image's tosign if parsegen.file_type() == 'elf' and parsegen.is_signed() and not sign and not parsegen.is_encrypted() and encrypt: raise RuntimeError('Cannot encrypt a signed unencrypted image without resigning ' 'as the sign no longer matches the format change.') # Set the security mechanisms parsegen.integrity_check = security_policy_list[idx].integrity_check and (parsegen.contains_integrity_check() or integrity_check) parsegen.sign = security_policy_list[idx].sign and (parsegen.is_signed() or sign) parsegen.encrypt = security_policy_list[idx].encrypt and (False if decrypt else (parsegen.is_encrypted() or encrypt)) # If encrypt: if encrypt: parsegen.encryption_params = encdec.get_encryption_parameters_blob() # Dump any debug data self.dump_parsegen_debug_data(image, parsegen) # If the security policy list contains more formats, call them if idx < len(security_policy_list) - 1: data = parsegen.get_wrapped_data() import tempfile tmp_fd = tempfile.NamedTemporaryFile(delete=False) tmp_fd.close() store_data_to_file(tmp_fd.name, data) # Backup the source path here src_image_dir_base = image.src_image.image_dir_base src_image_dir_ext = image.src_image.image_dir_ext src_image_name = image.src_image.image_name image.src_image.image_dir_base = os.path.dirname(tmp_fd.name) image.src_image.image_dir_ext = '' image.src_image.image_name = os.path.basename(tmp_fd.name) try: data = self._process_secure_operation(image, progress, security_policy_list, i_integrity_check, i_sign, i_encrypt, i_decrypt, idx + 1) finally: image.src_image.image_dir_base = src_image_dir_base image.src_image.image_dir_ext = src_image_dir_ext image.src_image.image_name = src_image_name os.remove(tmp_fd.name) parsegen.set_wrapped_data(data) # Sign the image if sign: self._status_updater(self._sign_image, image.status.sign, progress, True, image, parsegen) # Package and generate the output image file data = parsegen.get_data() if integrity_check: image.status.integrity_check.state = StatusInfo.SUCCESS if encrypt: image.status.encrypt.state = StatusInfo.SUCCESS if idx != 0: return data if decrypt: store_data_to_file(image.dest_image.decrypted_file, data) else: store_data_to_file(image.dest_image.image_path, data) logger.info(('Signed ' if sign else '') + ('& ' if sign and encrypt else '') + ('Encrypted ' if encrypt else '') + 'image is stored at ' + image.dest_image.image_path) image.image_under_operation = image.dest_image.image_path # Do any post processing self._status_updater(self._post_process, image.status.postprocess, progress, True, image, image.config.post_process.pil_splitter, getattr(self._stager, '_meta_build_path', None)) return parsegen
def log_once(self, msg): if msg not in self.message_print_set: logger.info(msg) self.message_print_set.add(msg)
def _validate_sign(self, dp_file, rootcerthash=None, sign_id=None): """Validate the given debugpolicy elf file. """ # Initialize SecImageCore isc = SecImageCore(debug=self.debug) isc.config_path = self.secimage_config if self.authority is not None: isc.authority = self.authority # Get the supported sign_id list sign_id_list = isc._img_config_parser.sign_id_list # Validating signed images & signed image(in case of one image) for sign_ids available in sign_id list if sign_id is None: if len(dp_file) > 1: for sign in range(len(dp_file)): logger.info( '\nValidating debugpolicy signed file against ' + sign_id_list[sign] + ' signature..') isc.set_image_path(dp_file[sign], sign_id_list[sign]) isc.output_dir = os.path.dirname(dp_file[sign]) isc.image_info_list[0].dest_image.image_dir_ext = '' # Process the signed elf isc.process(val_sign=True, root_cert_hash=rootcerthash) if os.path.isfile( c_path.join(self.output_dir, 'SecImage_log.txt')): shutil.move( c_path.join(self.output_dir, 'SecImage_log.txt'), c_path.join(self.output_dir, ('val_' + sign_id_list[sign] + '_secimage_log.txt'))) else: for sign in range(len(sign_id_list)): logger.info( '\nValidating debugpolicy signed file against ' + sign_id_list[sign] + ' signature..') isc.set_image_path(dp_file[0], sign_id_list[sign]) isc.output_dir = os.path.dirname(dp_file[0]) isc.image_info_list[0].dest_image.image_dir_ext = '' # Process the signed elf isc.process(val_sign=True, root_cert_hash=rootcerthash) if os.path.isfile( c_path.join(self.output_dir, 'SecImage_log.txt')): shutil.move( c_path.join(self.output_dir, 'SecImage_log.txt'), c_path.join(self.output_dir, ('val_' + sign_id_list[sign] + '_secimage_log.txt'))) # Validating signed image for given sign_id else: if sign_id not in sign_id_list: raise RuntimeError('Received sign_id "' + sign_id + '" as input.' + '\n' " Supported sign_id's are: " + str(sign_id_list)) logger.info('\nValidating debugpolicy signed file against ' + sign_id + ' signature..') isc.set_image_path(dp_file[0], sign_id) isc.output_dir = os.path.dirname(dp_file[0]) isc.image_info_list[0].dest_image.image_dir_ext = '' # Process the signed elf isc.process(val_sign=True, root_cert_hash=rootcerthash) if os.path.isfile(c_path.join(self.output_dir, 'SecImage_log.txt')): shutil.move( c_path.join(self.output_dir, 'SecImage_log.txt'), c_path.join(self.output_dir, ('val_' + sign_id + '_secimage_log.txt')))
def _validate_encrypt(self, image, parsegen): if parsegen.is_encrypted(): logger.info('Image ' + image.image_under_operation + ' is encrypted') else: raise RuntimeError('Image ' + image.image_under_operation + ' is not encrypted')
def workspace(self, workspace_path): workspace_path = c_path.normalize(workspace_path) self._workspace_dir_obj = self.CONFIG_MODULE.WorkspaceDir( workspace_path) logger.info('Workspace is set to: ' + workspace_path)
def process(self): if self.args.disclaimer: self.disclaimer_approval() #disable secimage logging secimage.log_to_file = lambda x: x logger.info( "Signing a file may take up to 3 minutes due to network connectivity. Please wait patiently." ) retValue = True if self.args.input_dir: input_files_list = c_path.find_files(self.args.input_dir, self.FILE_FILTER, combine=False) if input_files_list == []: logger.info( "No files to be signed in the input directory: {0}".format( self.args.input_dir)) retValue = False failure_list = [] for index, input_file in enumerate(input_files_list): input_file_path = c_path.join(self.args.input_dir, input_file) logger.info(OUTPUT_DELIMINATOR) logger.info("Processing {0}/{1}: {2}".format( (index + 1), len(input_files_list), input_file_path)) ret = self.process_file(input_file_path) if ret is False: failure_list.append(index) retValue = retValue and ret num_success = len(input_files_list) - len(failure_list) logger.info(OUTPUT_DELIMINATOR) logger.info("{0}/{1} succeeded.".format(num_success, len(input_files_list))) if len(failure_list) > 0: logger.info("Failures:") for index in failure_list: logger.info("{0}.{1}".format( index + 1, c_path.join(self.args.input_dir, input_files_list[index]))) else: logger.info(OUTPUT_DELIMINATOR) retValue = self.process_file() return retValue
def _validate_generation(self, dp_file): """Validate the generation """ reterr = [] # Set the debug params if self.debug: debug_dir = c_path.join(self.output_dir, defines.DEST_DEBUG_DIR) debug_prefix, debug_suffix = os.path.splitext( os.path.basename(c_path.join(self.output_dir, 'dp.dat'))) else: debug_dir, debug_prefix, debug_suffix = None, None, None dbgpelfparser = ParseGenDbgpElf( data=load_data_from_file(dp_file), version=self._config_parser.root.file_properties.revision, debug_dir=debug_dir, debug_prefix=debug_prefix, debug_suffix=debug_suffix, elf_class=None) # Validate against the debugpolicy config file if self._config_parser: if dbgpelfparser.dbgpparser.header.version != self._config_parser.root.file_properties.revision: reterr.append( 'Revision mismatch ' '' + 'Debugpolicy File: ' + str(dbgpelfparser.dbgpparser.header.version) + '' + ' Config File: ' + str(self._config_parser.root.file_properties.revision)) logger.error(reterr) return if getattr(dbgpelfparser.dbgpparser.header, 'sernum_start', None) is not None and \ dbgpelfparser.dbgpparser.header.sernum_start != self._config_parser.root.file_properties.serial_number_start: reterr.append( 'Serial Number Start mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header.sernum_start) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. serial_number_start)) if getattr(dbgpelfparser.dbgpparser.header, 'sernum_end', None) is not None and \ dbgpelfparser.dbgpparser.header.sernum_end != self._config_parser.root.file_properties.serial_number_end: reterr.append('Serial Number End mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header.sernum_end) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. serial_number_end)) if dbgpelfparser.dbgpparser.header.flags != self._config_parser.root.file_properties.flags: reterr.append( 'Flags mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header.flags) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties.flags)) if self._config_parser.root.file_properties.image_bit_map is not None: if dbgpelfparser.dbgpparser.header.imagebit_map != self._config_parser.root.file_properties.image_bit_map: reterr.append( 'Image Bit Map mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header.imagebit_map) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. image_bit_map)) if self._config_parser.root.file_properties.image_bit_map is None: if getattr(dbgpelfparser.dbgpparser.header, 'imagebit_map', None) is not None: if dbgpelfparser.dbgpparser.header.imagebit_map != 0: if dbgpelfparser.dbgpparser.header.imagebit_map != self._config_parser.root.file_properties.image_bit_map: reterr.append('Image Bit Map mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header. imagebit_map) + '' + '\nConfig File: ' + str(self._config_parser.root. file_properties.image_bit_map)) if self._config_parser.root.file_properties.image_id_list is not None: if len(self._config_parser.root.file_properties.image_id_list. image_id) == 0: for i in range( len( list(dbgpelfparser.dbgpparser.header. imgid_array))): if list(dbgpelfparser.dbgpparser.header.imgid_array )[i] != 0: reterr.append( 'Image ID Array mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header.imgid_array ) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. image_id_list.image_id + list([0] * (32 - len(self._config_parser.root. file_properties. image_id_list.image_id))))) break else: for i in range( len(self._config_parser.root.file_properties. image_id_list.image_id)): if list( dbgpelfparser.dbgpparser.header.imgid_array )[i] != self._config_parser.root.file_properties.image_id_list.image_id[ i]: reterr.append( 'Image ID Array mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header.imgid_array ) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. image_id_list.image_id + list([0] * (32 - len(self._config_parser.root. file_properties. image_id_list.image_id))))) break if self._config_parser.root.file_properties.image_id_list is None: if getattr(dbgpelfparser.dbgpparser.header, 'imgid_count', None) is not None: if dbgpelfparser.dbgpparser.header.imgid_count != 0: reterr.append( 'Image ID Array mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header.imgid_array) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. image_id_list)) if dbgpelfparser.dbgpparser.header.rootcerthash_array[:dbgpelfparser.dbgpparser.header.rootcerthash_count] != \ [x.lower() for x in self._config_parser.root.file_properties.root_cert_hash_list.root_cert_hash]: reterr.append( 'Root Certificate Hash Array mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header.rootcerthash_array) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. root_cert_hash_list.root_cert_hash)) if getattr(dbgpelfparser.dbgpparser.header, 'serial_num_array', None) is not None: if len(self._config_parser.root.file_properties. serial_num_list.serial_num) == 0: reterr.append( 'Serial Number Array mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header.serial_num_array) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. serial_num_list.serial_num + list([0] * (200 - len(self._config_parser.root.file_properties. serial_num_list.serial_num))))) else: for i in range( len(self._config_parser.root.file_properties. serial_num_list.serial_num)): if list( dbgpelfparser.dbgpparser.header. serial_num_array )[i] != self._config_parser.root.file_properties.serial_num_list.serial_num[ i]: reterr.append( 'Serial Number Array mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header. serial_num_array) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. serial_num_list.serial_num + list([0] * (200 - len(self._config_parser.root. file_properties.serial_num_list. serial_num))))) break if self._config_parser.root.file_properties.root_cert_hash_qti_list is not None: if len(self._config_parser.root.file_properties. root_cert_hash_qti_list.root_cert_hash_qti) == 0: for i in range( len( list(dbgpelfparser.dbgpparser.header. rootcerthash_qti_array))): if list(dbgpelfparser.dbgpparser.header. rootcerthash_qti_array)[i] != 0: reterr.append( 'Root Certificate Hash QTI Array mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header. rootcerthash_qti_array) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. root_cert_hash_qti_list.root_cert_hash_qti + list([0] * (4 - len( self._config_parser.root. file_properties.root_cert_hash_qti_list .root_cert_hash_qti))))) break else: for i in range( len(self._config_parser.root.file_properties. root_cert_hash_qti_list.root_cert_hash_qti)): if list( dbgpelfparser.dbgpparser.header. rootcerthash_qti_array )[i].lower( ) != self._config_parser.root.file_properties.root_cert_hash_qti_list.root_cert_hash_qti[ i].lower(): reterr.append( 'Root Certificate Hash QTI Array mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header. rootcerthash_qti_array) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. root_cert_hash_qti_list.root_cert_hash_qti + list([0] * (4 - len( self._config_parser.root. file_properties.root_cert_hash_qti_list .root_cert_hash_qti))))) break if self._config_parser.root.file_properties.root_cert_hash_qti_list is None: if getattr(dbgpelfparser.dbgpparser.header, 'rootcerthash_qti_count', None) is not None: if dbgpelfparser.dbgpparser.header.rootcerthash_qti_count != 0: reterr.append( 'Root Certificate Hash QTI Array mismatch ' '' + ':- \nDebugpolicy File: ' + str(dbgpelfparser.dbgpparser.header. rootcerthash_qti_array) + '' + '\nConfig File: ' + str(self._config_parser.root.file_properties. root_cert_hash_qti_list)) if reterr: if len(reterr) > 1: reterr = [(' ' + str(idx + 1) + '. ' + error) for idx, error in enumerate(reterr)] reterr = 'Following errors were found during validation:\n\n' + '\n'.join( reterr) else: reterr = reterr[0] logger.error(reterr) else: logger.info( 'Validation of debugpolicy file against debugpolicy config file is Successful!' )
def _execute_sign(self): # don't execute sectools, install, or pilsplit if no policy is provided if self.input.build_policy is None: return # create list containing command arguments to execute Sectools cmds = [ "python", c_path.join(SECTOOLS_DIR, "sectools.py"), "secimage", "-i", self.input.source, "-g", self.input.sign_id, "-c", self.input.config ] if self.input.app_id: cmds += ["--cfg_app_id", self.input.app_id] if self.input.jtag_id: cmds += ["--cfg_msm_part", self.input.jtag_id] if self.input.soc_hw_version: cmds += ["--cfg_soc_hw_version", self.input.soc_hw_version] cmds += ["--cfg_in_use_soc_hw_version", "1"] if self.input.soc_vers: cmds += ["--cfg_soc_vers", self.input.soc_vers] if self.input.signer: cmds += ["--cfg_selected_signer", self.input.signer] if self.input.qti_sign: cmds += ["--qti_signing"] if self.input.uie_qti: cmds += ["--cfg_UIE_capability", self.input.uie_qti] cmds += ["--cfg_UIE_key", "UIE_QTI"] if self.input.hash_table_algo: cmds += [ "--cfg_segment_hash_algorithm", self.input.hash_table_algo ] if self.input.signature_digest_algo: cmds += ["--cfg_hash_algorithm", self.input.signature_digest_algo] if self.input.num_root_certs: cmds += ["--cfg_num_root_certs", self.input.num_root_certs] if self.input.max_num_root_certs: cmds += ["--cfg_max_num_root_certs", self.input.max_num_root_certs] if self.input.selected_cert_config: cmds += [ "--cfg_selected_cert_config", self.input.selected_cert_config ] if self.input.client_id: cmds += ["--cfg_client_id", self.input.client_id] if self.input.lib_id: cmds += ["--cfg_lib_id", self.input.lib_id] if self.input.image_entry: cmds += ["--cfg_image_entry", self.input.image_entry] # maintain verbosity level across sectools if logger.verbosity == logger.WARN: cmds += ["-z"] elif logger.verbosity == logger.ERROR: cmds += ["-zz"] elif logger.verbosity == logger.DEBUG: cmds += ["-v"] # execute Sectools for each sec_image_policy for policy in self.input.build_policy.sec_image_policies: _cmds = copy.deepcopy(cmds) _cmds += [policy.cmd_options] # set output directory based on policy target_base_dir = c_path.join(self.input.target_base_dir, policy.id) _cmds += ["-o", target_base_dir] try: logger.debug("\nExecuting Sectools...") # output Sectools's output as it is being generated process = subprocess.Popen(_cmds, stdout=subprocess.PIPE) for line in iter(process.stdout.readline, ''): logger.info(line.rstrip()) except Exception, e: logger.error("Sectools failed!") if is_python_27(): logger.debug("Python version 2.7 is supported.") else: logger.debug("Python version 2.7 is not supported.") logger.error(e.message) raise RuntimeError(e.message) # install and pilsplit sectools's output file self._execute_install(policy)
def initialize(self, imageinfo, **kwargs): """ This is the first method to be called in our sign() method. You can set all of the self._cert data here if you have all of the keypairs and the certificates already available If the following variables are all set, than the below methods will never be called, and you simply need to override this one method self.certs[self.ROOT].cert self.certs[self.CA].cert self.certs[self.ATTEST].cert self.signature :return None """ # Call the Base Signer v2 to call DataProv LocalV2Signer.initialize(self, imageinfo, **kwargs) data_to_hash = StructDynamic( self.data_to_sign if self.data_to_sign else self.hash_to_sign, self.data_to_sign_format) # Call the HSM signer method try: # Call HSM signer API which provides the format of the data to sign if it is implemented root_cert, ca_cert, attest_cert, signature = \ self.sign_req_data(self.signing_attributes, self.create_subject_params(self.ATTEST, self.certs[self.ATTEST].params.params), self.hash_to_sign, data_to_hash) except NotImplementedError: # Call legacy HSM signer API root_cert, ca_cert, attest_cert, signature = \ self.sign_req(self.signing_attributes, self.create_subject_params(self.ATTEST, self.certs[self.ATTEST].params.params), self.hash_to_sign) # Make sure the attest and the signature are here if attest_cert is None or signature is None: raise RuntimeError( "Attestation Certificate or Signature are missing from hsm_signer_output" ) # Set our own internal fields and let the signer continue if root_cert is not None: logger.info("HSM Signer provided a root certificate") self.certs[self.ROOT].cert = root_cert if ca_cert is not None and self.CA in self.certs: logger.info("HSM Signer provided a CA certificate") self.certs[self.CA].cert = ca_cert logger.info("HSM Signer provided an attest certificate") self.certs[self.ATTEST].cert = attest_cert logger.info("HSM Signer provided a signature") # Pad signature to size in the header depending on authority since ECDSA signatures can be of variable size parsegen = kwargs.get("parsegen", None) authority = parsegen.authority if parsegen else AUTHORITY_OEM try: padded_length = data_to_hash.sig_size if authority == AUTHORITY_OEM else data_to_hash.sig_size_qti except RuntimeError: padded_length = len(signature) self.signature = signature.ljust(padded_length, PAD_BYTE_0) # Validation for key, value in self.certs.items(): if value.cert is None: raise RuntimeError("Certificate " + key + " is missing from HSM Signer")
def process( self, verify_setup=False, sign_attr=False, integrity_check=False, sign=False, encrypt=False, decrypt=False, val_image=False, val_integrity_check=False, val_sign=False, val_encrypt=False, root_cert_hash=None, progress_cb=PROGRESS_CB_PYPASS, ): """Performs the secure-image related operations specified from the params. :param bool verify_setup: Verify that the configuration of the object is correct and return. This will ignore any other params. :param bool sign_attr: Add signing attributes to hash segment of images. :param bool integrity_check: Add integrity check to the image. :param bool sign: Sign the images. (Re-sign if image is already signed) :param bool encrypt: Encrypt the images. (Re-encrypt if image is already encrypted) :param bool val_image: Validate the integrity of the image against the config file. :param bool val_integrity_check: Validate the integrity check in the image. :param bool val_sign: Validate that the image is signed and validate the integrity of the signing related data. :param bool val_encrypt: Validate that the image is encrypted and validate the integrity of the encryption related data. :param cb progress_cb: Callback method to get a status update during processing. Callback method should have this format: :: def progress_cb(status_string, progress_percent): \""" :param str status_string: the current status. :param int progress_percent: the progress (in percent) \""" ... """ from imageinfo import ImageInfo, StatusInfo from sectools.features.isc.signer.remote import RemoteSignerNote # Ensure that one or more image files is provided for processing if self._stager is None or not self.image_path_list: raise RuntimeError( 'Please specify one or more images for processing') # Ensure the correct set of operations is provided if not (verify_setup or integrity_check or sign or encrypt or decrypt or val_image or val_integrity_check or val_sign or val_encrypt): raise RuntimeError( 'Please specify one or more operations to perform.') # Print the openssl path version = '' path_info = 'is unavailable. Please run "which openssl" and "openssl version" to check openssl version info, and upgrade to required version' try: from sectools.common import crypto version = 'v' + '.'.join( tuple(str(x) for x in crypto.openssl.OPENSSL_VERSION_MIN)) + ' or greater ' path_info = 'is available at: "' + crypto.discovery_factory.get_impl( crypto.modules.MOD_OPENSSL) + '"' except Exception as e: pass logger.info('Openssl ' + version + path_info) if verify_setup: logger.note('The inputs provided (config, cmd args) are valid.') return # Start processing images individual_image_count = len(self.image_info_list) total_image_count = individual_image_count progress = ProgressNotifier(total_image_count, progress_cb, PROGRESS_TOTAL_STAGES) def _process(idx, image, sign_attr, integrity_check, sign, encrypt, decrypt, val_image, val_integrity_check, val_sign, val_encrypt): assert isinstance(image, ImageInfo) logger.info( '------------------------------------------------------') status_string = ('Processing ' + str(idx + 1) + '/' + str(total_image_count) + ': ' + image.image_under_operation) logger.info(status_string + '\n') # Send a progress notification to the toplevel progress.status = status_string progress.cur = idx progress.cur_stage = 0 file_logger_id = None image.authority = self.authority try: # Create the required directory structure for this image image_output_dir = image.dest_image.image_dir try: c_path.create_dir(image_output_dir) except Exception as e: raise RuntimeError('Could not create output directory: ' + image_output_dir + '\n' ' ' + 'Error: ' + str(e)) # Enable/Disable debug image.dest_image.debug_enable = self.debug c_path.create_debug_dir(image.dest_image.debug_dir) # Set the root cert hash image.validation_root_cert_hash = root_cert_hash # Enable file logging to the directory file_logger_id = logger.add_file_logger( c_path.join(image_output_dir, 'SecImage_log.txt'), logger.verbosity) # Create the security policies list for this image security_policy_list = create_security_policy_list(image) # Parsegen object parsegen = None # For secure operations if integrity_check or sign or encrypt or decrypt: parsegen = self._process_secure_operation( image, progress, security_policy_list, sign_attr, integrity_check, sign, encrypt, decrypt) # For validation if val_image or val_integrity_check or val_sign or val_encrypt: # Bypass validation when encrypted key provide is configured as UIE server because decryption will always fail if parsegen is not None and parsegen.is_encrypted( ) and encrypted_key_provider_id_supported( image.general_properties.UIE_key): logger.warning( "Skipping validation because encrypted key provider is configured as UIE server" ) else: parsegen = self._process_validation( image, progress, security_policy_list, val_image, val_integrity_check, val_sign, val_encrypt) # Print the image data if parsegen is not None: logger.info('\n' + str(parsegen)) # Set overall processing to true if not ((val_image and image.status.validate_parsegen.state == StatusInfo.ERROR) or (val_integrity_check and image.status.validate_integrity_check.state == StatusInfo.ERROR) or (val_sign and image.status.validate_sign.state == StatusInfo.ERROR) or (val_encrypt and image.status.validate_encrypt.state == StatusInfo.ERROR)): image.status.overall.state = StatusInfo.SUCCESS except RemoteSignerNote as e: logger.info('NOTE: ' + str(e), color=logger.YELLOW) except Exception: logger.error(traceback.format_exc()) logger.error(sys.exc_info()[1]) finally: if file_logger_id is not None: logger.removeFileLogger(file_logger_id) logger.info( '------------------------------------------------------\n') for idx, image in enumerate(self.image_info_list): _process(idx, image, sign_attr, integrity_check, sign, encrypt, decrypt, val_image, val_integrity_check, val_sign, val_encrypt) progress.complete()
def _process_secure_operation(self, image, progress, security_policy_list, i_integrity_check, i_sign, idx=0, parsegens=None): # Check bounds if len(security_policy_list) == 0: raise RuntimeError('Security policy list must not be empty.') elif len(security_policy_list) <= idx: raise RuntimeError('Security policy list length must be more than index.') # Get the current security policy file_type = security_policy_list[idx].file_type integrity_check = security_policy_list[idx].integrity_check and i_integrity_check sign = security_policy_list[idx].sign and i_sign # Create the parsegen object file_type_backup = image.image_type.file_type image.image_type.file_type = file_type try: parsegen = self._status_updater(self._create_parsegen_obj, image.status.parsegen, progress, True, image, validating=False, signing=sign, parsegens=parsegens) finally: image.image_type.file_type = file_type_backup # Set the security mechanisms parsegen.integrity_check = security_policy_list[idx].integrity_check and (parsegen.contains_integrity_check() or integrity_check) parsegen.sign = security_policy_list[idx].sign and (parsegen.is_signed() or sign) # Dump any debug data self.dump_parsegen_debug_data(image, parsegen) # If the security policy list contains more formats, call them if idx < len(security_policy_list) - 1: data = parsegen.get_wrapped_data() tmp_fd = tempfile.NamedTemporaryFile(delete=False) tmp_fd.close() store_data_to_file(tmp_fd.name, data) # Backup the source path here src_image_dir_base = image.src_image.image_dir_base src_image_dir_ext = image.src_image.image_dir_ext src_image_name = image.src_image.image_name image.src_image.image_dir_base = os.path.dirname(tmp_fd.name) image.src_image.image_dir_ext = '' image.src_image.image_name = os.path.basename(tmp_fd.name) try: data = self._process_secure_operation(image, progress, security_policy_list, i_integrity_check, i_sign, idx=idx + 1) finally: image.src_image.image_dir_base = src_image_dir_base image.src_image.image_dir_ext = src_image_dir_ext image.src_image.image_name = src_image_name os.remove(tmp_fd.name) parsegen.set_wrapped_data(data) # Sign the image if sign: self._status_updater(self._sign_image, image.status.sign, progress, True, image, parsegen) # Package and generate the output image file data = parsegen.get_data() if integrity_check: image.status.integrity_check.state = StatusInfo.SUCCESS if idx != 0: return data store_data_to_file(image.dest_image.image_path, data) logger.info(('Signed ' if sign else '') + 'image is stored at ' + image.dest_image.image_path, color=logger.GREEN) image.image_under_operation = image.dest_image.image_path return parsegen
def logging_state_info(self, msg): logger.info(msg) if self.state: self.state += '\n' + msg else: self.state = '\n' + msg
def _sign(self, hash_to_sign, cert_config, signing_attributes, general_properties, binary_to_sign): openssl_config_file_paths = self.config.signing.signer_attributes.local_signer_attributes.openssl_config_inputs self._validate_config(cert_config, general_properties, openssl_config_file_paths) # Obtain all the information from the signing_attributes debug_val = int(signing_attributes.debug, 16) if signing_attributes.debug is not None else None msm_part = int(signing_attributes.msm_part, 16) oem_id = int(signing_attributes.oem_id, 16) model_id = int(signing_attributes.model_id, 16) num_certs_in_certchain = general_properties.num_certs_in_certchain app_id = int(signing_attributes.app_id, 16) if signing_attributes.app_id is not None else None crash_dump = int(signing_attributes.crash_dump, 16) if signing_attributes.crash_dump is not None else None rot_en = int(signing_attributes.rot_en, 16) if signing_attributes.rot_en is not None else None # Create the crypto_params_dict self.certconfig_parser = CertConfigParser(cert_config, signing_attributes, general_properties) crypto_params_dict = self.certconfig_parser.get_crypto_params() hmac_params = signerutils.get_hmac_params_from_config(signing_attributes) # Create the attestation_certificate_key_pair attestation_certificate_key_pair = None root_certificate_params = crypto_params_dict['root_certificate_properties'] root_certificate_params_is_valid, generate_new_root_certificate = self._validate_certificate_params_dict(root_certificate_params) if root_certificate_params_is_valid: if generate_new_root_certificate: logger.info('Generating new Root certificate and a random key') generated_root_key_pair = crypto_functions.gen_rsa_key_pair(general_properties.key_size, key_exponent=signing_attributes.exponent) root_cert, root_key_pair = crypto_functions.create_root_certficate(root_certificate_params, generated_root_key_pair, 7300, openssl_config_file_paths.openssl_configfile_path, 1) else: logger.info('Using a predefined Root certificate and a predefined key') logger.info('Key Used: '+ root_certificate_params['private_key_path']) logger.info('Certificate Used: '+ root_certificate_params['certificate_path']) root_cert, root_key_pair = self._get_certificate_and_key_pair_from_files(root_certificate_params) else: logger.error("Root certificate params are invalid! Please check config file.") raise RuntimeError("Root certificate params are invalid! Please check config file.") if num_certs_in_certchain > 2: logger.debug("Generating Attestation CA certificate, since certchain size is greater than 2") attestation_ca_certificate_params = crypto_params_dict['attest_ca_certificate_properties'] attestation_ca_params_is_valid, generate_new_attestation_ca = self._validate_certificate_params_dict(attestation_ca_certificate_params) if attestation_ca_params_is_valid: if generate_new_attestation_ca: logger.info('Generating new Attestation CA certificate and a random key') generated_attestation_ca__key_pair = crypto_functions.gen_rsa_key_pair(general_properties.key_size, key_exponent=signing_attributes.exponent) attestation_ca_certificate, attestation_ca_certificate_key_pair = \ crypto_functions.create_certificate(attestation_ca_certificate_params, generated_attestation_ca__key_pair, root_cert, root_key_pair, days=7300, configfile=openssl_config_file_paths.openssl_configfile_path, serial_num=1, extfile_name=openssl_config_file_paths.ca_certificate_extensions_path) else: logger.info('Using a predefined Attestation CA certificate and a predefined key') logger.info('Key Used: '+ attestation_ca_certificate_params['private_key_path']) logger.info('Certificate Used: '+ attestation_ca_certificate_params['certificate_path']) attestation_ca_certificate, attestation_ca_certificate_key_pair = self._get_certificate_and_key_pair_from_files(attestation_ca_certificate_params) else: logger.error("Attestation CA certificate params are invalid! Please check config file.") raise RuntimeError("Attestation CA certificate params are invalid! Please check config file.") attestation_certificate_params = crypto_params_dict['attest_certificate_properties'] attestation_certificate_params_is_valid, generate_new_attestation_certificate = self._validate_certificate_params_dict(attestation_certificate_params) if attestation_certificate_params_is_valid: if generate_new_attestation_certificate: #TCG support if self._is_tcg_supported(signing_attributes) is True: if self.validate_tcg_from_config(attestation_ca_certificate_params['certificate_path'], signing_attributes) is False: raise ConfigError("tcg_min and tcg_max are not set correctly in configuration."\ "Signing will not continue." ) attestation_certificate_extensions_path = self._generate_attestation_certificate_extensions( openssl_config_file_paths.attestation_certificate_extensions_path, signing_attributes.tcg_min, signing_attributes.tcg_max) else: attestation_certificate_extensions_path = openssl_config_file_paths.attestation_certificate_extensions_path logger.info('Generating new Attestation certificate and a random key') certificate_ou_sw_id ="01 " + hmac_params.sw_id_str + " SW_ID" certificate_ou_hw_id ="02 " + hmac_params.msm_id_str + " HW_ID" certificate_ou_oem_id ="04 " + "%0.4X" % oem_id + " OEM_ID" certificate_ou_sw_size ="05 " + "%0.8X" % len(binary_to_sign) + " SW_SIZE" certificate_ou_model_id ="06 " + "%0.4X" % model_id + " MODEL_ID" certificate_hash_alg = "07 0001 SHA256" certificate_ou = [ certificate_ou_sw_id, certificate_ou_hw_id, certificate_ou_oem_id, certificate_ou_sw_size, certificate_ou_model_id, certificate_hash_alg ] #Optional attributes if debug_val is not None: certificate_ou_debug_id ="03 " + "%0.16X" % debug_val + " DEBUG" certificate_ou.append(certificate_ou_debug_id) if app_id is not None: certificate_app_id = "08 " + "%0.16X" % app_id + " APP_ID" certificate_ou.append(certificate_app_id) if crash_dump is not None: certificate_crash_dump = "09 " + "%0.16X" % crash_dump + " CRASH_DUMP" certificate_ou.append(certificate_crash_dump) if rot_en is not None: certificate_rot_en = "10 " + "%0.16X" % rot_en + " ROT_EN" certificate_ou.append(certificate_rot_en) if 'OU' in attestation_certificate_params.keys(): if type(attestation_certificate_params['OU'])==list: for item in attestation_certificate_params['OU']: certificate_ou.append(item) else: certificate_ou.append(attestation_certificate_params['OU']) attestation_certificate_params['OU']=certificate_ou if attestation_certificate_key_pair is None: attestation_certificate_key_pair = crypto_functions.gen_rsa_key_pair(key_exponent=signing_attributes.exponent, key_size_in_bits = general_properties.key_size) if num_certs_in_certchain > 2: #sign the attestation cert with the attestation_ca_cert attestation_certificate, attestation_certificate_key_pair = \ crypto_functions.create_certificate(attestation_certificate_params, attestation_certificate_key_pair, attestation_ca_certificate, attestation_ca_certificate_key_pair, days=7300, configfile=openssl_config_file_paths.openssl_configfile_path, serial_num=1, extfile_name=attestation_certificate_extensions_path) else: #sign the attestation cert with the root cert attestation_certificate, attestation_certificate_key_pair = \ crypto_functions.create_certificate(attestation_certificate_params, attestation_certificate_key_pair, root_cert, root_key_pair, days=7300, configfile=openssl_config_file_paths.openssl_configfile_path, serial_num=1, extfile_name=attestation_certificate_extensions_path) attestation_certificate = crypto_functions.cert_pem_to_der(attestation_certificate) #Clean temp file if self._is_tcg_supported(signing_attributes) is True: c_path.clean_file(attestation_certificate_extensions_path) else: #generate_new_attestation_certificate == False logger.info('Using a predefined Attestation certificate and a predefined key') logger.info('Key Used: '+ attestation_certificate_params['private_key_path']) logger.info('Certificate Used: '+ attestation_certificate_params['certificate_path']) attestation_certificate, attestation_certificate_key_pair = self._get_certificate_and_key_pair_from_files(attestation_certificate_params) attestation_certificate = crypto_functions.cert_pem_to_der(attestation_certificate) # Since the get_hmac_params_from_certificate_chain always works with the first cert in the cert chain, # this function will work for a single der certificate as well. hmac_params = crypto_functions.get_hmacparams_from_certificate_chain(attestation_certificate) hasher = Hasher() hash_to_sign=hasher.qcom_hmac(binary_to_sign, hmac_params) signature = crypto_functions.encrypt_with_private_key(hash_to_sign, attestation_certificate_key_pair['private_key']) else: logger.error("Attestation certificate params are invalid! Please check config file.") raise RuntimeError("Attestation certificate params are invalid! Please check config file.") if num_certs_in_certchain > 2: attestation_ca_certificate = crypto_functions.cert_pem_to_der(attestation_ca_certificate) else: attestation_ca_certificate = None root_cert = crypto_functions.cert_pem_to_der(root_cert) root_cert_list = self.certconfig_parser.get_rootcerts() certificate_list = self._get_certificate_list(general_properties.num_root_certs, num_certs_in_certchain, attestation_certificate, attestation_ca_certificate, root_cert, root_cert_list) cert_chain=crypto_functions.create_certificate_chain(certificate_list) signer_output = SignerOutput() signer_output.root_cert = root_cert signer_output.attestation_ca_cert = attestation_ca_certificate signer_output.attestation_cert = attestation_certificate signer_output.signature = signature signer_output.cert_chain = cert_chain signer_output.root_cert_list = root_cert_list signer_output.attestation_key = attestation_certificate_key_pair['private_key'] return signer_output
def sign(self, dp_file, sign_id=None): """Sign the given debugpolicy elf file. """ try: self.input_file_list.pop() except: pass # Initialize SecImageCore isc = SecImageCore(debug=self.debug) isc.config_path = self.secimage_config if self.authority is not None: isc.authority = self.authority # Get the supported sign_id list sign_id_list = isc._img_config_parser.sign_id_list # Generating signed images for sign_ids available in sign_id list if sign_id is None: for sign in range(len(sign_id_list)): isc.set_image_path(dp_file, sign_id_list[sign]) isc.output_dir = os.path.dirname(dp_file) isc.image_info_list[0].dest_image.image_dir_ext = '' # Process the debug policy isc.process(sign=True) # Check if the signing is done or not if not isc.image_info_list[ 0].status.sign.state == isc.image_info_list[ 0].status.sign.SUCCESS: raise RuntimeError( 'Failed to sign the debugpolicy elf file: ' + isc.image_info_list[0].image_under_operation) logger.info('Signed debugpolicy elf file at: ' + isc.image_info_list[0].image_under_operation) self.input_file_list.append( isc.image_info_list[0].image_under_operation) if os.path.isfile( c_path.join(self.output_dir, 'SecImage_log.txt')): shutil.move( c_path.join(self.output_dir, 'SecImage_log.txt'), c_path.join( self.output_dir, (sign_id_list[sign] + '_secimage_log.txt'))) # Generating signed image for given sign_id else: if sign_id not in sign_id_list: raise RuntimeError('Received sign_id "' + sign_id + '" as input.' + '\n' " Supported sign_id's are: " + str(sign_id_list)) isc.set_image_path(dp_file, sign_id) isc.output_dir = os.path.dirname(dp_file) isc.image_info_list[0].dest_image.image_dir_ext = '' # Process the debug policy isc.process(sign=True) # Check if the signing is done or not if not isc.image_info_list[ 0].status.sign.state == isc.image_info_list[ 0].status.sign.SUCCESS: raise RuntimeError( 'Failed to sign the debugpolicy elf file: ' + isc.image_info_list[0].image_under_operation) logger.info('Signed debugpolicy elf file at: ' + isc.image_info_list[0].image_under_operation) self.input_file_list.append( isc.image_info_list[0].image_under_operation) if os.path.isfile(c_path.join(self.output_dir, 'SecImage_log.txt')): shutil.move( c_path.join(self.output_dir, 'SecImage_log.txt'), c_path.join(self.output_dir, (sign_id + '_secimage_log.txt')))