Пример #1
0
    def c_validate(self):
        """Validates the command line args provided by the user."""

        # configure verbosity level
        if self.parsed_args.quiet == 1:
            logger.verbosity = logger.WARN
        elif self.parsed_args.quiet > 1:
            logger.verbosity = logger.ERROR
        elif self.parsed_args.verbose == 0:
            logger.verbosity = logger.INFO
        else:
            logger.verbosity = logger.DEBUG

        err_strings = [
            "--target_base_dir (-t) is a required option and must be provided.",
            "--source (-i) is a required option and must be provided.",
            "--sign_id (-g) is a required option and must be provided.",
            "--jtag_id and --soc_hw_version are mutually exclusive options and cannot both be provided. Provide neither or provide only one.",
            "config", "qti_sign", "relocatable"
        ]

        init_logging = True
        err_message = validate_args(self.parsed_args, err_strings,
                                    init_logging)

        if err_message:
            logger.error(err_message)
            self.error(err_message)
Пример #2
0
 def restartDevice(self):
     """ Returns true if device restarted and connected
     """
     logger.info('Sending reboot command')
     if self.getDeviceStatus():
         process = subprocess.Popen('adb reboot && adb wait-for-device',
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
     elif self.checkFastboot():
         process = subprocess.Popen('fastboot reboot',
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
     else:
         raise RuntimeError(
             'device is not boot up and not in fastboot mode, please reboot the device manually'
         )
     stdout, stderr = process.communicate()
     retcode = process.returncode
     if retcode != 0:
         logger.error(ensure_str(stderr))
         return False
     else:
         logger.info(
             'reboot command completed, wait for 30 seconds to check if device boot up'
         )
         time.sleep(30)
         return self.getDeviceStatus()
Пример #3
0
def get_env_build_policy(environment):
    # get the supported build policies from the policy file
    supported_build_policies = sectools_builder_core.BuildPolicy.get_supported_build_policies(DEFAULT_POLICY_FILE)
    enabled_env_build_policies = []
    # get the enabled build policy from the environment using the ids from the supported build policies
    for policy in supported_build_policies:
        if environment.get("USES_SEC_POLICY_" + policy.upper()):
            logger.debug("Found build policy environment variable {0}".format("USES_SEC_POLICY_" + policy.upper()))
            enabled_env_build_policies.append(policy)
        elif environment.get("SEC_POLICY_" + policy.upper()):
            logger.debug("Found build policy environment variable {0}".format("SEC_POLICY_" + policy.upper()))
            enabled_env_build_policies.append(policy)
        elif environment.get(policy.upper()):
            logger.debug("Found build policy environment variable {0}".format(policy.upper()))
            enabled_env_build_policies.append(policy)
        elif environment.get(policy):
            logger.debug("Found build policy environment variable {0}".format(policy))
            enabled_env_build_policies.append(policy)
    if not enabled_env_build_policies:
        logger.info("No environmental build policy variable was enabled nor was one provided as a command line argument. Sectools will not be executed.")
        logger.info("If execution of Sectools is desired, a build policy must be set in the environment or passed as a command line argument. Supported build policies are: {0}".format(", ".join(supported_build_policies).upper()))
        return None
    elif len(enabled_env_build_policies) > 1:
        error_message = "The following environmental build policy variables are enabled: {0}. Only one build policy can be enabled at a time.".format(", ".join(enabled_env_build_policies).upper())
        logger.error(error_message)
        raise RuntimeError(error_message)
    else:
        logger.debug("Successfully retrieved build policy {0} from environment".format(enabled_env_build_policies[0].upper()))
        return enabled_env_build_policies[0]
Пример #4
0
def get_env_args(environment, init_logging, **kwargs):

    for key, val in kwargs.items():
        kwargs[key] = resolve(environment, val)
    kwargs["build_policy_id"] = get_env_build_policy(environment)
    kwargs["additional_secimage_policy_ids"] = get_env_secimage_policies(
        environment)

    arg_package = BuilderInputPackage(False, environment, **kwargs)

    err_strings = [
        "target_base_dir is a required value and must be provided.",
        "source is a required value and must be provided.",
        "sign_id is a required value and must be provided",
        "jtag_id and soc_hw_version are mutually exclusive values and cannot both be provided. Provide neither or provide only one.",
        "config", "qti_sign", "relocatable",
        "Provided target_image_type_filter value is invalid."
        "Provided config_type value is invalid."
    ]

    err_message = validate_args(arg_package, err_strings, init_logging)

    if err_message:
        logger.error(err_message)
        raise RuntimeError(err_message)
    else:
        logger.debug("Completed argument parsing")
        logger.debug("Wrapping parsed inputs into a package")
        return arg_package
 def build(self):
     logger.debug("Executing SectoolsBuilderCore.build()")
     # construct build policy object based on selected build_policy_id
     if self.input.build_policy is None and self.input.build_policy_id is None:
         logger.error("A build policy was not provided. Sectools execution, installation, and pilsplitting will be skipped.")
     elif self.input.build_policy is None:
         logger.debug("Constructing BuildPolicy based on selected build_policy_id...")
         self.input.build_policy = BuildPolicy(self.input.policy_file, self.input.build_policy_id, self.input.sign_id, self.input.sectools_install_base_dir, self.input.additional_secimage_policy_ids)
         logger.debug("\n\nConstructed BuildPolicy:\n" + str(self.input.build_policy) + "\n")
     # either call sectools and proceed with installation and pilsplitting or return SCons callback to build method
     if self.input.execute_sectools:
         # update config file with relocatable value
         self._generate_config_file()
         # validate files and paths
         errors = []
         validate_file(self.input.source, "source", errors)
         validate_dir(self.input.target_base_dir, "target_base_dir", errors)
         validate_dir(self.input.sectools_install_base_dir, "sectools_install_base_dir", errors)
         validate_dir(self.input.pilsplitter_target_base_dir, "pilsplitter_target_base_dir", errors)
         if errors:
             err_string = "\n".join(errors)
             logger.error(err_string)
             raise RuntimeError(err_string)
         # drive sign, install, and pilsplit sequence
         self._execute_sign()
     else:
         # return SCons callback to build method
         return self._scons_callback()
Пример #6
0
    def discover(self):
        """Searches for the ecies binary in the predefined packaged path.

        :returns str: Path to the ecies binary.
        """
        module_name = BINARY_NAME.title()
        filenames = bin_names(BINARY_NAME)
        filenames += alternate_bin_names(BINARY_NAME)
        module = ModuleNotFound

        for filename in filenames:
            file_path = c_path.join(packaged_bin_folder, filename)
            if c_path.validate_file(file_path):
                module = file_path
                logger.debug2(module_name + ': Found at - ' + module)
                break
        else:
            logger.debug2(module_name + ': Not Found')

        # Log if permissions are not correct
        if module != ModuleNotFound and not os.access(module, os.X_OK):
            logger.error(module_name +
                         ': Cannot execute. Missing execution permission.')

        return module
Пример #7
0
    def _executeCmds(self, cmds, verbose):
        image_info_list = []
        from sectools.features.isc.parsegen.elf import NON_HASHABLE_SEGMENTS, \
            NON_ENCAP_SEGMENTS, PT_PHDR, set_non_hashable_segments, \
            set_non_encap_segments
        try:
            parsed_args = secimage.parse_args(cmds)
            #Suppress secimage log level
            backup_verbosity = self.update_secimage_verbosity(
                self.args.verbose)

            #Include phdr for hashing
            backup_non_hashable_segments = NON_HASHABLE_SEGMENTS
            set_non_hashable_segments([])

            #Incluse phdr as non-encap segment
            backup_non_encap_segments = NON_ENCAP_SEGMENTS
            set_non_encap_segments(backup_non_encap_segments + [PT_PHDR])

            # Call sectools
            image_info_list = secimage.main(parsed_args)

        except Exception:
            logger.debug(traceback.format_exc())
            logger.error(sys.exc_info()[1])

        finally:
            set_non_encap_segments(backup_non_encap_segments)
            set_non_hashable_segments(backup_non_hashable_segments)
            logger.verbosity = backup_verbosity

        return image_info_list
    def _execute_install(self, policy):
        logger.debug("\nInstalling Sectools's output file...")
        if self.input.sectools_install_base_dir:
            path, filename = os.path.split(self.input.source)
            chipset = ConfigParser(
                self.input.config).root.metadata.get_chipset()
            src = c_path.normalize(
                c_path.join(self.input.target_base_dir, policy.id, chipset,
                            self.input.sign_id, filename))
            for install_location in policy.install_locations:
                if self.input.install_file_name:
                    dest = c_path.join(install_location,
                                       self.input.install_file_name)
                else:
                    dest = c_path.join(install_location, filename)

                # Attempt installation 3 times before failing
                installation_successful = False
                for i in range(3):
                    try:
                        c_path.create_dir(install_location)
                        copy_successful, error = c_path.copyFile(
                            src, dest, None, True)
                        if not copy_successful:
                            continue
                    except:
                        # Installation failed so retry installation
                        continue
                    installation_successful = True
                    logger.info("Installed \"{0}\" to \"{1}\"".format(
                        src, dest))
                    break
                if not installation_successful:
                    error_message = "Failed to install \"{0}\" to \"{1}\"".format(
                        src, dest)
                    logger.error(error_message)
                    raise RuntimeError(error_message)

                # pilsplit sectools's output file
                pilsplit_subdirectory = ""
                if install_location != self.input.sectools_install_base_dir:
                    pilsplit_subdirectory = install_location.replace(
                        os.path.join(self.input.sectools_install_base_dir, "",
                                     ""), "")
                pilsplit_prefix = self.input.install_file_name.split(
                    "."
                )[0] if self.input.install_file_name else filename.split(
                    ".")[0]
                self._execute_pilsplit(dest, pilsplit_prefix,
                                       pilsplit_subdirectory)
        else:
            logger.info(
                "Installation was skipped because a value for sectools_install_base_dir was not provided"
            )
            if self.input.pilsplitter_target_base_dir:
                logger.info(
                    "Pilsplitting was skipped because a value for sectools_install_base_dir was not provided"
                )
    def discover(self):
        '''Searches for the openssl binary in:

        #. The environment using the openssl tag
        #. Prepackaged binary folder
        #. Current path
        #. System path

        :returns str: Path to the openssl binary.
        '''
        module_name = BINARY_NAME.title()
        filenames = bin_names(BINARY_NAME)
        module = ModuleNotFound

        for filename in filenames:
            # Using the environment
            if OPENSSL_ENV_DIR_TAG in os.environ:
                env_module = c_path.join(os.environ[OPENSSL_ENV_DIR_TAG],
                                         filename)
                if not c_path.validate_file(env_module):
                    logger.debug2(
                        module_name +
                        ': File from environment does not exist at - ' +
                        env_module)
                elif not self.is_supported_version(env_module):
                    logger.debug2(
                        module_name +
                        ': File from environment is not the correct version - '
                        + env_module)
                else:
                    module = env_module
                    logger.debug2(module_name +
                                  ': Found from environment at - ' +
                                  env_module)
                    break

            # Searching in prepacked dir, current dir and system paths
            else:
                folder = packaged_bin_folder
                modules_found = c_path.which(filename, paths=[folder])
                for module_found in modules_found:
                    if not self.is_supported_version(module_found):
                        continue
                    module = module_found
                    conf_file = c_path.join(folder, OPENSSL_CONF_FILE)
                    if c_path.validate_file(conf_file):
                        os.environ[OPENSSL_ENV_CONF_TAG] = conf_file
                    logger.debug2(module_name + ': Found at - ' + module)
                    break
        else:
            logger.debug2(module_name + ': Not Found')

        # Log if permissions are not correct
        if module != ModuleNotFound and not os.access(module, os.X_OK):
            logger.error(module_name +
                         ': Cannot execute. Missing execution permission.')

        return module
Пример #10
0
    def __init__(self, meta_build_path, config_dir_obj, sign_id_list=[]):
        assert isinstance(meta_build_path, str)
        assert isinstance(config_dir_obj, ConfigDir)

        # Initialize the BaseStager
        BaseStager.__init__(self)

        self.config_dir_obj = config_dir_obj

        # Create internal attributes
        self._meta_build_path = meta_build_path

        # Validate that the meta_build path exists
        meta_build_path = c_path.normalize(meta_build_path)
        if not c_path.validate_dir(meta_build_path):
            raise RuntimeError('No read access to the meta build path: ' + meta_build_path)

        # Get the meta lib module from the metabuild
        meta_info = self.get_meta_info(meta_build_path)

        # Create the image info list based on the meta data
        for sign_id, chipset, image_src_path, image_dest_path in self.get_image_info_from_meta(meta_info):
            # Filer on the sign id
            if sign_id_list:
                if sign_id not in sign_id_list:
                    continue

            try:
                img_config_parser = self.get_image_config_parser(chipset)

                # Validate the sign_id
                sign_id = self._get_sign_id(img_config_parser,
                                            os.path.basename(image_src_path.image_path),
                                            sign_id)

                # Get the config block for the sign id
                img_config_block = img_config_parser.get_config_for_sign_id(sign_id)

                # Create the one image info object
                image_info = ImageInfo('', sign_id, img_config_block,
                                       img_config_parser)

                # Set the src path
                image_info.src_image = image_src_path
                image_info.image_under_operation = image_info.src_image.image_path

                # Set the dest path
                image_info.dest_image = image_dest_path

                # Put the image info object into the list
                self._image_info_list.append(image_info)

            except Exception as e:
                logger.error(str(e))

        if not self._image_info_list:
            raise RuntimeError('No images found from the meta build.')
Пример #11
0
 def get_data(self, sign=None, encrypt=None):
     # Resolve the operation
     sign = self.sign if sign is None else sign
     encrypt = self.encrypt if encrypt is None else encrypt
 
     # Allow base to do any checks
     SecParseGenBase.get_data(self, sign, encrypt)
     if encrypt:
         logger.error('Mbn Images do not support encryption. Returning the ' + ('signed' if sign else 'raw') + ' image.')
     return self._get_data_int(sign, False)     
Пример #12
0
 def checkFastboot(self):
     process = subprocess.Popen('fastboot devices',
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
     stdout, stderr = process.communicate()
     if process.returncode == 0 and stdout != '':
         return True
     else:
         logger.error(ensure_str(stderr))
         return False
Пример #13
0
 def get_data(self, sign=None, encrypt=None):
     # Resolve the operation
     sign = self.sign if sign is None else sign
     encrypt = self.encrypt if encrypt is None else encrypt
 
     # Allow base to do any checks
     SecParseGenBase.get_data(self, sign, encrypt)
     if sign:
         logger.error('Bin Images do not support signing. Returning the raw image.')
     return self._get_data_int(False, encrypt)     
Пример #14
0
    def discover(self):
        """Searches for the openssl binary in:

        #. The environment using the openssl tag
        #. Prepackaged binary folder
        #. Current path
        #. System path

        :returns str: Path to the openssl binary.
        """
        module_name = BINARY_NAME.title()
        filenames = bin_names(BINARY_NAME)
        module = ModuleNotFound
        logger.debug2('module_name: ' + str(module_name) + ', filenames: ' + str(filenames))

        for filename in filenames:
            # Using the environment
            if OPENSSL_ENV_DIR_TAG in os.environ:
                logger.debug2(str(OPENSSL_ENV_DIR_TAG) + ' tag found in environment')
                env_module = c_path.join(os.environ[OPENSSL_ENV_DIR_TAG], filename)
                logger.debug2('Looking for: ' + str(env_module))
                if not c_path.validate_file(env_module):
                    logger.warning(module_name + ': File from environment does not exist at - ' + env_module)
                elif not self.is_supported_version(env_module):
                    logger.warning(module_name + ': File from environment is not the correct version - ' + env_module)
                else:
                    module = env_module
                    logger.debug2(module_name + ': Found from environment at - ' + env_module)
                    break

            # Searching in prepacked dir, current dir and system paths
            else:
                folder = packaged_bin_folder
                logger.debug2('Looking for: ' + str(filename) + ' in folder: ' + str(folder))
                for module_found in c_path.which_generator(filename, paths=[folder], find_one=False):
                    if not self.is_supported_version(module_found):
                        logger.debug2('Incorrect version: ' + str(module_found))
                        continue
                    module = module_found
                    conf_file = c_path.join(folder, OPENSSL_CONF_FILE)
                    if c_path.validate_file(conf_file):
                        os.environ[OPENSSL_ENV_CONF_TAG] = conf_file
                    logger.debug2(module_name + ': Found at - ' + module)
                    break
                # Check if module is found
                if module != ModuleNotFound:
                    break
        else:
            logger.error(module_name + ': Not Found')

        # Log if permissions are not correct
        if module != ModuleNotFound and not os.access(module, os.X_OK):
            logger.error(module_name + ': Cannot execute. Missing execution permission.')

        return module
Пример #15
0
    def _decrypt_data(self):
        if self.encdec is None:
            logger.error("Input image is encrypted but decryption of image failed. There are two possible causes:\n"
                         + "\t1) Selected_encryptor is not set in config file or command line args.\n"
                         + "\t2) You are attempting to sign but not encrypt a previously encrypted image. This is not allowed.")
            raise RuntimeError('Image is encrypted. Cannot proceed without a decryptor.')

        decryptor = self.encdec.get_decryptor(encryption_parameters_blob=self.encryption_params,
                                              key=self.encdec.get_dummy_key())

        parsegen_updater = ParseGenEncDec(self.store_debug_data, self.encrypt_segment)
        parsegen_updater.decrypt(self.encdec.get_segment_num_scheme(), self._elf_parsegen, decryptor)
Пример #16
0
    def process_file(self, input_file=None):
        if self.args.validate or self.serialnum is None:
            input_filename = input_file if input_file is not None else self.args.image_file
            path, filename = os.path.split(input_filename)
            signed_filename = filename
            if path != self.args.output_dir or self.args.validate is True:
                output_filename = signed_filename
            else:
                name, ext = os.path.splitext(signed_filename)
                output_filename = name + "_signed" + ext
        else:
            input_filename = TESTSIG_PATH
            output_filename = "{0}{1}.so".format(TESTSIG_PREFIX,
                                                 self.serialnum.unpadded_str)
            signed_filename = TESTSIG_FILENAME

        c_path.create_dir(self.args.output_dir)

        output_filename_base, ext = os.path.splitext(output_filename)
        self.generated_config = os.path.join(
            self.args.output_dir,
            output_filename_base + "_" + GENERATED_CONFIG)
        src_config = self.args.config if self.args.config else DEFAULT_SRC_CONFIG
        logger.debug("Source config file: {0}".format(src_config))
        self.generate_config_file(src_config, self.generated_config, self.args)

        image_info_list = self.invokeSecImage(self.args, input_filename,
                                              self.generated_config)

        #Post processing
        retValue = False if len(image_info_list) == 0 else True
        for image_info in image_info_list:
            if self.args.validate:
                if image_info.status.validate_sign.state == StatusInfo.SUCCESS:
                    logger.info("Input file is signed and valid!")
                elif image_info.status.validate_sign.state == StatusInfo.ERROR:
                    if self.log_contains(STR_OUTPUT_UNSIGNED_VALID):
                        logger.info(self.ERR_FILE_NOT_SIGNED)
                    elif self.log_contains(STR_OUTPUT_SIGNED_INVALID):
                        logger.info(self.ERR_FILE_SIG_INVALID)
                    else:
                        logger.error(self.ERR_FILE_INVALID)
                    retValue = False
            else:
                if image_info.status.sign.state == StatusInfo.SUCCESS and \
                    image_info.status.validate_sign.state == StatusInfo.SUCCESS:
                    self.postProcess(signed_filename, output_filename,
                                     self.generated_config)
                else:
                    logger.error("Signing failed!")
                    retValue = False

        return retValue
Пример #17
0
 def fastbootDevice(self):
     """ Returns true if device is in fastboot mode
     """
     process = subprocess.Popen('adb reboot bootloader',
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
     stdout, stderr = process.communicate()
     if process.returncode == 0:
         time.sleep(5)
         return self.checkFastboot()
     else:
         logger.error(ensure_str(stderr))
         return False
Пример #18
0
    def get_data(self, integrity_check=None, sign=None, encrypt=None):
        # Resolve the operation
        integrity_check = self.integrity_check if integrity_check is None else integrity_check
        sign = self.sign if sign is None else sign
        encrypt = self.encrypt if encrypt is None else encrypt

        # Allow base to do any checks
        SecParseGenBase.get_data(self, integrity_check, sign, encrypt)
        if integrity_check:
            logger.error('Mbn Images do not support integrity check.')
        if encrypt:
            logger.error('Mbn Images do not support encryption.')
        return self._get_data_int(sign, False)
Пример #19
0
 def _status_updater(self, method, status, progress, raise_err, *args, **kwargs):
     try:
         retval = method(*args, **kwargs)
         status.state = StatusInfo.SUCCESS
         progress.push()
         return retval
     except Exception as e:
         status.state = StatusInfo.ERROR
         status.error = str(e)
         progress.push()
         if raise_err:
             raise
         else:
             logger.error(status.error)
Пример #20
0
 def _status_updater(self, method, status, progress, raise_err, *args, **kwargs):
     try:
         retval = method(*args, **kwargs)
         status.state = StatusInfo.SUCCESS
         progress.push()
         return retval
     except Exception as e:
         status.state = StatusInfo.ERROR
         status.error = str(e)
         progress.push()
         if raise_err:
             raise
         else:
             logger.error(status.error)
Пример #21
0
    def __init__(self, policy_file, build_policy_id, sign_id, install_base_dir, additional_secimage_policy_ids):
        root = CoreConfig(policy_parser, policy_file).root
        self.install_base_dir = install_base_dir

        # get all the supported build policies
        supported_build_policies = root.build_policy.policy_enable

        # loop through supported build policies and check that build_policy_id corresponds to one of the supported build policies
        self.policy = None
        supported_build_policy_ids = []

        # get build policy based on provided build_policy_id
        for build_policy in supported_build_policies:
            supported_build_policy_ids.append(build_policy.id)
            if build_policy.id == build_policy_id or build_policy.feature_flag.lower() == build_policy_id or "sec_policy_" + build_policy.id == build_policy_id:
                # found build policy matching specified policy
                self.policy = build_policy
        if self.policy is None:
            # raise error because the provided build_policy_id is not one of the ids specified in the sectools_policy.xml file
            error_message = "Provided build_policy_id \"{0}\" does not match one of the supported build policy ids: {1}".format(build_policy_id, ", ".join(supported_build_policy_ids))
            logger.error(error_message)
            raise RuntimeError(error_message)

        # get the sec image policies
        logger.debug("Getting secimage policies for \"{0}\" build policy...".format(build_policy_id))
        self.sec_image_policies, self.sec_image_policy_ids = BuildPolicy._get_policies(root.sec_image_policy.policy, self.policy.sec_image_policy)
        logger.debug("Secimage policies retrieved for \"{0}\" build policy: {1}".format(build_policy_id, ", ".join(self.sec_image_policy_ids)))

        # get the sec image policies specified by additional_secimage_policy_ids
        if additional_secimage_policy_ids:
            logger.debug("Adding additional secimage policies specified in the environment to the build policy...")
            additional_secimage_policies, additional_secimage_policy_ids = BuildPolicy._get_policies(root.sec_image_policy.policy, additional_secimage_policy_ids, self.sec_image_policy_ids)
            # add the additional sec image policies and their ids to the existing sec image lists
            if additional_secimage_policy_ids:
                logger.debug("Additional secimage policies added to \"{0}\" build policy: {1}".format(build_policy_id, ", ".join(additional_secimage_policy_ids)))
                self.sec_image_policies += additional_secimage_policies
                self.sec_image_policy_ids += additional_secimage_policy_ids

        # filter out sec image policies that specify an excluded sign_id that matches the provided sign_id
        BuildPolicy._remove_policies_for_excluded_sign_ids(self.sec_image_policies, self.sec_image_policy_ids, sign_id)

        # get the install policies
        logger.debug("Getting install policies for \"{0}\" build policy...".format(build_policy_id))
        self.install_policies, self.install_policy_ids = BuildPolicy._get_policies(root.install_policy.policy, self.policy.install_policy)
        logger.debug("Install policies retrieved for \"{0}\" build policy: {1}".format(build_policy_id, ", ".join(self.install_policy_ids)))

        # initialize install locations for sec image policies if installation should be performed
        if self.install_base_dir:
            BuildPolicy._set_install_locations_for_sec_image_policies(self.install_policies, self.sec_image_policies, self.install_base_dir)
Пример #22
0
    def get_data(self, integrity_check=None, sign=None, encrypt=None):
        # Resolve the operation
        integrity_check = self.integrity_check if integrity_check is None else integrity_check
        sign = self.sign if sign is None else sign
        encrypt = self.encrypt if encrypt is None else encrypt

        if integrity_check:
            logger.error('Bin Images do not support integrity check.')
        if sign:
            logger.error('Bin Images do not support signing.')

        data = self.data
        if encrypt:
            data = self.encryption_params + self.encrypt_segment(data, 0)
        return data
Пример #23
0
    def _validate_oid_raw(self, min_attest, max_attest, min_ca, max_ca):
        tcg_ok = False

        if min_attest is not None:
            assert isinstance(min_attest, BaseAttribute)
        if max_attest is not None:
            assert isinstance(max_attest, BaseAttribute)
        if min_ca is not None:
            assert isinstance(min_ca, BaseAttribute)
        if max_ca is not None:
            assert isinstance(max_ca, BaseAttribute)

        if ((min_attest is None) and (max_attest is None) and (min_ca is None)
                and (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 (min_attest is not None) and (max_attest is not None) and (
                min_ca is None) and (max_ca is None):
            logger.error(
                "\nTCGs found in Attestation cert, but not in CA cert. This is invalid."
            )
        elif (min_attest is None) and (max_attest is None) and (
                min_ca is not None) and (max_ca is not None):
            logger.error(
                "\nNo TCGs found in Attestation cert, but there are TCGs in CA cert. This is invalid."
            )
        elif (min_attest is not None) and (max_attest is not None) and (
                min_ca is not None) and (max_ca is not None):
            if (min_ca.value <= min_attest.value <= max_attest.value <=
                    max_ca.value):
                tcg_ok = True
                logger.debug("\nTCG values fall within CA constraints.")
            else:
                logger.error("\nTCG values are outside the CA constraints.")
        else:
            logger.error("\nInvalid TCG values")

        tcg_log_mesg = "\nAttestation cert : tcg_min={0} tcg_max={1}".format(min_attest, max_attest) + \
                       "\nCA cert (allowed): tcg_min={0} tcg_max={1}\n".format(min_ca, max_ca)
        if tcg_ok is False:
            logger.error(tcg_log_mesg)
        else:
            logger.debug(tcg_log_mesg)

        return tcg_ok
Пример #24
0
 def _status_updater(self, method, status, progress, raise_err, *args, **kwargs):
     try:
         retval = method(*args, **kwargs)
         status.state = StatusInfo.SUCCESS
         return retval
     except CustomError as e:
         # No change in imageinfo status.
         logger.info(str(e))
     except Exception as e:
         status.state = StatusInfo.ERROR
         status.error = str(e)
         if raise_err:
             raise
         else:
             logger.error(status.error)
     finally:
         progress.push()
Пример #25
0
 def _status_updater(self, method, status, progress, raise_err, *args, **kwargs):
     from imageinfo import ImageInfo, StatusInfo
     try:
         retval = method(*args, **kwargs)
         status.state = StatusInfo.SUCCESS
         progress.push()
         return retval
     except Exception as e:
         status.state = StatusInfo.ERROR
         status.error = str(e)
         progress.push()
         if raise_err:
             raise
         else:
             if isinstance (e, CustomError):
                 logger.info(status.error)
             else:
                 logger.error(status.error)
Пример #26
0
    def get_image_info_from_meta(cls, meta_info):
        # Get a list of all files tagged with sign_id
        meta_images_list = meta_info.get_files_detailed('sign_id')

        for image in meta_images_list:
            try:
                logger.debug('Found image from meta_build for signing: ' +
                             image.sign_id)

                source_path = None
                dest_path = None
                for each_path in image.file_path:
                    if source_path is None:
                        if getattr(each_path, 'sign_source', False):
                            source_path = each_path.value
                    if dest_path is None:
                        if getattr(each_path, 'sign_dest', False):
                            dest_path = each_path.value
                    if source_path and dest_path:
                        break

                if source_path is None or dest_path is None:
                    raise RuntimeError(
                        'SourcePath, DestPath should not be missing.')

                sign_id = image.sign_id
                chipset = image.chipset
                image_src_path = ImagePath()
                image_dest_path = DestImagePath()

                image_src_path.image_dir_base = image.image_dir_base
                image_src_path.image_dir_ext = source_path
                image_src_path.image_name = image.file_name[0].value
                image_dest_path.image_dir_base = image.image_dir_base
                image_dest_path.image_dir_ext = dest_path
                image_dest_path.image_name = image.file_name[0].value

            except Exception as e:
                logger.error(str(e))
                continue

            yield (sign_id, chipset, image_src_path, image_dest_path,
                   MetaError.SUCCESS)
Пример #27
0
        def _decode_binary_blob(self, binary_blob, validating):
            if len(binary_blob) != EncryptionParamsSectionBody.L2AssociatedData.SPEC_SIZE_BYTES:
                raise RuntimeError("L2 Associated Data blob is of the wrong size")

            string_offset = 0
            string_end = EncryptionParamsSectionBody.L2AssociatedData.L2_ASSOCIATED_DATA_SIZE_FLD_LEN_BYTES
            self.l2_associated_data_size, = struct.unpack(">H", binary_blob[string_offset:string_end])

            string_offset = string_end + EncryptionParamsSectionBody.RSVD_BYTE_LEN_BYTES * 2
            string_end = string_offset + EncryptionParamsSectionBody.L2AssociatedData.MAJOR_VERSION_FLD_LEN_BYTES + \
                         EncryptionParamsSectionBody.L2AssociatedData.MINOR_VERSION_FLD_LEN_BYTES + \
                         EncryptionParamsSectionBody.L2AssociatedData.KEY_LADDER_LEN_FLD_LEN_BYTES + \
                         EncryptionParamsSectionBody.RSVD_BYTE_LEN_BYTES

            major_version, minor_version, self.key_ladder_length, tmp = struct.unpack("=BBBB", binary_blob[string_offset:string_end])
            string_offset = string_end

            if (major_version, minor_version) != (self.major_version, self.minor_version):
                raise RuntimeError(("Encryption Parameters L2 Associated Data version \"{0}.{1}\" does not match expected version \"{2}.{3}\""
                                    "\n       Ensure that the correct encryptor value is set.").format(major_version, minor_version, self.major_version, self.minor_version))

            if (major_version, minor_version) == (EncryptionParamsSectionBody.L2AssociatedData.MAJOR_VERSION_FLD_VAL_1, EncryptionParamsSectionBody.L2AssociatedData.MINOR_VERSION_FLD_VAL_0):
                string_end = string_offset + EncryptionParamsSectionBody.L2AssociatedData.IMAGE_ID_BITMAP_FLD_VERSION_1_0_LEN_BYTES
                image_id_bitmap, = struct.unpack("=I", binary_blob[string_offset:string_end])
            elif (major_version, minor_version) == (EncryptionParamsSectionBody.L2AssociatedData.MAJOR_VERSION_FLD_VAL_1, EncryptionParamsSectionBody.L2AssociatedData.MINOR_VERSION_FLD_VAL_1):
                string_end = string_offset + EncryptionParamsSectionBody.L2AssociatedData.IMAGE_ID_BITMAP_FLD_VERSION_1_1_LEN_BYTES
                image_id_bitmap_upper, image_id_bitmap_lower = struct.unpack("=QQ", binary_blob[string_offset:string_end])
                image_id_bitmap = image_id_bitmap_lower * (2 ** 64) + image_id_bitmap_upper
            else:
                raise RuntimeError("Configured Encryption Parameters L2 Associated Data version \"{0}.{1}\" is invalid.".format(self.major_version, self.minor_version))

            image_id = int(math.log(image_id_bitmap, 2))
            if image_id != self.image_id:
                if validating:
                    errstr = list()
                    mismatches = list()
                    mismatches.append((EncryptionParamsSectionBody.L2AssociatedData.IMAGE_ID, "0x%X" % image_id, "0x%X" % self.image_id))
                    create_mismatch_table(mismatches, errstr, operation="encryption", data_type_to_compare="Attribute", image_region="Encryption Parameters")
                    logger.error('Following validations failed for the image:\n       ' +
                                 '\n       '.join([(str(i + 1) + '. ' + e) for i, e in enumerate(errstr)]))
                else:
                    logger.warning(("Extracted Encryption Parameters " + EncryptionParamsSectionBody.L2AssociatedData.IMAGE_ID + " value \"{0}\" does not match config value \"{1}\""
                                   "\n\t Encryption Parameters " + EncryptionParamsSectionBody.L2AssociatedData.IMAGE_ID + " value will be updated with value \"{1}\"").format(hex(image_id), hex(self.image_id)))
Пример #28
0
    def execute(self, cmd, logfile, work_dir=None, timer=900, interval=5):
        fd = open(logfile, 'w+')
        p = subprocess.Popen(r" ".join(cmd), cwd=work_dir, shell=False, stdout=fd, stderr=fd)
        self.pid = p.pid

        # set timer and start polling process status
        # kill the test process and cleanup upon timeout
        import time
        count = int(timer / interval)
        while count > 0:
            time.sleep(interval)
            if p.poll() is not None:
                break
            count -= 1
        if p.poll() is None:
            p.terminate()
            logger.error('process is terminiated due to timeout after ' + str(timer) + ' seconds')
        fd.close()

        return p.returncode
Пример #29
0
 def _execute_pilsplit(self, file_to_pilsplit, pilsplit_prefix, subdirectory):
     logger.debug("\nPilsplitting Sectools's output file...")
     if self.input.pilsplitter_target_base_dir:
         try:
             if subdirectory:
                 subdir = c_path.join(self.input.pilsplitter_target_base_dir, subdirectory)
                 c_path.create_dir(subdir)
                 prefix = c_path.join(subdir, pilsplit_prefix)
             else:
                 subdir = self.input.pilsplitter_target_base_dir
                 prefix = c_path.join(self.input.pilsplitter_target_base_dir, pilsplit_prefix)
             SecImageCore.pil_split(file_to_pilsplit, prefix)
             logger.info("Pilsplitted \"{0}\" into directory \"{1}\"".format(file_to_pilsplit, subdir))
         except Exception as e:
             logger.error(str(e))
             error_message = "Failed to pilsplit \"{0}\"".format(file_to_pilsplit)
             logger.error(error_message)
             raise RuntimeError(error_message)
     else:
         logger.info("Pilsplit was skipped because a value for pilsplitter_target_base_dir was not provided")
    def get_image_info_from_meta(cls, meta_info):
        # Get a list of all files tagged with sign_id
        meta_images_list = meta_info.get_files_detailed('sign_id')

        for image in meta_images_list:
            try:
                logger.debug('Found image from meta_build for signing: ' + image.sign_id)

                source_path = None
                dest_path = None
                for each_path in image.file_path:
                    if source_path is None:
                        if getattr(each_path, 'sign_source', False):
                            source_path = each_path.value
                    if dest_path is None:
                        if getattr(each_path, 'sign_dest', False):
                            dest_path = each_path.value
                    if source_path and dest_path:
                        break

                if source_path is None or dest_path is None:
                    raise RuntimeError('SourcePath, DestPath should not be missing.')

                sign_id = image.sign_id
                chipset = image.chipset
                image_src_path = ImagePath()
                image_dest_path = DestImagePath()

                image_src_path.image_dir_base = image.image_dir_base
                image_src_path.image_dir_ext = source_path
                image_src_path.image_name = image.file_name[0].value
                image_dest_path.image_dir_base = image.image_dir_base
                image_dest_path.image_dir_ext = dest_path
                image_dest_path.image_name = image.file_name[0].value

            except Exception as e:
                logger.error(str(e))
                continue

            yield (sign_id, chipset, image_src_path, image_dest_path)
Пример #31
0
    def _validate_certificate_params_dict(self, certificate_params_dict):
        certificate_params_is_valid = False
        generate_new_certificate = False
        for key in certificate_params_dict:
            if key not in ['C', 'CN', 'L', 'O', 'ST', 'OU']:
                if key not in ['private_key_path', 'certificate_path']:
                    logger.error("Invalid Key is being passed in configuration!" + repr(key))
                    raise RuntimeError("Invalid Key is being passed in configuration!")
                else:
                    if os.path.exists(certificate_params_dict['private_key_path']) is False:
                        err_str = "private_key_path does not exist: {0}!".format(certificate_params_dict['private_key_path'])
                        logger.error(err_str)
                        certificate_params_is_valid = False
                        raise RuntimeError(err_str)

                    if os.path.exists(certificate_params_dict['certificate_path']) is False:
                        err_str = "certificate_path does not exist: {0}!".format(certificate_params_dict['certificate_path'])
                        logger.error(err_str)
                        certificate_params_is_valid = False
                        raise RuntimeError(err_str)

                    generate_new_certificate = False
                    certificate_params_is_valid = True

            else:
                certificate_params_is_valid = True
                generate_new_certificate = True

        return certificate_params_is_valid, generate_new_certificate
    def _validate_certificate_params_dict(self, certificate_params_dict):
        certificate_params_is_valid = False
        generate_new_certificate = False
        for key in certificate_params_dict:
            if key not in ['C', 'CN', 'L', 'O', 'ST', 'OU']:
                if key not in ['private_key_path', 'certificate_path']:
                    logger.error("Invalid Key is being passed in configuration!" + repr(key))
                    raise RuntimeError("Invalid Key is being passed in configuration!")
                else:
                    if os.path.exists(certificate_params_dict['private_key_path']) is False:
                        err_str = "private_key_path does not exist: {0}!".format(certificate_params_dict['private_key_path'])
                        logger.error(err_str)
                        certificate_params_is_valid = False
                        raise RuntimeError(err_str)

                    if os.path.exists(certificate_params_dict['certificate_path']) is False:
                        err_str = "certificate_path does not exist: {0}!".format(certificate_params_dict['certificate_path'])
                        logger.error(err_str)
                        certificate_params_is_valid = False
                        raise RuntimeError(err_str)

                    generate_new_certificate = False
                    certificate_params_is_valid = True

            else:
                certificate_params_is_valid = True
                generate_new_certificate = True

        return certificate_params_is_valid, generate_new_certificate
Пример #33
0
    def loadMetaBuild(self, keyword=None, timer=1200, interval=5):
        """ load meta build with fastboot_complete.py
        :param str meta_build_path: meta build directory, require read access
        """
        if self.run:
            self.retcode = ''
            # meta build path validation
            meta_path_val = c_path.normalize(self.meta_build_path)
            if not c_path.validate_dir_write(meta_path_val):
                raise RuntimeError('Cannot write at: ' + meta_path_val)

            # check device status (put device to fastboot mode)
            if AndroidDevice.checkFastboot():
                enable_buildloading = True
            else:
                enable_buildloading = AndroidDevice.fastbootDevice()

            if enable_buildloading:
                cmd = ['python', BUILDLOAD_PY]
                cwd = c_path.join(meta_path_val, BUILD_SCRIPTS_DIR)
                self.logging_state_info(getCurrentTime() + ' start meta build loading, please wait and do not interrupt ...')
                self.logging_state_info('Set current working directory: ' + cwd)
                self.logging_state_info('Meta build loading command: ' + " ".join(cmd))
                self.log = c_path.join(meta_path_val, FASTBOOT_COMPLETE_LOG)
                self.run = False
                self.retcode = self.execute(cmd, self.log, cwd, timer, interval)
                self.logging_state_info(getCurrentTime() +' meta build loading return code: ' + str(self.retcode))
                self.logging_state_info('meta build loading log can be found at: ' + self.log)
                if self.retcode == 0:
                    self.run = True
                self.logging_state_info(SECTION_BREAK)
                if AndroidDevice.restartDevice():
                    self.logging_state_info('device reboot completed')
                else:
                    self.logging_state_info('device reboot failed, please reboot the device manually')
            else:
                self.retcode = 1
                logger.error('device cannot be set in fastboot mode, please set manually')
        else:
            self.logging_state_info('skip meta build loading')
    def __init__(self, meta_build_path, config_dir_obj, sign_id_list=[]):
        assert isinstance(meta_build_path, str)
        assert isinstance(config_dir_obj, ConfigDir)

        # Initialize the BaseStager
        BaseStager.__init__(self)

        self.config_dir_obj = config_dir_obj

        # Create internal attributes
        self._meta_build_path = meta_build_path

        # Validate that the meta_build path exists
        meta_build_path = c_path.normalize(meta_build_path)
        if not c_path.validate_dir(meta_build_path):
            raise RuntimeError('No read access to the meta build path: ' + meta_build_path)

        # Get the meta lib module from the metabuild
        meta_info = self.get_meta_info(meta_build_path)

        # Create the image info list based on the meta data
        for sign_id, chipset, image_src_path, image_dest_path in self.get_image_info_from_meta(meta_info):
            # Filer on the sign id
            if sign_id_list:
                if sign_id not in sign_id_list:
                    continue

            try:
                img_config_parser = self.get_image_config_parser(chipset)

                # Validate the sign_id
                sign_id = self._get_sign_id(img_config_parser,
                                            os.path.basename(image_src_path.image_path),
                                            sign_id)

                # Get the config block for the sign id
                img_config_block = img_config_parser.get_config_for_sign_id(sign_id)

                # Create the one image info object
                image_info = ImageInfo('', sign_id, img_config_block,
                                       img_config_parser)

                # Set the src path
                image_info.src_image = image_src_path
                image_info.image_under_operation = image_info.src_image.image_path

                # Set the dest path
                image_info.dest_image = image_dest_path

                # Check if the dest image name should be overriden
                if img_config_block.output_file_name is not None:
                    image_info.dest_image.image_name = img_config_block.output_file_name

                # Put the image info object into the list
                self._image_info_list.append(image_info)

            except Exception as e:
                logger.error(str(e))

        if not self._image_info_list:
            raise RuntimeError('No images found from the meta build.')
Пример #35
0
    if len(args) > 1:
        feature = args[1]
        for supported_feature in FEATURES_LIST:
            if feature == supported_feature.CMD_ARG_TOOL_NAME:
                supported_feature.main(supported_feature.parse_args(sys.argv[1:]))
                break
        else:
            raise RuntimeError('Feature provided from command line: "' + feature + '" is invalid.' + '\n'
                               '       ' + 'Please choose from : ' + str([f.CMD_ARG_TOOL_NAME for f in FEATURES_LIST]))

if __name__ == '__main__':
    try:
        # Check that the command line are valid and are normalized.
        args = SectoolsParser().pos_args

        main(args)

    except Exception:
        logger.debug(traceback.format_exc())
        logger.error(sys.exc_info()[1])
        sys.exit(1)

    except KeyboardInterrupt:
        print
        logger.error('Keyboard Interrupt Received. Exiting!')
        sys.exit(1)

    sys.exit(0)

    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
Пример #37
0
    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 get_image_info_from_meta(self, meta_info):
        # Cache dicts
        build_paths = dict()
        attrs = dict()
        file_types = dict()

        for sign_id in self.img_config_parser.sign_id_list:
            try:
                logger.debug('Searching metabuild for ' + sign_id)
                image = self.img_config_parser.get_config_for_sign_id(sign_id)
                image_path = image.meta_build_location

                # Replace any tags
                re_match = re.match('\$\((.*?)\)', image_path)
                if re_match:
                    tags = re_match.group(1)
                    tags_dict = {}
                    for tag in tags.split(','):
                        tag = tag.strip().split(':')
                        tags_dict[tag[0]] = tag[1]

                    replacement = None
                    if self.TAG_BUILD_PATH in tags_dict:
                        build = tags_dict[self.TAG_BUILD_PATH]
                        paths_data = build_paths.get(build, None)
                        if paths_data is None:
                            paths_data = meta_info.get_build_path(build)
                            build_paths[build] = paths_data
                        replacement = paths_data

                    elif self.TAG_ATTR in tags_dict:
                        attr = tags_dict[self.TAG_ATTR]
                        file_type = tags_dict[self.TAG_FILE_TYPE]
                        paths_data = attrs.get((attr, file_type), None)
                        if paths_data is None:
                            paths_data = meta_info.get_file_vars(attr, file_type)
                            attrs[(attr, file_type)] = paths_data
                        if tags_dict[self.TAG_VAR] in paths_data:
                            replacement = paths_data[tags_dict[self.TAG_VAR]][0]

                    elif self.TAG_FILE_TYPE in tags_dict:
                        file_type = tags_dict[self.TAG_FILE_TYPE]
                        paths_data = file_types.get(file_type, None)
                        if paths_data is None:
                            paths_data = meta_info.get_files(file_type)
                            file_types[file_type] = paths_data
                        if paths_data:
                            for each_path in paths_data:
                                if each_path.lower().endswith(image.name.lower()):
                                    replacement = each_path
                                    break
                    else:
                        raise RuntimeError('Unknown image type')

                    if replacement:
                        image_path = image_path.replace(re_match.group(0), replacement)
                    else:
                        logger.warning('File not found in meta build: ' + sign_id)
                        continue

                image_path = image_path.replace(self.REPL_META_PATH, self._meta_build_path)

                image_src_path = ImagePath()
                image_dest_path = DestImagePath()

                image_src_path.image_dir_base = os.path.dirname(image_path)
                image_src_path.image_dir_ext = ''
                image_src_path.image_name = os.path.basename(image_path)
                image_dest_path.image_dir_base = os.path.dirname(image_path)
                image_dest_path.image_dir_ext = ''
                image_dest_path.image_name = os.path.basename(image_path)

            except Exception as e:
                logger.error(str(e))
                continue

            yield (sign_id, self.chipset, image_src_path, image_dest_path)