def __init__(self, image_path, img_config_parser, parsegen_config, authority, sign_id=None, gen_multi_image=False, multi_image_path=None): from sectools.features.isc.parsegen.config.parser import ParsegenCfgParser assert isinstance(image_path, str) assert isinstance(img_config_parser, ConfigParser) assert isinstance(parsegen_config, ParsegenCfgParser) if sign_id is not None: assert isinstance(sign_id, str) # Initialize the BaseStager BaseStager.__init__(self, authority) # Validate that the image path exists image_path = c_path.normalize(image_path) if not c_path.validate_file(image_path): raise RuntimeError('No read access to the image path: ' + image_path) # Put the image info object into the list imageinfo = self._create_imageinfo(img_config_parser, parsegen_config, sign_id, image_path, False) self._image_info_list.append(imageinfo) # Validate that the Multi-Image Sign & Integrity image path exists if multi_image_path is not None: multi_image_path = c_path.normalize(multi_image_path) if not c_path.validate_file(multi_image_path): raise RuntimeError('No read access to the ' + multi_image_string() + ' image path: ' + multi_image_path) # Set sign id to Multi-Image image's sign id sign_id = MULTI_IMAGE_SIGN_ID[authority] # Set the Multi-Image Signing & Integrity image's imageinfo multi_image_imageinfo = self._create_imageinfo( img_config_parser, parsegen_config, sign_id, multi_image_path, False) self._multi_image_imageinfo_dict[ multi_image_imageinfo.chipset] = multi_image_imageinfo # Create image info object for to-be-created Multi-Image Signing and Integrity image elif gen_multi_image: # Set sign id to Multi-Image Sign & Integrity image's sign id sign_id = MULTI_IMAGE_SIGN_ID[authority] # Set the Multi-Image Signing & Integrity image's imageinfo multi_image_imageinfo = self._create_imageinfo( img_config_parser, parsegen_config, sign_id, None, gen_multi_image) self._multi_image_imageinfo_dict[ multi_image_imageinfo.chipset] = multi_image_imageinfo
def _create_imageinfo(self, img_config_parser, parsegen_config, sign_id, image_path, gen_multi_image, src_image=None, dest_image=None): if not gen_multi_image and sign_id not in MULTI_IMAGE_SIGN_ID.values(): # Validate the sign_id sign_id = self._get_sign_id(img_config_parser, os.path.basename(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) else: try: # Get the config block for the Multi-Image Sign & Integrity image img_config_block = img_config_parser.get_config_for_sign_id( sign_id) except: raise RuntimeError(multi_image_string() + " images are not supported for chipset {0}". format(img_config_parser.chipset)) # Create the image info object image_info = ImageInfo(image_path, sign_id, img_config_block, img_config_parser, parsegen_config, gen_multi_image=gen_multi_image, authority=self.authority) image_info.dest_image.image_name = image_info.src_image.image_name # Set src_image if src_image is not None: image_info.src_image = src_image image_info.image_under_operation = image_info.src_image.image_path # Set dest_image if dest_image is not None: image_info.dest_image = dest_image # Check if the dest image name should be overridden if img_config_block.output_file_name is not None: image_info.dest_image.image_name = img_config_block.output_file_name return image_info
def __init__(self, hash_algorithm, data=None, images=None): self._initialize(hash_algorithm, images) # Validate hash algorithm if self.hash_algorithm not in ENCODE_HASH_ALGO: raise RuntimeError( multi_image_string() + " segment does not support configured segment_hash_algorithm {0}" .format(self.hash_algorithm)) # Validate that required information is provided if data is None and not images: raise RuntimeError( "When creating a " + multi_image_string() + " segment at least one of the following must be provided:\n" "\t1) An existing " + multi_image_string() + " segment\n" "\t2) Images to add to (or update) in the " + multi_image_string() + " segment") if data: self._unpack(data) if images: self._update()
def get_multi_image_entry_data(self, authority): logger.debug("Getting data to hash for " + authority + " " + multi_image_string() + " entry") try: if self.is_signed(): return self.data_to_sign else: header = self._mbn_parsegen.header # Copy the MBN header so that masking doesn't alter original header header = copy_header(header) # Mask metadata and sig/cert sizes of other authority header = mask_header_values(header, self.authority) return header.pack() + self._mbn_parsegen.code except: return None
def _update(self): def get_hash(data): from sectools.features.isc.signer.utils.hmac import HMAC h = HMAC.HASH_ALGO_MAP[self.hash_algorithm]() h.update(data) return h.digest() for image in self.images_to_add_or_update: sw_id = int(image.imageinfo.sw_id, 16) app_id = image.imageinfo.app_id app_id_normalized = int(app_id, 16) if app_id is not None else 0 data = image.get_multi_image_entry_data(image.authority) if not data: raise RuntimeError( "Cannot add image entry to " + multi_image_string() + " segment for image with SW_ID={0} because it has no hash segment." .format(hex(sw_id))) # Update existing hash entry if (sw_id, app_id_normalized) in self.image_hash_dict.keys(): if app_id is None: logger.info( "Updated " + multi_image_string() + " entry for image with SW_ID={0}".format(hex(sw_id))) else: logger.info( "Updated " + multi_image_string() + " entry for image with SW_ID={0} and APP_ID={1}". format(hex(sw_id), hex(app_id_normalized))) # Add new hash entry else: if app_id is None: logger.info( "Added " + multi_image_string() + " entry for image with SW_ID={0}".format(hex(sw_id))) else: logger.info( "Added " + multi_image_string() + " entry for image with SW_ID={0} and APP_ID={1}". format(hex(sw_id), hex(app_id_normalized))) self.image_hash_dict[(sw_id, app_id_normalized)] = get_hash(data) if len(self.image_hash_dict) > MAX_NUM_IMAGES: raise RuntimeError( multi_image_string() + " segment cannot contains {0} image entries." "\nMaximum allowed number of images entries is {1}.".format( len(self.image_hash_dict), MAX_NUM_IMAGES))
def _unpack(self, data): # Validate size of segment is not smaller than allowed minimum min_size_of_hash_entry = min(HASH_ALGO_TO_SIZE_MAP.values()) min_size = self._get_fixed_size() + self._get_id_size( ) + min_size_of_hash_entry if len(data) < min_size: raise RuntimeError(multi_image_string() + " segment is of invalid size {0} bytes." "\nMinimum allowed size is {1} bytes.".format( len(data), min_size)) # Extract segment header offset = 0 end = self._get_fixed_size() ( self.magic_number, self.version, self.res0, self.res1, self.res2, self.res3, self.res4, self.res5, self.res6, self.res7, self.res8, self.res9, self.res10, self.res11, self.res12, self.res13, self.res14, self.res15, self.res16, self.res17, self.res18, self.res19, self.res20, self.res21, self.res22, self.res23, self.res24, self.res25, self.res26, self.res27, self.res28, self.res29, self.res30, self.res31, num_images, hash_algorithm, ) = struct.unpack(self._get_fixed_format(), data[offset:end]) # Validate extracted values if self.magic_number != MAGIC_NUM: raise RuntimeError(multi_image_string() + " segment contains invalid magic number {0}." "\nMagic number must be {1}.".format( self.magic_number, MAGIC_NUM)) if self.version != MULT_IMAGE_VERSION_0: raise RuntimeError(multi_image_string() + " segment contains invalid version number {0}." "\nSupported version are: {1}.".format( self.version, SUPPORTED_VERSIONS)) if num_images > MAX_NUM_IMAGES: raise RuntimeError( multi_image_string() + " segment contains {0} image entries." "\nMaximum allowed number of images entries is {1}.".format( num_images, MAX_NUM_IMAGES)) if hash_algorithm not in DECODE_HASH_ALGO: raise RuntimeError( multi_image_string() + " segment contains invalid hash algorithm value {0}." "\nAllowed hash algorithm values are {1}.".format( hash_algorithm, DECODE_HASH_ALGO.keys())) elif DECODE_HASH_ALGO[hash_algorithm] != self.hash_algorithm: raise RuntimeError( multi_image_string() + " segment was created using {0} but segment_hash_algorithm is configured to {1}." "\nChange configured segment_hash_algorithm value to {0}.". format(DECODE_HASH_ALGO[hash_algorithm], self.hash_algorithm)) # Validate segment size expected_size = self._get_fixed_size() + (self._get_id_size( ) + HASH_ALGO_TO_SIZE_MAP[self.hash_algorithm]) * num_images if expected_size < len(data): raise RuntimeError( multi_image_string() + " segment is of invalid size {0} bytes." "\nSegment containing {1} {2} image entries should be {} bytes." .format(len(data), num_images, self.hash_algorithm, expected_size)) # Extract sw_id/app_id and hash values for i in range(num_images): offset = end end += self._get_id_size() ( sw_id, app_id, ) = struct.unpack(self._get_id_format(), data[offset:end]) hash_size = HASH_ALGO_TO_SIZE_MAP[self.hash_algorithm] offset = end end += hash_size image_hash = data[offset:end] self.image_hash_dict[(sw_id, app_id)] = image_hash store_debug_data_to_file(FILE_EXTRACTED, data[0:end], self.debug_dir) store_debug_data_to_file(FILE_EXTRACTED_READABLE, str(self), self.debug_dir)
def print_summary(args, image_info_list, multi_image_imageinfo_list): """Prints the summary of the actions performed by SecImage""" if not image_info_list: return # Check which actions were performed actions = [] multi_image_actions = [] if args.no_op: actions.append('parse') if args.integrity_check: actions.append('integrity_check') if args.sign: actions.append('sign') if args.encrypt: actions.append('encrypt') if args.validate: actions.append('validate') if multi_image_imageinfo_list: if args.m_integrity_check: multi_image_actions.append('integrity_check') if args.m_sign: multi_image_actions.append('sign') if args.m_encrypt: multi_image_actions.append('encrypt') if args.m_validate: multi_image_actions.append('validate') if not (actions + multi_image_actions): return # Figure out the output directory output_print = (('Output is saved at: ' + args.output_dir + '\n') if args.output_dir else ('Minimized build was updated at: ' + args.mini_build + '\n') if args.mini_build else '\n') # Log the actions and output directory actions_str = ('Following actions were performed: "' + ', '.join(actions) + '"' + '\n') if actions else '' multi_image_actions_str = ('Following ' + multi_image_string() + ' actions were performed: "' + ', '.join(multi_image_actions) + '"' + '\n') if multi_image_actions else '' logger.info('SUMMARY:' + '\n' + actions_str + multi_image_actions_str + output_print) # Table information summary_table = TablePrinter([1]) # summary_table = TablePrinter([0]) COLUMN_IDX = 0 COLUMN_SIGN_ID = 1 COLUMN_PARSE = 2 COLUMN_INTEGRITY_CHECK = 3 COLUMN_SIGN = 4 COLUMN_ENCRYPT = 5 COLUMN_VAL_PARSE = 6 COLUMN_VAL_INTEGRITY_CHECK = 7 COLUMN_VAL_SIGN = 8 COLUMN_VAL_ENCRYPT = 9 # First row summary_table.insert_data(0, COLUMN_IDX, 'Idx') summary_table.insert_data(0, COLUMN_SIGN_ID, 'SignId') summary_table.insert_data(0, COLUMN_PARSE, 'Parse') summary_table.insert_data(0, COLUMN_INTEGRITY_CHECK, 'Integrity') summary_table.insert_data(0, COLUMN_SIGN, 'Sign') summary_table.insert_data(0, COLUMN_ENCRYPT, 'Encrypt') summary_table.insert_data(0, COLUMN_VAL_PARSE, 'Validate', column_end=COLUMN_VAL_ENCRYPT) # Second row summary_table.insert_data(1, COLUMN_VAL_PARSE, 'Parse') summary_table.insert_data(1, COLUMN_VAL_INTEGRITY_CHECK, 'Integrity') summary_table.insert_data(1, COLUMN_VAL_SIGN, 'Sign') summary_table.insert_data(1, COLUMN_VAL_ENCRYPT, 'Encrypt') # Data rows for idx, image in enumerate(image_info_list + multi_image_imageinfo_list): idx += 2 summary_table.insert_data(idx, COLUMN_IDX, str(idx - 1) + '.') summary_table.insert_data(idx, COLUMN_SIGN_ID, image.sign_id) summary_table.insert_data(idx, COLUMN_PARSE, image.status.parsegen.state) summary_table.insert_data(idx, COLUMN_INTEGRITY_CHECK, image.status.integrity_check.state) summary_table.insert_data(idx, COLUMN_SIGN, image.status.sign.state) summary_table.insert_data(idx, COLUMN_ENCRYPT, image.status.encrypt.state) summary_table.insert_data(idx, COLUMN_VAL_PARSE, image.status.validate_parsegen.state) summary_table.insert_data(idx, COLUMN_VAL_INTEGRITY_CHECK, image.status.validate_integrity_check.state) summary_table.insert_data(idx, COLUMN_VAL_SIGN, image.status.validate_sign.state) summary_table.insert_data(idx, COLUMN_VAL_ENCRYPT, image.status.validate_encrypt.state) logger.info(summary_table.get_data())
def c_validate(self): """Validates the command line args provided by the user. :raises: RuntimeError if any error occurs. """ args = self.parsed_args err = [] # Check the input files if ((args.image_file and args.meta_build) or (not args.image_file and not args.meta_build)): err.append( 'Provide either image_file or a meta_build for processing.') # Check that m_image_file and meta_build are not both provided if args.meta_build and args.m_image_file: err.append('--m_image_file cannot be provided with meta_build.') err.append('Provide --m_gen flag if ' + multi_image_string() + ' file generation is desired.') # Check that m_gen and m_image_file are not both provided if args.m_gen and args.m_image_file: err.append('Provide either --m_image_file or --m_gen.') # Check that --override flag is not given without help flag if args.overrides and not args.help: err.append( '-h flag must accompany --overrides flag to view overridable properties' ) # Check if the meta build supports sign id meta_supports_sign_id = False if args.meta_build: meta_supports_sign_id = SecImageCore.meta_supports_sign_id( args.meta_build) # Check the configuration option and output dir if args.image_file or (args.meta_build and not meta_supports_sign_id): if ((args.chipset and args.config_path) or (not args.chipset and not args.config_path)): err.append( 'Provide either chipset or a config_path to process images.' ) if not args.output_dir: err.append('Provide the output_dir for storing the output.') elif args.meta_build and not meta_supports_sign_id: if not args.output_dir and not args.mini_build: err.append( 'Provide either output_dir or mini_build for storing the output.' ) if not (args.integrity_check or args.sign or args.encrypt or args.decrypt or args.validate or args.verify_inputs or args.no_op): err.append('Specify one or more operations to perform.') # Check that multi-image operations are enabled when m_gen or m_image_file are provided if args.m_image_file and not (args.m_integrity_check or args.m_sign or args.m_encrypt or args.m_decrypt or args.m_validate): err.append('Specify one or more ' + multi_image_string() + ' image operations to perform.') if args.m_gen and not (args.m_integrity_check or args.m_sign or args.m_encrypt): err.append('Specify one or more ' + multi_image_string() + ' image operations to perform.') # Check that multi-image operations are not enabled when m_gen and m_image_file are missing if not (args.m_gen or args.m_image_file) and ( args.m_integrity_check or args.m_sign or args.m_encrypt or args.m_decrypt or args.m_validate): err.append( 'Provide either --m_image_file or --m_gen when performing ' + multi_image_string() + ' image operations.') # Check that no_op operation is only enabled when m_gen or m_image_file are provided if args.no_op and not (args.m_gen or args.m_image_file): err.append( 'Provide either --m_image_file or --m_gen when adding image entry to ' + multi_image_string() + ' image.') # Check that no_op operation is not provided with any other individual image operations if args.no_op and (args.integrity_check or args.sign or args.encrypt or args.decrypt or args.validate): err.append( 'no_op operation cannot be performed alongside other image operations' ) # Check sign_attr is only set when adding hash table if args.sign_attr and not (args.integrity_check or args.sign): err.append( 'sign_attr operation can only be performed when integrity_check or sign are being performed.' ) # Check m_sign_attr is only set when adding hash table if args.m_sign_attr and not (args.m_integrity_check or args.m_sign): err.append( 'm_sign_attr operation can only be performed when m_integrity_check or m_sign are being performed.' ) # Check other options: if args.rch and not args.validate: err.append( 'Root Cert Hash can only be given when "--validate" operation is provided.' ) # Check and sanitize any paths for read access for path in ['image_file', 'config_path']: path_val = getattr(args, path, None) if path_val: path_val = c_path.normalize(path_val) if not c_path.validate_file(path_val): err.append('Cannot access ' + path + ' at: ' + path_val) setattr(args, path, path_val) # Check and sanitize any paths for read dir access for path in ['meta_build']: path_val = getattr(args, path, None) if path_val: path_val = c_path.normalize(path_val) if not c_path.validate_dir(path_val): err.append('Cannot access ' + path + ' at: ' + path_val) setattr(args, path, path_val) # Check and sanitize paths for write access for path in ['output_dir', 'mini_build']: path_val = getattr(args, path, None) if path_val: path_val = c_path.normalize(path_val) try: c_path.create_dir(path_val) except Exception as e: err.append('Cannot write at: ' + path_val + '\n' ' ' + 'Error: ' + str(e)) setattr(args, path, path_val) # Raise error if any if err: if len(err) > 1: err = [(' ' + str(idx + 1) + '. ' + error) for idx, error in enumerate(err)] err = 'Please check the command line args:\n\n' + '\n'.join( err) else: err = err[0] raise RuntimeError(err)
def c_add_options(self): """Adds the command line args supported by secimage.""" # Signing individual image img_group = self.add_option_group('Signing individual image') img_group.add_option('--overrides', action='store_true', help=optparse.SUPPRESS_HELP) img_group.add_option('-i', '--image_file', metavar='<file>', help='path to the image file.') img_group.add_option( '-g', '--sign_id', metavar='<id>', help='sign id corresponding to the image_file provided.') img_group.add_option( '-p', '--chipset', metavar='<id>', help='id of the chipset corresponding to the image_file.') img_group.add_option('-c', '--config_path', metavar='<file>', help='path to the secimage config file.') img_group.add_option('--qti_signing', action='store_true', default=False, help=optparse.SUPPRESS_HELP) # Signing metabuild meta_group = self.add_option_group('Signing images from metabuild') meta_group.add_option( '-m', '--meta_build', metavar='<dir>', help= 'path to the meta-build to be used for obtaining the images to sign.' ) # Specifying the output location output_group = self.add_option_group('Specifying output location') output_group.add_option( '-o', '--output_dir', metavar='<dir>', help='directory to store output files. DEFAULT: "./' + DEF_SECIMAGE_OUTPUT_DIR_NAME + '"', default=DEF_SECIMAGE_OUTPUT_DIR_PATH) output_group.add_option( '-n', '--mini_build', metavar='<dir>', help='path to the minimized build to store the signed images to. ' 'This option works with the meta_build option.') # Specifying the operation operations_group = self.add_option_group( 'Operations for individual images') operations_group.add_option('-t', '--integrity_check', action='store_true', default=False, help='add hash table segment.') operations_group.add_option( '-r', '--sign_attr', action='store_true', default=False, help= 'add signing attributes to hash table segment of unsigned Secboot 3.0 image.' ) operations_group.add_option('-s', '--sign', action='store_true', default=False, help='sign the image.') operations_group.add_option('-e', '--encrypt', action='store_true', default=False, help='encrypt the image.') operations_group.add_option('--decrypt', action='store_true', default=False, help=optparse.SUPPRESS_HELP) operations_group.add_option('-a', '--validate', action='store_true', default=False, help='validate the image.') operations_group.add_option( '--no_op', action='store_true', default=False, help= 'perform no operations on individual image when adding entry to ' + multi_image_string() + ' image.') operations_group.add_option('-l', '--verify_inputs', action='store_true', default=False, help='verify the command line options.') # Multi-Image Sign & Integrity image operations multi_image_group = self.add_option_group( 'Operations for ' + multi_image_string() + ' images\n' + ' (to be used when adding or updating image entries in ' + multi_image_string() + ' image)') multi_image_group.add_option('--m_gen', action='store_true', default=False, help='generate a new ' + multi_image_string() + ' image.') multi_image_group.add_option('--m_image_file', metavar='<file>', help='path to an existing ' + multi_image_string() + ' image file.') multi_image_group.add_option('--m_integrity_check', action='store_true', default=False, help='add hash table segment to ' + multi_image_string() + ' image.') multi_image_group.add_option( '--m_sign_attr', action='store_true', default=False, help='add signing attributes to hash table segment of unsigned ' + multi_image_string() + ' image.') multi_image_group.add_option('--m_sign', action='store_true', default=False, help='sign the ' + multi_image_string() + ' image.') multi_image_group.add_option('--m_encrypt', action='store_true', default=False, help='encrypt the ' + multi_image_string() + ' image.') multi_image_group.add_option('--m_decrypt', action='store_true', default=False, help=optparse.SUPPRESS_HELP) multi_image_group.add_option('--m_validate', action='store_true', default=False, help='validate the ' + multi_image_string() + ' image.') # Other options other_group = self.add_option_group('Other options') other_group.add_option( '--rch', '--root_cert_hash', metavar='<hash>', help= 'root cert hash to validate the signed image cert chain against. ' 'This option can only be used with the validate operation.') # Populate override options for tag, override in self.overrides.get_properties().items(): operations_group.add_option('--' + self.override_prefix + tag, metavar='<' + override.type_str + '_value>', help=optparse.SUPPRESS_HELP) # Populate special override options for tag, override in self.spec_overrides.get_properties().items(): operations_group.add_option('--' + self.spec_override_prefix + tag, metavar='<' + override.type_str + '_value>', help=optparse.SUPPRESS_HELP)
def _validate_properties(self): self.errors = [] sa = self.signing_attributes if not POLICY_OEM_ID_0.is_ignore(): if int(sa.oem_id, 16) == 0: POLICY_OEM_ID_0.run('OEM ID is set to 0 for sign_id "' + str(self.sign_id) + '"') # Secboot v1 requires oem permissions only if sa.secboot_version == SECBOOT_VERSION_1_0: if not sa.oem_sign: # oem_sign cannot be false for secboot v1 self._add_error( 'OEM operations cannot be disabled for a secboot version ' + str(SECBOOT_VERSION_1_0) + ' image.') if sa.qti_sign: # qti_sign cannot be true for secboot v1 self._add_error( 'Cannot perform QTI operations on a secboot version ' + str(SECBOOT_VERSION_1_0) + ' image.') # If all authority permissions are disabled, throw error elif not sa.qti_sign and not sa.oem_sign: self._add_error( 'Cannot perform image operations because OEM and QTI operations are disabled for image.' ) # Raise warnings for Secboot v2.1 and greater chipsets if self.chipset in SECBOOT_2_0_DOUBLE_SIGN_CHIPSETS + SECBOOT_3_0_DOUBLE_SIGN_CHIPSETS: if sa.rot_en is not None and int(sa.rot_en, 16) == 1: logger.warning( "rot_en should not be set to \"{0}\" for chipset \"{1}\".". format(sa.rot_en, self.chipset)) if sa.hash_algorithm == "sha1": logger.warning( "hash_algorithm should not be set to \"{0}\" for chipset \"{1}\"." .format(sa.hash_algorithm, self.chipset)) if sa.exponent == 3: logger.warning( "exponent should not be set to \"{0}\" for chipset \"{1}\"." .format(sa.exponent, self.chipset)) if sa.dsa_type == "ecdsa": if sa.rsa_padding is not None: logger.warning( "rsa_padding should not be set for chipset \"{0}\" when ECDSA signing." .format(self.chipset)) logger.warning( "rsa_padding and hmac will be ignored.".format( self.chipset)) sa.rsa_padding = None sa.hmac = None else: if sa.rsa_padding is None or sa.rsa_padding == "pkcs": logger.warning( "rsa_padding should not be set to RSAPKCS for chipset \"{0}\"." .format(self.chipset)) # Ignore max_num_root_certs value if target is not MRC v2.0 double sign target if not (self.chipset in MRC_2_0_CHIPSETS and sa.qti_sign and sa.oem_sign): sa.max_num_root_certs = None if self.is_multi_image and sa.multi_image_segment_phys_addr is None: self._add_error( multi_image_string() + " operation requires multi_image_segment_phys_addr config value." ) # Based on secboot_version allowed formats differ for sw_id, anti_rollback_version, rot_en, uie_key_switch_enable, root_revoke_activate_enable, & debug. # Validation must happen outside of rule.py because images of different secboot versions can coexist in the same config file. # Only Secboot 3 supports anti_rollback_version as its own value if sa.secboot_version == SECBOOT_VERSION_3_0: if sa.anti_rollback_version is None: self._add_error( "Secboot {0} requires anti_rollback_version field.".format( sa.secboot_version)) if (int(sa.sw_id, 16) & 0xFFFFFFFF00000000) != 0: self._add_error( "Provide anti-rollback version in anti_rollback_version field for secboot {0} chipset." .format(sa.secboot_version)) self._add_error( "sw_id value {0} exceeds maximum allowed length of 10 characters." .format(sa.sw_id)) if sa.anti_rollback_version is not None and (int( sa.anti_rollback_version, 16) & 0xFFFFFFFF00000000) != 0: self._add_error( "anti_rollback_version value {0} exceeds maximum allowed length of 10 characters." .format(sa.anti_rollback_version)) # sha1 is disallowed for Secboot 3 if sa.hash_algorithm == "sha1": self._add_error( "sha1 hash_algorithm is not allowed for secboot {0} images." .format(sa.secboot_version)) if sa.segment_hash_algorithm == "sha1": self._add_error( "sha1 segment_hash_algorithm is not allowed for secboot {0} images." .format(sa.secboot_version)) # rot_en rule, LSB 32bits must not be greater than 1 multi_serial_numbers = sa.multi_serial_numbers.serial if sa.multi_serial_numbers is not None else [] self._validate_serial_bound_value( sa.rot_en, "rot_en", self.chipset, ignore_num_root_certs=True, disable_in_value_binding=sa.secboot_version == SECBOOT_VERSION_3_0, additional_serials_are_bindable=len(multi_serial_numbers) > 0, allowed_lsb_values=[0, 1]) # Validate uie_key_switch_enable self._validate_serial_bound_value( sa.uie_key_switch_enable, "uie_key_switch_enable", self.chipset, ignore_num_root_certs=True, disable_in_value_binding=sa.secboot_version == SECBOOT_VERSION_3_0, additional_serials_are_bindable=len(multi_serial_numbers) > 0) # MRC 1.0 use case # Validate revocation_enablement self._validate_serial_bound_value(sa.revocation_enablement, "revocation_enablement", self.chipset, MRC_1_0_CHIPSETS, sa.num_root_certs) # Validate activation_enablement self._validate_serial_bound_value(sa.activation_enablement, "activation_enablement", self.chipset, MRC_1_0_CHIPSETS, sa.num_root_certs) # MRC 2.0 use case # Validate root_revoke_activate_enable self._validate_serial_bound_value( sa.root_revoke_activate_enable, "root_revoke_activate_enable", self.chipset, MRC_2_0_CHIPSETS, sa.num_root_certs, disable_in_value_binding=sa.secboot_version == SECBOOT_VERSION_3_0, additional_serials_are_bindable=len(multi_serial_numbers) > 0) self._validate_serial_bound_value( sa.debug, "debug", self.chipset, ignore_num_root_certs=True, disable_in_value_binding=sa.secboot_version == SECBOOT_VERSION_3_0, additional_serials_are_bindable=len(multi_serial_numbers) > 0, allowed_lsb_values=[0, 2, 3] if sa.secboot_version != SECBOOT_VERSION_3_0 else None) if self.errors: raise RuntimeError("".join(self.errors))
import os import defines from cfgparser import ConfigParser from cfgparser import defines as cfgdef from sectools.common.utils import c_path from sectools.common.utils.c_base import ValPolicy from sectools.common.utils.c_logging import logger from sectools.common.utils.c_misc import multi_image_string from sectools.features.isc import defines from sectools.features.isc.cfgparser.defines import JTAGID_SIGN_IDS, MRC_1_0_CHIPSETS, MRC_2_0_CHIPSETS, SECBOOT_2_0_DOUBLE_SIGN_CHIPSETS, SECBOOT_3_0_DOUBLE_SIGN_CHIPSETS, SECBOOT_1_IMAGE_TYPES from sectools.features.isc.defines import SECBOOT_VERSION_1_0, SECBOOT_VERSION_3_0 POLICY_OEM_ID_0 = ValPolicy(ValPolicy.WARN) MULTI_IMAGE_FILENAME = multi_image_string() + " image" OEM_MULTI_IMAGE_SIGN_ID = "multi_image" QTI_MULTI_IMAGE_SIGN_ID = "multi_image_qti" MULTI_IMAGE_SIGN_ID = { defines.AUTHORITY_OEM: OEM_MULTI_IMAGE_SIGN_ID, defines.AUTHORITY_QTI: QTI_MULTI_IMAGE_SIGN_ID, } class ImagePath(object): def __init__(self, image_path=''): self._image_dir_base = os.path.dirname(image_path) self._image_dir_ext = '' self._image_name = os.path.basename(image_path) @property