Beispiel #1
0
    def _process_secure_operation(self, image, progress, integrity_check, sign, encrypt, 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
        image.encdec = encdec
        parsegen = self._status_updater(self._create_parsegen_obj,
                                        image.status.parsegen,
                                        progress, True,
                                        image)

        # Set the security mechanisms
        parsegen.integrity_check = parsegen.contains_integrity_check() or integrity_check
        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,
                                 progress, True,
                                 image, parsegen)

        # Package and generate the output image file
        if integrity_check or sign or encrypt:
            store_data_to_file(image.dest_image.image_path, parsegen.get_data())
            if integrity_check:
                image.status.integrity_check.state = StatusInfo.SUCCESS
            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,
                                 progress, True,
                                 image, image.config.post_process.pil_splitter,
                                 getattr(self._stager, '_meta_build_path', None))

        # 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))
    def _sign(self, binary_to_sign, image_tosign_filename, cert_folder):

        c_path.create_dir(cert_folder)

        c_misc.store_data_to_file(image_tosign_filename, binary_to_sign)
        sig_package = signerutils.getSigPackage(cert_folder)
        if sig_package is not None:
            [signature, cert_chain_list] = signerutils.\
                                        readSigFromZip(sig_package)
            if self.validate_sig(binary_to_sign, signature,
                                 cert_chain_list) is False:
                raise ExternalSignerError(
                    self.MESG_INVALID_SIG.format(image_tosign_filename,
                                                 sig_package))

        else:
            raise ExternalSignerError(
                self.MESG_ASKUSERTOSIGN.format(image_tosign_filename,
                                               cert_folder))

        signer_output = self._get_signer_output(signature, cert_chain_list)

        self._cleanup(cert_folder)

        return signer_output
Beispiel #3
0
    def dump_parsegen_debug_data(self, image, parsegen):
        if image.dest_image.debug_dir_parsegen is None:
            return

        so = parsegen
        fp = image.dest_image
        from imageinfo import DestImagePath
        assert isinstance(fp, DestImagePath)

        debug_logs = []
        try: debug_logs.append((so.get_data(False, False, False), fp.debug_file_parsegen_unsigned))
        except Exception: pass
        try: debug_logs.append((so.data_to_sign, fp.debug_file_parsegen_tosign))
        except Exception: pass
        try: debug_logs.append((so.cert_chain, fp.debug_file_parsegen_cert_chain))
        except Exception: pass
        try: debug_logs.append((so.data_signature, fp.debug_file_parsegen_signature))
        except Exception: pass
        try: debug_logs.append((so.get_data(True, False, False), fp.debug_file_parsegen_integrity_check))
        except Exception: pass
        try: debug_logs.append((so.get_data(True, True, False), fp.debug_file_parsegen_signed))
        except Exception: pass
        try: debug_logs.append((so.get_data(True, True, True), fp.debug_file_parsegen_encrypted))
        except Exception: pass

        for data, debug_file in debug_logs:
            try: store_data_to_file(debug_file, data)
            except Exception: logger.debug2('Failed to save debug file ' + debug_file + '\n'
                                            '    ' + str(sys.exc_info()[1]))
    def _sign(self, binary_to_sign,
                    image_tosign_filename, cert_folder):

        c_path.create_dir(cert_folder)

        c_misc.store_data_to_file(image_tosign_filename, binary_to_sign)
        sig_package = signerutils.getSigPackage(cert_folder)
        if sig_package is not None:
            [signature, cert_chain_list] = signerutils.\
                                        readSigFromZip(sig_package)
            if self.validate_sig(binary_to_sign, signature,
                                        cert_chain_list) is False:
                raise ExternalSignerError(
                        self.MESG_INVALID_SIG.
                                    format(image_tosign_filename, sig_package))

        else:
            raise ExternalSignerError(
                    self.MESG_ASKUSERTOSIGN.
                                format(image_tosign_filename, cert_folder))

        signer_output = self._get_signer_output(signature, cert_chain_list)

        self._cleanup(cert_folder)

        return signer_output
Beispiel #5
0
    def dump_signer_debug_data(self, image, sign_assets):
        if image.dest_image.debug_dir_signer is None:
            return
        c_path.create_debug_dir(image.dest_image.debug_dir_signer)

        sa = sign_assets
        fp = image.dest_image
        from imageinfo import DestImagePath
        assert isinstance(fp, DestImagePath)

        debug_logs = [
            (sa.root_cert, fp.debug_file_signer_root_cert),
            (sa.attestation_ca_cert, fp.debug_file_signer_attestation_ca_cert),
            (sa.attestation_cert, fp.debug_file_signer_attestation_cert),
            (sa.signature, fp.debug_file_signer_signature),
            (sa.cert_chain, fp.debug_file_signer_cert_chain)
        ]

        # Save the private attributes too
        debug_logs += [
            (sa.root_key, fp.debug_file_signer_root_key),
            (sa.attestation_ca_key, fp.debug_file_signer_attestation_ca_key),
            (sa.attestation_key, fp.debug_file_signer_attestation_key)
        ]

        for data, debug_file in debug_logs:
            try:
                store_data_to_file(debug_file, data)
            except Exception:
                logger.debug2('Failed to save debug file ' + debug_file + '\n'
                              '    ' + str(sys.exc_info()[1]))
    def dump_parsegen_debug_data(self, image, parsegen):
        if image.dest_image.debug_dir_parsegen is None:
            return

        so = parsegen
        fp = image.dest_image
        from imageinfo import DestImagePath
        assert isinstance(fp, DestImagePath)

        debug_logs = []
        try: debug_logs.append((so.get_data(False, False, False), fp.debug_file_parsegen_unsigned))
        except Exception: pass
        try: debug_logs.append((so.data_to_sign, fp.debug_file_parsegen_tosign))
        except Exception: pass
        try: debug_logs.append((so.cert_chain, fp.debug_file_parsegen_cert_chain))
        except Exception: pass
        try: debug_logs.append((so.data_signature, fp.debug_file_parsegen_signature))
        except Exception: pass
        try: debug_logs.append((so.get_data(True, False, False), fp.debug_file_parsegen_integrity_check))
        except Exception: pass
        try: debug_logs.append((so.get_data(True, True, False), fp.debug_file_parsegen_signed))
        except Exception: pass
        try: debug_logs.append((so.get_data(True, True, True), fp.debug_file_parsegen_encrypted))
        except Exception: pass

        for data, debug_file in debug_logs:
            try: store_data_to_file(debug_file, data)
            except Exception: logger.debug2('Failed to save debug file ' + debug_file + '\n'
                                            '    ' + str(sys.exc_info()[1]))
    def _pil_split(self, src, prefix):
        from sectools.common.parsegen.elf.format import ParseGenElf, pack_phdrs, PF_OS_SEGMENT_HASH

        # Load the data
        p_obj = ParseGenElf(load_data_from_file(src))

        # File names
        elfhdr = prefix + '.mdt'

        # Cleanup
        for eachpattern in [elfhdr, (prefix + '.b*')]:
            import glob
            for eachfile in glob.glob(eachpattern):
                try: os.remove(eachfile)
                except Exception: pass

        # Create the mdt data
        elfdata = p_obj.ehdr.pack() + pack_phdrs(p_obj.phdrs)

        # Dump the segments
        for idx, phdr in enumerate(p_obj.phdrs):
            path = prefix + ('.b%02d' % idx)
            store_data_to_file(path, p_obj.segments[phdr])
            if phdr.f_os_segment_type == PF_OS_SEGMENT_HASH:
                elfdata += p_obj.segments[phdr]

        # Dump the final elfhdr mdt
        store_data_to_file(elfhdr, elfdata)
Beispiel #8
0
    def pil_split(src, prefix):
        from sectools.common.parsegen.elf.format import ParseGenElf, pack_phdrs, PF_OS_SEGMENT_HASH

        # Load the data
        p_obj = ParseGenElf(load_data_from_file(src))

        # File names
        elfhdr = prefix + '.mdt'

        # Cleanup
        for eachpattern in [elfhdr, (prefix + '.b*')]:
            import glob
            for eachfile in glob.glob(eachpattern):
                try:
                    os.remove(eachfile)
                except Exception:
                    pass

        # Create the mdt data
        elfdata = p_obj.ehdr.pack() + pack_phdrs(p_obj.phdrs)

        # Dump the segments
        for idx, phdr in enumerate(p_obj.phdrs):
            path = prefix + ('.b%02d' % idx)
            store_data_to_file(path, p_obj.segments[phdr])
            if phdr.f_os_segment_type == PF_OS_SEGMENT_HASH:
                elfdata += p_obj.segments[phdr]

        # Dump the final elfhdr mdt
        store_data_to_file(elfhdr, elfdata)
    def _saveResultToFile(self, filename):
        result = self.getResult()

        path, file = os.path.split(filename)
        if not os.path.exists(path):
            os.makedirs(path)

        c_misc.store_data_to_file(filename, result)
    def _saveResultToFile(self, filename):
        result = self.getResult()

        path, file = os.path.split(filename)
        if not os.path.exists(path):
            os.makedirs(path)

        c_misc.store_data_to_file(filename, result)
 def save(self):
     if self.status_code != "1":
         raise ExternalSignerError(
             "Error returned from signature response:\n{0}".format(
                 self._get_tag("Error").text))
     result = self._get_result()
     path, f = os.path.split(self.signature_result_file)
     if not os.path.exists(path):
         os.makedirs(path)
     c_misc.store_data_to_file(self.signature_result_file, result)
Beispiel #12
0
    def dump_signer_debug_data(self, image, sign_assets, parsegen):
        if image.dest_image.debug_dir_signer is None:
            return
        c_path.create_debug_dir(image.dest_image.debug_dir_signer)

        sa = sign_assets
        fp = image.dest_image
        from imageinfo import DestImagePath
        assert isinstance(fp, DestImagePath)

        # Backup parsegen authority
        authority = parsegen.authority

        # QTI Signature and Cert Chain
        parsegen.authority = defines.AUTHORITY_QTI
        data_signature_qti = parsegen.data_signature
        cert_chain_qti = parsegen.cert_chain

        # OEM Signature and Cert Chain
        parsegen.authority = defines.AUTHORITY_OEM
        data_signature = parsegen.data_signature
        cert_chain = parsegen.cert_chain

        # Restore authority
        parsegen.authority = authority

        debug_logs = [
            (sa.root_cert, fp.debug_file_signer_root_cert),
            (sa.attestation_ca_cert, fp.debug_file_signer_attestation_ca_cert),
            (sa.attestation_cert, fp.debug_file_signer_attestation_cert),
            (data_signature, fp.debug_file_signer_signature),
            (cert_chain, fp.debug_file_signer_cert_chain),
            (data_signature_qti, fp.debug_file_signer_qti_signature),
            (cert_chain_qti, fp.debug_file_signer_qti_cert_chain)
        ]

        # Save the private attributes too
        debug_logs += [
            (sa.root_key, fp.debug_file_signer_root_key),
            (sa.attestation_ca_key, fp.debug_file_signer_attestation_ca_key),
            (sa.attestation_key, fp.debug_file_signer_attestation_key)
        ]

        for data, debug_file in debug_logs:
            try:
                store_data_to_file(debug_file, data)
            except Exception:
                logger.debug2('Failed to save debug file ' + debug_file + '\n'
                              '    ' + str(sys.exc_info()[1]))
    def dump_debug_secdat(self, secdat_parser, path):
        """Dumps the secdat related debug data into the output directory.

        :param obj secdat_parser: Parser to dump debug info for
        """
        if not self.debug:
            return

        try:
            debug_dir = c_path.join(path, defines.DEST_DEBUG_DIR)
            c_path.create_dir(debug_dir)
            secdat_repr_log = c_path.join(debug_dir, defines.DEST_DEBUG_FILE_SECDAT_REPR)
            store_data_to_file(secdat_repr_log, repr(secdat_parser))
            logger.info('Dumped debug secdat repr at: ' + secdat_repr_log  + ', date & time: ' + datetime.datetime.now().strftime('%c'))
        except Exception as e:
            logger.warning('Failed to store debug logs: ' + str(e))
    def dump_debug_data_model(self, data_model, path):
        """Dumps the data model related debug data into the output directory.

        :param obj data_model: Data model to dump debug info for
        """
        if not self.debug:
            return

        try:
            debug_dir = c_path.join(path, defines.DEST_DEBUG_DIR)
            c_path.create_dir(debug_dir)
            debug_file = c_path.join(debug_dir, defines.DEST_DEBUG_FILE_DATA_MODEL_REPR.format(self.TOOL_NAME))
            store_data_to_file(debug_file, repr(data_model))
            logger.info('Dumped debug data model repr at: ' + debug_file + ', date & time: ' + datetime.datetime.now().strftime('%c'))
        except Exception as e:
            logger.warning('Failed to store debug logs: ' + str(e))
Beispiel #15
0
    def get_metabuild_log(self):
        data = []
        logdir = os.path.dirname(self.log)
        ufc_log = c_path.join(logdir, UFC_LOG)
        regenerate_log = c_path.join(logdir, REGENERATE_BUID_LOG)
        buildloading_log = c_path.join(logdir, FASTBOOT_COMPLETE_LOG)
        metabuild_log = c_path.join(logdir, META_BUILD_LOG)

        # remove meta build log from previous session
        if c_path.validate_file(metabuild_log):
            os.remove(metabuild_log)

        data.append('Meta build log:\n')

        if c_path.validate_file(ufc_log):
            data.append(SECTION_BREAK)
            data.append('Step 1: UltraFastCopy meta build')
            data.append('Meta Build: ' + self.meta_build_path)
            data.append(SECTION_BREAK)
            data.append(load_data_from_file(ufc_log))
        else:
            data.append('meta build copy skipped')
            data.append(SECTION_BREAK)

        if c_path.validate_file(regenerate_log):
            data.append(SECTION_BREAK)
            data.append('Step 2: Meta build regeneration')
            data.append('Meta Build: ' + logdir)
            data.append('Image Build:' + self.image_build_path)
            data.append(SECTION_BREAK)
            data.append(load_data_from_file(regenerate_log))
        else:
            data.append('meta build regeneration skipped')
            data.append(SECTION_BREAK)

        if c_path.validate_file(buildloading_log):
            data.append(SECTION_BREAK)
            data.append('Step 3: Meta build loading')
            data.append('Meta Build: ' + logdir)
            data.append(SECTION_BREAK)
            data.append(load_data_from_file(buildloading_log))

        store_data_to_file(metabuild_log, "\n".join(data))

        return metabuild_log
    def dump_signer_debug_data(self, image, sign_assets):
        if image.dest_image.debug_dir_signer is None:
            return

        sa = sign_assets
        fp = image.dest_image
        from imageinfo import DestImagePath
        assert isinstance(fp, DestImagePath)

        debug_logs = [(sa.root_cert, fp.debug_file_signer_root_cert),
                      (sa.attestation_ca_cert, fp.debug_file_signer_attestation_ca_cert),
                      (sa.attestation_cert, fp.debug_file_signer_attestation_cert),
                      (sa.attestation_key, fp.debug_file_signer_attestation_key),
                      (sa.signature, fp.debug_file_signer_signature),
                      (sa.cert_chain, fp.debug_file_signer_cert_chain)]

        for data, debug_file in debug_logs:
            try: store_data_to_file(debug_file, data)
            except Exception: logger.debug2('Failed to save debug file ' + debug_file + '\n'
                                            '    ' + str(sys.exc_info()[1]))
Beispiel #17
0
    def dump_signer_debug_data(self, image, sign_assets, parsegen, more_debug_logs=[]):
        if image.dest_image.debug_dir_signer is None:
            return
        c_path.create_debug_dir(image.dest_image.debug_dir_signer)

        sa = sign_assets
        fp = image.dest_image
        assert isinstance(fp, self.dest_image_path_class)

        # Backup parsegen authority
        authority = parsegen.authority

        # OEM Signature and Cert Chain
        parsegen.authority = AUTHORITY_OEM
        data_signature = parsegen.data_signature
        cert_chain = parsegen.cert_chain

        # Restore authority
        parsegen.authority = authority

        debug_logs = [(sa.root_cert, fp.debug_file_signer_root_cert),
                      (sa.attestation_ca_cert, fp.debug_file_signer_attestation_ca_cert),
                      (sa.attestation_cert, fp.debug_file_signer_attestation_cert),
                      (data_signature, fp.debug_file_signer_signature),
                      (cert_chain, fp.debug_file_signer_cert_chain)]

        for dbg_log in more_debug_logs:
            debug_logs.append((dbg_log[0], getattr(fp, dbg_log[1])))

        # Save the private attributes too
        debug_logs += [(sa.root_key, fp.debug_file_signer_root_key),
                       (sa.attestation_ca_key, fp.debug_file_signer_attestation_ca_key),
                       (sa.attestation_key, fp.debug_file_signer_attestation_key)]

        for data, debug_file in debug_logs:
            try:
                store_data_to_file(debug_file, data)
            except Exception:
                logger.debug2('Failed to save debug file ' + debug_file + '\n'
                              '    ' + str(sys.exc_info()[1]))
Beispiel #18
0
    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()
Beispiel #19
0
    def generate(self, sign_id=None):
        """Generate the debugpolicy elf file based on the configs which have been setup.
        """
        # 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(
            version=self._config_parser.root.file_properties.revision,
            debug_dir=debug_dir,
            debug_prefix=debug_prefix,
            debug_suffix=debug_suffix,
            elf_class=self._config_parser.root.file_properties.elf.elf_class)

        # Set version number to be revision number
        dbgpelfparser.dbgpparser.header.version = self._config_parser.root.file_properties.revision

        # Set serial number start and end values
        if not (self._config_parser.root.file_properties.serial_number_start is None or \
                self._config_parser.root.file_properties.serial_number_end is None):
            self.versionAttrCheck(dbgpelfparser.dbgpparser.header,
                                  "set_sernum",
                                  ["serial_number_start", "serial_number_end"])
            dbgpelfparser.dbgpparser.header.set_sernum(
                self._config_parser.root.file_properties.serial_number_start,
                self._config_parser.root.file_properties.serial_number_end)

        # Validate flag bits and set flags
        self.flagBitsCheck(dbgpelfparser.dbgpparser.header.INVALID_FLAG_BITS,
                           self._config_parser.root.file_properties.flags)
        dbgpelfparser.dbgpparser.header.flags = self._config_parser.root.file_properties.flags

        # Set imagebit_map
        if self._config_parser.root.file_properties.image_bit_map is not None:
            self.versionAttrCheck(dbgpelfparser.dbgpparser.header,
                                  "imagebit_map", "image_bit_map")
            dbgpelfparser.dbgpparser.header.imagebit_map = self._config_parser.root.file_properties.image_bit_map

        # Set Image ID Info
        if self._config_parser.root.file_properties.image_id_list is not None:
            self.versionAttrCheck(dbgpelfparser.dbgpparser.header,
                                  "imgid_array", "image_id_list")
            dbgpelfparser.dbgpparser.header.imgid_array = self._config_parser.root.file_properties.image_id_list.image_id

        # Initialize rootcerthash array
        dbgpelfparser.dbgpparser.header.rootcerthash_array = self._config_parser.root.file_properties.root_cert_hash_list.root_cert_hash

        # Set Serial Num List
        if self._config_parser.root.file_properties.serial_num_list is not None:
            self.versionAttrCheck(dbgpelfparser.dbgpparser.header,
                                  "serial_num_array", "serial_num_list")
            dbgpelfparser.dbgpparser.header.serial_num_array = self._config_parser.root.file_properties.serial_num_list.serial_num

        # Initialize rootcerthash_qc array
        if self._config_parser.root.file_properties.root_cert_hash_qc_list is not None:
            self.versionAttrCheck(dbgpelfparser.dbgpparser.header,
                                  "rootcerthash_qc_array",
                                  "root_cert_hash_qc_list")
            dbgpelfparser.dbgpparser.header.rootcerthash_qc_array = self._config_parser.root.file_properties.root_cert_hash_qc_list.root_cert_hash_qc

        # Set physical address
        dbgpelfparser.phys_addr = self._config_parser.root.file_properties.elf.phys_addr

        # Validate header version contents
        dbgpelfparser.dbgpparser.header.validate_ranges()

        dbgpelf_data = dbgpelfparser.get_data()
        dp_unsigned = c_path.join(self.output_dir, 'dp_unsigned.mbn')
        store_data_to_file(dp_unsigned, dbgpelf_data)
        logger.info('Generated unsigned debugpolicy elf file at: ' +
                    dp_unsigned + ', date & time: ' +
                    datetime.datetime.now().strftime('%c'))
        dp_unsigned_repr = c_path.join(self.output_dir, 'dbgpelf_repr.txt')
        store_data_to_file(dp_unsigned_repr, repr(dbgpelfparser))
        logger.info('Dumped debugpolicy elf repr at: ' + dp_unsigned_repr +
                    ', date & time: ' + datetime.datetime.now().strftime('%c'))

        self.sign(dp_unsigned, sign_id)
Beispiel #20
0
    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:
            tmp_file_path = c_path.create_tmp_file(data=parsegen.get_wrapped_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_file_path)
            image.src_image.image_dir_ext = ''
            image.src_image.image_name = os.path.basename(tmp_file_path)

            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_file_path)

            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 parsegen.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 write_to_file(self, file_path, version, hdr_info=None):
     store_data_to_file(file_path, self.get_data(version, hdr_info))
Beispiel #22
0
    def _process_validation(self,
                            image,
                            progress,
                            security_policy_list,
                            i_val_image,
                            i_val_integrity_check,
                            i_val_sign,
                            i_val_encrypt,
                            idx=0):
        # TODO: Need to figure how to do this
        #image.dest_image._mid = 'validation'

        # 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
        val_image = i_val_image
        val_integrity_check = security_policy_list[
            idx].integrity_check and i_val_integrity_check
        val_sign = security_policy_list[idx].sign and i_val_sign
        val_encrypt = security_policy_list[idx].encrypt and i_val_encrypt

        # 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

        # Update the souce image path
        image.src_image.image_dir_base = os.path.dirname(
            image.image_under_operation)
        image.src_image.image_dir_ext = ''
        image.src_image.image_name = os.path.basename(
            image.image_under_operation)

        try:
            # Create the encryptor object
            encdec = None
            if val_encrypt and image.general_properties.selected_encryptor:
                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.validate_parsegen,
                                                progress, True, image)
            finally:
                image.image_type.file_type = file_type_backup
                image.encdec = encdec_backup

            # Set the security mechanisms
            parsegen.integrity_check = parsegen.contains_integrity_check()
            parsegen.sign = parsegen.is_signed()
            parsegen.encrypt = parsegen.is_encrypted()

            # Dump any debug data
            self.dump_parsegen_debug_data(image, parsegen)

            # Validate parsegen
            if val_image:
                self._status_updater(self._validate_parsegen,
                                     image.status.validate_parsegen, progress,
                                     False, image, parsegen)

            # Validate integrity check
            if val_integrity_check:
                self._status_updater(self._validate_integrity_check,
                                     image.status.validate_integrity_check,
                                     progress, False, image, parsegen)

            # Validate sign
            if val_sign:
                self._status_updater(self._validate_sign,
                                     image.status.validate_sign, progress,
                                     False, image, parsegen)

            # Validate encrypt
            if val_encrypt:
                self._status_updater(self._validate_encrypt,
                                     image.status.validate_encrypt, progress,
                                     False, 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 image_under_operation here
                image_under_operation_int = image.image_under_operation
                image.image_under_operation = tmp_fd.name

                try:
                    self._process_validation(image, progress,
                                             security_policy_list, i_val_image,
                                             i_val_integrity_check, i_val_sign,
                                             i_val_encrypt, idx + 1)
                finally:
                    image.image_under_operation = image_under_operation_int

                os.remove(tmp_fd.name)

        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

        return parsegen
    def _process_validation(self, image, progress, security_policy_list,
                            i_val_image, i_val_integrity_check, i_val_sign, i_val_encrypt, idx=0):
        # TODO: Need to figure how to do this
        #image.dest_image._mid = 'validation'

        # 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
        val_image = i_val_image
        val_integrity_check = security_policy_list[idx].integrity_check and i_val_integrity_check
        val_sign = security_policy_list[idx].sign and i_val_sign
        val_encrypt = security_policy_list[idx].encrypt and i_val_encrypt

        # 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

        # Update the souce image path
        image.src_image.image_dir_base = os.path.dirname(image.image_under_operation)
        image.src_image.image_dir_ext = ''
        image.src_image.image_name = os.path.basename(image.image_under_operation)

        try:
            # Create the encryptor object
            encdec = None
            if val_encrypt:
                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.validate_parsegen,
                                                progress, True,
                                                image)
            finally:
                image.image_type.file_type = file_type_backup
                image.encdec = encdec_backup

            # Set the security mechanisms
            parsegen.integrity_check = parsegen.contains_integrity_check()
            parsegen.sign = parsegen.is_signed()
            parsegen.encrypt = parsegen.is_encrypted()

            # Dump any debug data
            self.dump_parsegen_debug_data(image, parsegen)

            # Validate parsegen
            if val_image:
                self._status_updater(self._validate_parsegen,
                                     image.status.validate_parsegen,
                                     progress, False,
                                     image, parsegen)

            # Validate integrity check
            if val_integrity_check:
                self._status_updater(self._validate_integrity_check,
                                     image.status.validate_integrity_check,
                                     progress, False,
                                     image, parsegen)

            # Validate sign
            if val_sign:
                self._status_updater(self._validate_sign,
                                     image.status.validate_sign,
                                     progress, False,
                                     image, parsegen)

            # Validate encrypt
            if val_encrypt:
                self._status_updater(self._validate_encrypt,
                                     image.status.validate_encrypt,
                                     progress, False,
                                     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 image_under_operation here
                image_under_operation_int = image.image_under_operation
                image.image_under_operation = tmp_fd.name

                try:
                    self._process_validation(image, progress, security_policy_list,
                                             i_val_image, i_val_integrity_check, i_val_sign, i_val_encrypt, idx + 1)
                finally:
                    image.image_under_operation = image_under_operation_int

                os.remove(tmp_fd.name)

        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

        return parsegen
Beispiel #24
0
    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 is_TA(image.signing_attributes.sw_id):
                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
Beispiel #25
0
    def _process_validation(self,
                            image,
                            progress,
                            security_policy_list,
                            i_val_image,
                            i_val_integrity_check,
                            i_val_sign,
                            i_val_encrypt,
                            idx=0,
                            prefix_override=None):
        # TODO: Need to figure how to do this
        #image.dest_image._mid = 'validation'

        # 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
        val_image = i_val_image
        val_integrity_check = security_policy_list[
            idx].integrity_check and i_val_integrity_check
        val_sign = security_policy_list[idx].sign and i_val_sign
        val_encrypt = security_policy_list[idx].encrypt and i_val_encrypt

        # 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

        # Update the souce image path
        image.src_image.image_dir_base = os.path.dirname(
            image.image_under_operation)
        image.src_image.image_dir_ext = ''
        image.src_image.image_name = os.path.basename(
            image.image_under_operation)

        try:
            # 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, True)

            # 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.validate_parsegen,
                                                progress, True, image, True,
                                                False, prefix_override)
            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,
                parsegen.is_encrypted())

            # Prevent validation when using an encrypted key provider
            from sectools.features.isc.encryption_service.unified import encrypted_key_provider_id_supported
            encrypted_key_provider_id = image.signing_attributes.UIE_key
            if parsegen.is_encrypted() and encrypted_key_provider_id_supported(
                    encrypted_key_provider_id):
                raise RuntimeError(
                    "The image is encrypted. Validation is not supported when using an encrypted key provider.\n"
                    "Try again with validation disabled.")

            # Set the security mechanisms
            parsegen.integrity_check = parsegen.contains_integrity_check()
            parsegen.sign = parsegen.is_signed()
            parsegen.encrypt = parsegen.is_encrypted()

            # Validate parsegen
            if val_image:
                self._status_updater(self._validate_parsegen,
                                     image.status.validate_parsegen, progress,
                                     False, image, parsegen)

            # Validate integrity check
            if val_integrity_check:
                self._status_updater(self._validate_integrity_check,
                                     image.status.validate_integrity_check,
                                     progress, False, image, parsegen)

            # Validate sign
            if val_sign:
                self._status_updater(self._validate_sign,
                                     image.status.validate_sign, progress,
                                     False, image, parsegen)

            # Validate encrypt
            if val_encrypt:

                self._status_updater(self._validate_encrypt,
                                     image.status.validate_encrypt, progress,
                                     False, image, parsegen)

            # 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(
                    prefix=security_policy_list[idx + 1].file_type,
                    delete=False)
                tmp_fd.close()
                store_data_to_file(tmp_fd.name, data)

                # Backup the image_under_operation here
                image_under_operation_int = image.image_under_operation
                image.image_under_operation = tmp_fd.name

                # Override debug dumped file prefix
                prefix_override = SecImageCore._get_prefix_override(
                    prefix_override, file_type)

                try:
                    self._process_validation(image, progress,
                                             security_policy_list, i_val_image,
                                             i_val_integrity_check, i_val_sign,
                                             i_val_encrypt, idx + 1,
                                             prefix_override)
                finally:
                    image.image_under_operation = image_under_operation_int

                os.remove(tmp_fd.name)

        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

        return parsegen
Beispiel #26
0
    def _process_secure_operation(self,
                                  image,
                                  progress,
                                  security_policy_list,
                                  i_integrity_check,
                                  i_sign,
                                  i_encrypt,
                                  i_decrypt,
                                  idx=0):
        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 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
Beispiel #27
0
    def _create_parsegen(self, image, progress, security_policy_list, 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.')
        file_type = security_policy_list[idx].file_type

        # 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

        # Update the souce image path
        image.src_image.image_dir_base = os.path.dirname(image.image_under_operation)
        image.src_image.image_dir_ext = ''
        image.src_image.image_name = os.path.basename(image.image_under_operation)

        try:
            # 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=False)
            finally:
                image.image_type.file_type = file_type_backup

            # Set the security mechanisms
            parsegen.integrity_check = parsegen.contains_integrity_check()
            parsegen.sign = parsegen.is_signed()

            # 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(prefix=security_policy_list[idx + 1].file_type, delete=False)
                tmp_fd.close()
                store_data_to_file(tmp_fd.name, data)

                # Backup the image_under_operation here
                image_under_operation_int = image.image_under_operation
                image.image_under_operation = tmp_fd.name

                try:
                    self._create_parsegen(image, progress, security_policy_list, idx + 1)
                finally:
                    image.image_under_operation = image_under_operation_int

                os.remove(tmp_fd.name)

        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

        return parsegen
    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