def get_scons_targets(input): # initialize target lists integrity_targets = list() sign_targets = list() encrypt_targets = list() sign_and_encrypt_targets = list() scons_targets = [integrity_targets, sign_targets, encrypt_targets, sign_and_encrypt_targets] pilsplit_files_to_clean = list() # get chipset and filename of input file chipset = SecImageConfigParser(input.config).root.metadata.get_chipset() path, filename = os.path.split(input.source) if input.build_policy: for policy in input.build_policy.sec_image_policies: target_list_to_append_to = scons_targets[target_map[policy.cmd_options]] # get path to installed image if input.sectools_install_base_dir: for install_location in policy.install_locations: if input.install_file_name: target = c_path.join(install_location, input.install_file_name) else: target = c_path.join(install_location, filename) logger.debug("Added to-be-installed file \"{0}\" to SCons target list".format(target)) target_list_to_append_to.append(target) # determine pilsplit images to cleanup if input.pilsplitter_target_base_dir: if install_location != input.sectools_install_base_dir: pilsplit_directory = c_path.join(input.pilsplitter_target_base_dir, install_location.replace(os.path.join(input.sectools_install_base_dir, "", ""), "")) else: pilsplit_directory = input.pilsplitter_target_base_dir if c_path.validate_dir_write(pilsplit_directory): pilsplit_filename = input.install_file_name.split(".")[0] if input.install_file_name else filename.split(".")[0] # get all pil files in pilsplit target directory regex = r"^" + re.escape(pilsplit_filename) + r"\.((mdt)|(b[0-9][0-9]))$" pil_files = [c_path.join(pilsplit_directory, f) for f in os.listdir(pilsplit_directory) if re.match(regex, f)] for pil_file in pil_files: logger.debug("Added pilsplit file \"{0}\" to SCons clean list".format(pil_file)) pilsplit_files_to_clean.append(pil_file) # get path to uninstalled image if no installation is requested else: uninstalled_target = c_path.normalize(c_path.join(input.target_base_dir, policy.id, chipset, input.sign_id, filename)) target_list_to_append_to.append(uninstalled_target) logger.debug("Added file \"{0}\" to SCons target list".format(uninstalled_target)) # remove duplicates from lists for i, targets in enumerate(scons_targets): scons_targets[i] = remove_duplicates(targets) pilsplit_files_to_clean = remove_duplicates(pilsplit_files_to_clean) # clean pilsplit files input.environment.Clean(scons_targets, pilsplit_files_to_clean) # return target list return scons_targets
def __init__(self, binary_data, binary_data_format): self._data = binary_data self._format = binary_data_format[0] self._fields = list(binary_data_format[1]) if len(self.fields) != len(remove_duplicates(self.fields)): raise RuntimeError("Fields must not contain duplicates") if len(self.fields) != len(re.sub("[@=<>!0-9]", "", self.format)): raise RuntimeError("Number of fields must match the number of structures defined by format string") if len(self.binary_data) < calcsize(self.format): raise RuntimeError("Length of data must be greater than or equal to length specified by format string") super(StructDynamic, self).__init__(self.format)
def validate(self, images, *args): assert(isinstance(images, complex_images_list)) image_list = images.get_image() retval = [True] errors = [] def add_error(sign_id, error): retval[0] = False errors.append("\nsign_id={0}: ".format(sign_id) + error) # expect args[0] to be instance of signing assert(isinstance(args[0], complex_general_properties)) assert(isinstance(args[1], complex_metadata)) general_properties = args[0] # Not Overridable use_serial_number_in_signing =\ general_properties.get_use_serial_number_in_signing() attributes = dict( hash_algorithm=general_properties.get_hash_algorithm(), hmac=general_properties.get_hmac(), rsa_padding=general_properties.get_rsa_padding(), num_root_certs=general_properties.get_num_root_certs(), secboot_version=general_properties.get_secboot_version(), dsa_type=general_properties.get_dsa_type(), key_size=general_properties.get_key_size(), exponent=general_properties.get_exponent()) # Overridable default_debug = general_properties.get_debug() default_sw_id = general_properties.get_sw_id() default_oem_id = general_properties.get_oem_id() default_model_id = general_properties.get_model_id() default_msm_part = general_properties.get_msm_part() default_soc_hw_version = general_properties.get_soc_hw_version() default_in_use_soc_hw_version = general_properties.get_in_use_soc_hw_version() for image in image_list: sign_id = image.get_sign_id() overrides = image.get_general_properties_overrides() # Update all the overridable attributes for attr in defines.CONFIG_STRUCTURE["images_list"]["image"][0][ "general_properties_overrides"].keys(): attr_override = getattr(overrides, "get_" + attr)() if attr_override is None: attributes[attr] = locals()["default_" + attr] else: attributes[attr] = attr_override return retval[0], "".join(remove_duplicates(errors))
def compare_lists(self, config_attr, attr, dup_in_cert_is_error, missing_is_error): is_multi_serial_numbers = attr == 'multi_serial_numbers' if is_multi_serial_numbers: config_list = getattr(config_attr, attr).serial if getattr( config_attr, attr) is not None else [] else: config_list = getattr(config_attr, attr) if getattr( config_attr, attr) is not None else [] cert_list = getattr(self, attr) if getattr(self, attr) is not None else [] # Lower case config items to match case of extracted subject returned by get_subject_list_from_text for index, item in enumerate(config_list): config_list[index] = item.lower() # Lists are empty so they match if config_list == cert_list == []: return True, None, None # Items in config match those in cert cert_without_duplicates = remove_duplicates(cert_list) if len(cert_list) == len(cert_without_duplicates) and set( config_list) == set(cert_without_duplicates): return True, None, None # Lists don't match. Determine which items are duplicated or missing cert_errors = [] config_errors = [] # Determine if duplicates exist in certificate if dup_in_cert_is_error: duplicates = get_duplicates(cert_list) if len(duplicates) > 0: for item in duplicates: config_errors.append('No duplicate') cert_errors.append('Duplicate: ' + item) if missing_is_error: # Determine items in cert that are missing from config for item in cert_list: if item not in config_list: config_errors.append('Missing') cert_errors.append(item) # Determine items in config that are missing from cert for item in config_list: if item not in cert_list: config_errors.append(item) cert_errors.append('Missing') return False, cert_errors, config_errors
def validate(self, images, *args): assert (isinstance(images, complex_images_list)) image_list = images.get_image() retval = [True] errors = [] def add_error(sign_id, error): retval[0] = False errors.append("\nsign_id={0}: ".format(sign_id) + error) def validate_hex_list(sign_id, hex_list, max_num_allowed, list_name, item_name, length_of_item): if len(hex_list) > max_num_allowed: add_error( sign_id, "{0} provided {1}s exceeds allowed maximum of {2}".format( len(hex_list), item_name, max_num_allowed)) for val in hex_list: try: if val[:2] != "0x" or len(val) != length_of_item or (int( val, 16) == 0): raise ValueError("malformed") int(val, 16) except ValueError: add_error( sign_id, "Provided {0} value \"{1}\" is not a valid {2}".format( list_name, val, item_name)) duplicates = get_duplicates(hex_list) if len(duplicates) > 0: if len(duplicates) == 1: error_str = "{0} contains a duplicate of the following value: {1}".format( list_name, ", ".join(duplicates)) else: error_str = "{0} contains duplicates of the following values: ".format( list_name, ", ".join(duplicates)) add_error(sign_id, error_str) # expect args[0] to be instance of signing # the following default signing attributes are checked if signing is TCG assert (isinstance(args[0], complex_general_properties)) general_properties = args[0] default_sw_id = general_properties.get_sw_id() default_app_id = general_properties.get_app_id() default_crash_dump = general_properties.get_crash_dump() default_msm_part = general_properties.get_msm_part() default_soc_hw_version = general_properties.get_soc_hw_version() default_soc_vers = general_properties.get_soc_vers() default_mask_soc_hw_version = general_properties.get_mask_soc_hw_version( ) default_in_use_soc_hw_version = general_properties.get_in_use_soc_hw_version( ) default_use_serial_number_in_signing = general_properties.get_use_serial_number_in_signing( ) default_serial_number = general_properties.get_serial_number() default_oem_id = general_properties.get_oem_id() default_model_id = general_properties.get_model_id() default_debug = general_properties.get_debug() default_multi_serial_numbers = general_properties.get_multi_serial_numbers( ).get_serial() if general_properties.get_multi_serial_numbers( ) is not None else [] default_oid = general_properties.get_object_id() default_oid_min = default_oid.min if default_oid is not None else None default_oid_max = default_oid.max if default_oid is not None else None default_hash_algorithm = general_properties.get_hash_algorithm() default_hmac = general_properties.get_hmac() default_rsa_padding = general_properties.get_rsa_padding() default_num_root_certs = general_properties.get_num_root_certs() default_max_num_root_certs = general_properties.get_max_num_root_certs( ) default_mrc_index = general_properties.get_mrc_index() default_secboot_version = general_properties.get_secboot_version() default_dsa_type = general_properties.get_dsa_type() default_ecdsa_curve = general_properties.get_ecdsa_curve() default_key_size = general_properties.get_key_size() default_exponent = general_properties.get_exponent() default_client_id = general_properties.get_client_id() default_lib_id = general_properties.get_lib_id() default_UIE_server_cert_path = general_properties.get_UIE_server_cert_path( ) assert (isinstance(args[1], complex_metadata)) metadata = args[1] chipset = metadata.get_chipset() for image in image_list: sign_id = image.get_sign_id() image_type = image.get_image_type() overrides = image.get_general_properties_overrides() sw_id = overrides.get_sw_id() if overrides.get_sw_id( ) is not None else default_sw_id app_id = overrides.get_app_id() if overrides.get_app_id( ) is not None else default_app_id crash_dump = overrides.get_crash_dump( ) if overrides.get_crash_dump() is not None else default_crash_dump msm_part = overrides.get_msm_part() if overrides.get_msm_part( ) is not None else default_msm_part soc_hw_version = overrides.get_soc_hw_version( ) if overrides.get_soc_hw_version( ) is not None else default_soc_hw_version soc_vers = overrides.get_soc_vers() if overrides.get_soc_vers( ) is not None else default_soc_vers mask_soc_hw_version = overrides.get_mask_soc_hw_version( ) if overrides.get_mask_soc_hw_version( ) is not None else default_mask_soc_hw_version in_use_soc_hw_version = overrides.get_in_use_soc_hw_version( ) if overrides.get_in_use_soc_hw_version( ) is not None else default_in_use_soc_hw_version use_serial_number_in_signing = overrides.get_use_serial_number_in_signing( ) if overrides.get_use_serial_number_in_signing( ) is not None else default_use_serial_number_in_signing serial_number = overrides.get_serial_number( ) if overrides.get_serial_number( ) is not None else default_serial_number oem_id = overrides.get_oem_id() if overrides.get_oem_id( ) is not None else default_oem_id model_id = overrides.get_model_id() if overrides.get_model_id( ) is not None else default_model_id debug = overrides.get_debug() if overrides.get_debug( ) is not None else default_debug multi_serial_numbers = list(overrides.get_multi_serial_numbers( ).get_serial() if overrides.get_multi_serial_numbers( ) is not None else default_multi_serial_numbers) override_oid = overrides.get_object_id( ) if overrides.get_object_id() is not None else default_oid oid_min = override_oid.min if override_oid is not None else default_oid_min oid_max = override_oid.max if override_oid is not None else default_oid_max hmac = overrides.get_hmac() if overrides.get_hmac( ) is not None else default_hmac hmac = hmac or hmac is None rsa_padding = overrides.get_rsa_padding( ) if overrides.get_rsa_padding( ) is not None else default_rsa_padding hash_algorithm = overrides.get_hash_algorithm( ) if overrides.get_hash_algorithm( ) is not None else default_hash_algorithm num_root_certs = overrides.get_num_root_certs( ) if overrides.get_num_root_certs( ) is not None else default_num_root_certs max_num_root_certs = overrides.get_max_num_root_certs( ) if overrides.get_max_num_root_certs( ) is not None else default_max_num_root_certs mrc_index = overrides.get_mrc_index() if overrides.get_mrc_index( ) is not None else default_mrc_index secboot_version = overrides.get_secboot_version( ) if overrides.get_secboot_version( ) is not None else default_secboot_version dsa_type = overrides.get_dsa_type() if overrides.get_dsa_type( ) is not None else default_dsa_type ecdsa_curve = overrides.get_ecdsa_curve( ) if overrides.get_ecdsa_curve( ) is not None else default_ecdsa_curve key_size = overrides.get_key_size() if overrides.get_key_size( ) is not None else default_key_size exponent = overrides.get_exponent() if overrides.get_exponent( ) is not None else default_exponent client_id = overrides.get_client_id() if overrides.get_client_id( ) is not None else default_client_id lib_id = overrides.get_lib_id() if overrides.get_lib_id( ) is not None else default_lib_id UIE_server_cert_path = overrides.get_UIE_server_cert_path( ) if overrides.get_UIE_server_cert_path( ) is not None else default_UIE_server_cert_path # Secboot version checking if secboot_version is None or ( image_type in SECBOOT_1_IMAGE_TYPES and secboot_version != SECBOOT_VERSION_1_0): # general properties update occurs in imageinfo's _sanitize_general_properties (like for all other config value updates) secboot_version = SECBOOT_VERSION_1_0 if num_root_certs > 1 and secboot_version != SECBOOT_VERSION_1_0 and chipset not in ( SECBOOT_2_0_CHIPSETS + SECBOOT_3_0_CHIPSETS): # Multiple root certs not allowed with secboot 2.0 and greater multi-party signing add_error( sign_id, "Multiple root certs are not supported for secboot {0} chipset {1}." .format(str(secboot_version), chipset)) # Default hash algorithm to sha256 if hash_algorithm is None: hash_algorithm = "sha256" # Backward compatibility: dsa_type is optional, so if it does not exist assume RSA if dsa_type is None: dsa_type = "rsa" # Manually check that ecdsa / rsa arguments exist when the corresponding if dsa_type == "rsa": if exponent is None or key_size is None: add_error( sign_id, "You must specify exponent and key size when using RSA." ) if dsa_type == "ecdsa": general_properties.exponent = None general_properties.key_size = None if ecdsa_curve is None: add_error( sign_id, "You must specify the ecdsa curve when using ECDSA.") # Check that ecdsa value is only used with supported chipset if chipset not in ECDSA_CHIPSETS: add_error( sign_id, "ECDSA is not supported for chipset {0}.".format( chipset)) else: # RSAPSS requires SHA256 or SHA384 if rsa_padding == "pss": if hash_algorithm not in ["sha256", "sha384"]: add_error( sign_id, "RSAPSS requires SHA256 or SHA384 hash. hash_algorithm={0}." .format(hash_algorithm)) if hmac: add_error( sign_id, "RSAPSS cannot be used with HMAC. hmac must be set as False. hmac={0}." .format(hmac)) else: if not hmac: add_error(sign_id, "RSAPKCS should be used with HMAC.") if secboot_version == SECBOOT_VERSION_3_0: # Secboot 3 only support sha256 and sha384 if hash_algorithm not in ["sha256", "sha384"]: add_error( sign_id, "Secboot {0} requires SHA256 or SHA384 hash.".format( secboot_version)) # Secboot 3 HMAC has restriction due to soc_hw_version and other values being removed from MBN header if hmac: if mask_soc_hw_version is not None: add_error( sign_id, "Secboot {0} requires that mask_soc_hw_version not be set when HMAC is set." .format(secboot_version)) if in_use_soc_hw_version == 1: add_error( sign_id, "Secboot {0} requires in_use_soc_hw_version to be set to 0 when HMAC is set." .format(secboot_version)) if use_serial_number_in_signing == 1: if serial_number is None or not multi_serial_numbers: add_error( sign_id, "Secboot {0} requires that serial_number and first serial in multi_serial_numbers match when HMAC and use_serial_number_in_signing are set." .format(secboot_version)) if serial_number is not None and multi_serial_numbers and serial_number != multi_serial_numbers[ 0]: add_error( sign_id, "Secboot {0} requires that serial_number and first serial in multi_serial_numbers match when HMAC and use_serial_number_in_signing are set.\n\t" "serial_number={1} serial={2}".format( secboot_version, serial_number, multi_serial_numbers[0])) # TZ apps rule, must have app_id set if (int(sw_id, 16) & 0xFFFFFFFF) == 0xC: if app_id is None or int(app_id, 16) == 0: add_error( sign_id, "app_id is not set for TZ apps: sw_id={0}.".format( sw_id)) #TODO: app_id is image specific, current rule checking will cover all the images in the config file """ # other than tz, app_id must not be present else: if app_id is not None: retval = False error_str += '\n app_id is set for Non-TZ image: sign_id=%s, sw_id=%s, app_id=%s' % (sign_id, sw_id, app_id) """ # crash_dump rule, LSB 32bits must not be greater than 1 if crash_dump is not None and (int(crash_dump, 16) & 0xFFFFFFFF) > 1: add_error( sign_id, "crash_dump 32bit LSB must be 0 or 1: crash_dump={0}.". format(crash_dump)) if secboot_version == SECBOOT_VERSION_3_0: # msm_part must be provided for secboot 3 images if msm_part is None: add_error( sign_id, "MSM_PART must be used to sign Secboot {0} images but MSM_PART is missing." .format(secboot_version)) # Make sure soc_vers is provided when in_use_soc_hw_version is set to 1 if in_use_soc_hw_version == 1 and soc_vers is None: add_error( sign_id, "IN_USE_SOC_HW_VERSION specifies SOC_VERS is used but SOC_VERS tag is missing." ) else: # At least one of MSM_PART or SOC_HW_VERSION must be specified if msm_part is None and soc_hw_version is None: add_error( sign_id, "MSM_PART and SOC_HW_VERSION are missing from config. At least one must exist." ) # Only use Family and Device number for soc_hw_version: if soc_hw_version is not None and len(soc_hw_version) != 10: add_error( sign_id, "soc_hw_version value {0} is not valid. Value must start with 0x and be 8 bytes." .format(soc_hw_version)) # Check if any sign_ids in SOC-chipset need to sign with JTAG ID if (soc_hw_version is not None) and (chipset in JTAGID_SIGN_IDS) and ( sign_id in JTAGID_SIGN_IDS[chipset]) and (msm_part is None): add_error( sign_id, "MSM_PART must be used to sign this image but MSM_PART is missing." ) # Assure in_use_soc_hw_version exists if both msm_part and soc_hw_version are given if soc_hw_version is not None and msm_part is not None and in_use_soc_hw_version is None: add_error( sign_id, "IN_USE_SOC_HW_VERSION must exist to chose between MSM_PART and SOC_HW_VERSION." ) # in_use_soc_hw_version must exist with soc_hw_version if soc_hw_version is not None and in_use_soc_hw_version is None: add_error( sign_id, "IN_USE_SOC_HW_VERSION must be set when using SOC_HW_VERSION." ) # Make sure in_use_soc_hw_version's specification exists if in_use_soc_hw_version == 1 and soc_hw_version is None: add_error( sign_id, "IN_USE_SOC_HW_VERSION specifies SOC_HW_VERSION is used but SOC_HW_VERSION tag is missing." ) elif in_use_soc_hw_version == 0 and msm_part is None: add_error( sign_id, "IN_USE_SOC_HW_VERSION specifies SOC_HW_VERSION is NOT used but MSM_PART tag is missing." ) # mask_soc_hw_version may only exist if soc_hw_version exists if soc_hw_version is None: if mask_soc_hw_version is not None: add_error( sign_id, "MASK_SOC_HW_VERSION can not exist without the SOC_HW_VERSION tag." ) if mask_soc_hw_version is not None and in_use_soc_hw_version == 1 and self.mask_warning is True: logger.warning( "The mask_soc_hw_version field is set and will mask the soc_hw_version during signing. Please ensure this is the desired result." ) self.mask_warning = False # Validate soc_vers if soc_vers is not None: soc_vers_list = soc_vers.split() validate_hex_list(sign_id, soc_vers_list, MAX_NUM_SOC_VERS_MAP[secboot_version], "soc_vers", "soc_ver", 6) # use_serial_number_in_signing rule: serial number must be set if use_serial_number_in_signing == 1: if serial_number is None or int(serial_number, 16) == 0: add_error( sign_id, "serial_number must be set when use_serial_number_in_signing is enabled." ) elif len(serial_number) > 10: add_error( "sign_id={0}: serial_number value must be 10 characters or less in length" .format(sign_id)) # Ensure MRC targets are properly configured to avoid OU field conflicts misconfigured_mrc_chipsets = get_duplicates(MRC_1_0_CHIPSETS + MRC_2_0_CHIPSETS) if misconfigured_mrc_chipsets: raise RuntimeError( "MRC 1.0 and MRC 2.0 chipsets must be mutually exclusive. The following chipsets are configured incorrectly: {0}." .format(", ".join(misconfigured_mrc_chipsets))) # Validate MRC cert values if chipset in MRC_2_0_CHIPSETS and chipset in SECBOOT_2_0_DOUBLE_SIGN_CHIPSETS + SECBOOT_3_0_DOUBLE_SIGN_CHIPSETS and max_num_root_certs is None: add_error( sign_id, "max_num_root_certs must be provided for chipset \"{0}\".". format(chipset)) # MRC 1.0 support up to 4 roots, MRC 2.0 supports 1 or 4 roots if chipset in MRC_1_0_CHIPSETS + MRC_2_0_CHIPSETS: if max_num_root_certs is not None and num_root_certs > max_num_root_certs: add_error( sign_id, "num_root_certs must be less than or equal to max_num_root_certs: num_root_certs={0}, max_num_root_certs={1}." .format(num_root_certs, max_num_root_certs)) if num_root_certs not in [1, 2, 3, 4]: add_error(sign_id, "num_root_certs must be in range [1-4].") # Legacy MRC supports up to 16 roots elif num_root_certs < 1 or num_root_certs > 16: add_error(sign_id, "num_root_certs must be in range [1-16].") if num_root_certs > 1 and mrc_index is None: add_error( sign_id, "mrc_index must be provided when num_root_certs is greater than 1." ) if mrc_index is not None and mrc_index >= num_root_certs: add_error( sign_id, "Index out of range: mrc_index={0}, num_root_certs={1}.". format(mrc_index, num_root_certs)) # Format and validate debug if debug is not None: if len(debug) > 18: add_error( sign_id, "Debug value must be 18 characters or less in length.") elif secboot_version != SECBOOT_VERSION_3_0 and len( debug) < 18: padding_len = 18 - len(debug) debug = debug[:2] + "0" * padding_len + debug[2:] # Validate the multi_serial_numbers if len(multi_serial_numbers) > 0: if secboot_version == SECBOOT_VERSION_2_0: if debug is None: add_error( sign_id, "Debug serials were provides but debug field was not provided." ) elif debug[:-8] in multi_serial_numbers: add_error( sign_id, "Duplicate serial value of {0} in debug and multi_serial_numbers." .format(debug[:-8])) elif int(debug[:-8], 16) != 0: multi_serial_numbers.append(debug[:-8]) validate_hex_list(sign_id, multi_serial_numbers, MAX_NUM_SERIALS_MAP[secboot_version], "multi_serial_numbers", "serial", 10) # TCG rules if oid_min is not None and oid_max is None: add_error( sign_id, "{0} min is set, must also set max.".format( default_oid.name)) elif oid_max is not None and oid_min is None: add_error( sign_id, "{0} max is set, must also set min.".format( default_oid.name)) elif default_oid is not None: # Move the min > max checking to signer. It should be validated after valid 32 # bit integer is checked. Otherwise, int() conversion will throw an exception oid_min_config_str = oid_min oid_max_config_str = oid_max if oid_min_config_str and oid_max_config_str: oid_min = int(oid_min, 16) if "0x" in oid_min else int(oid_min) oid_max = int(oid_max, 16) if "0x" in oid_max else int(oid_max) if oid_min > oid_max: add_error( sign_id, "{0} min must be less than max, min={1} max={2}.". format(default_oid.name, oid_min_config_str, oid_max_config_str)) if int(sw_id, 16) != 0: add_error( sign_id, "For {0}, sw_id must be 0, sw_id = {1}.".format( default_oid.name, sw_id)) if int(msm_part, 16) != 0: add_error( sign_id, "For {0}, msm_part must be 0, msm_part = {1}.".format( default_oid.name, msm_part)) if int(oem_id, 16) != 0: add_error( sign_id, "For {0}, oem_id must be 0, oem_id = {1}.".format( default_oid.name, oem_id)) if int(model_id, 16) != 0: add_error( sign_id, "For {0}, model_id must be 0, model_id = {1}.".format( default_oid.name, model_id)) if int(debug, 16) != 2: add_error( sign_id, "For {0}, debug must be 2, debug = {1}.".format( default_oid.name, debug)) if client_id is not None and int(client_id, 16) == 0: add_error( sign_id, "client_id must be a non-zero value, client_id={0}.". format(client_id)) if lib_id is not None and int(lib_id, 16) == 0: add_error( sign_id, "lib_id must be a non-zero value, lib_id={0}.".format( lib_id)) if UIE_server_cert_path and c_path.validate_file( UIE_server_cert_path) is False: add_error( sign_id, "UIE_server_cert_path is invalid, path={0}".format( UIE_server_cert_path)) return retval[0], "".join(remove_duplicates(errors))
def validate(self, images, *args): def add_error(sign_id_, error): retval[0] = False errors.append("\nsign_id={0}: ".format(sign_id_) + error) assert (isinstance(images, complex_images_list)) retval = [True] errors = [] # expect args[0] to be instance of signing # the following default signing attributes are checked if signing is TCG assert (isinstance(args[0], complex_general_properties)) general_properties = args[0] defaults = Attributes() for gp_name, gp_instance in vars(defaults).items(): if not isinstance(gp_instance, StandardAttribute): continue setattr(defaults, gp_name, getattr(general_properties, "get_" + gp_name)()) resolve_enumerated(defaults, DEBUG_TAG) default_oid_min = None if defaults.object_id is None else defaults.object_id.min default_oid_max = None if defaults.object_id is None else defaults.object_id.max assert (isinstance(args[1], complex_metadata)) chipset = args[1].get_chipset() for image in images.get_image(): sign_id = image.get_sign_id() overrides = image.get_general_properties_overrides() attributes = Attributes() for gp_name, gp_instance in vars(attributes).items(): if not isinstance(gp_instance, StandardAttribute): continue value = getattr(overrides, "get_" + gp_name)() setattr(attributes, gp_name, getattr(defaults, gp_name) if value is None else value) resolve_enumerated(attributes, DEBUG_TAG) if attributes.object_id is None: oid_min = default_oid_min oid_max = default_oid_max else: oid = attributes.object_id oid_min = oid.min oid_max = oid.max # Sanitize secboot_version if (attributes.secboot_version is None or image.get_image_type() in SECBOOT_1_IMAGE_TYPES): attributes.secboot_version = SECBOOT_VERSION_1_0 self.sanitize_soc_vers(sign_id, attributes, add_error) if (attributes.num_root_certs > 1 and attributes.secboot_version != SECBOOT_VERSION_1_0 and chipset not in (SECBOOT_2_0_CHIPSETS + SECBOOT_3_0_CHIPSETS)): # Multiple root certs not allowed with secboot 2.0 and greater multi-party signing add_error( sign_id, "Multiple root certs are not supported for Secure Boot {0} chipset {1}." .format(str(attributes.secboot_version), chipset)) if attributes.dsa_type == "ecdsa": # Check that ecdsa value is only used with supported chipset if chipset not in ECDSA_CHIPSETS: add_error( sign_id, "ecdsa is not supported for chipset {0}.".format( chipset)) else: # RSAPSS requires SHA256 or SHA384 if attributes.rsa_padding == "pss": if attributes.hash_algorithm not in ["sha256", "sha384"]: add_error( sign_id, "rsapss requires 'sha256' or 'sha384' hash. hash_algorithm={0}." .format(attributes.hash_algorithm)) if attributes.hmac: add_error( sign_id, "rsapss cannot be used with hmac. hmac must be set as False. hmac={0}." .format(attributes.hmac)) else: if not attributes.hmac: add_error(sign_id, "rsapkcs should be used with hmac.") # TZ apps rule, must have app_id set if is_TA(attributes.sw_id): if int(attributes.app_id, 16) == 0: add_error( sign_id, "app_id is not set for TZ apps: sw_id={0}.".format( attributes.sw_id)) # Ensure MRC targets are properly configured to avoid OU field conflicts misconfigured_mrc_chipsets = get_duplicates(MRC_1_0_CHIPSETS + MRC_2_0_CHIPSETS) if misconfigured_mrc_chipsets: raise RuntimeError( "MRC 1.0 and MRC 2.0 chipsets must be mutually exclusive. The following chipsets " "are configured incorrectly: {0}.".format( ", ".join(misconfigured_mrc_chipsets))) # MRC 1.0 support up to 4 roots, MRC 2.0 supports 1 or 4 roots if chipset in MRC_1_0_CHIPSETS + MRC_2_0_CHIPSETS: if attributes.num_root_certs > attributes.max_num_root_certs: add_error( sign_id, "num_root_certs must be less than or equal to max_num_root_certs: " "num_root_certs={0}, max_num_root_certs={1}.".format( attributes.num_root_certs, attributes.max_num_root_certs)) if attributes.num_root_certs not in [1, 2, 3, 4]: add_error(sign_id, "num_root_certs must be in range [1-4].") # Legacy MRC supports up to 16 roots elif attributes.num_root_certs < 1 or attributes.num_root_certs > 16: add_error(sign_id, "num_root_certs must be in range [1-16].") if attributes.mrc_index >= attributes.num_root_certs: add_error( sign_id, "Index out of range: mrc_index={0}, num_root_certs={1}.". format(attributes.mrc_index, attributes.num_root_certs)) # Ensure num_certs_in_certchain does not exceed max_num_certs_in_certchain if attributes.num_certs_in_certchain > attributes.max_num_certs_in_certchain: add_error( sign_id, "num_certs_in_certchain must be less than or equal to max_num_certs_in_certchain: " "num_certs_in_certchain={0}, max_num_certs_in_certchain={1}." .format(attributes.num_certs_in_certchain, attributes.max_num_certs_in_certchain)) # TCG rules if oid_min is not None and oid_max is None: add_error( sign_id, "{0} min is set, must also set max.".format( defaults.object_id.name)) elif oid_max is not None and oid_min is None: add_error( sign_id, "{0} max is set, must also set min.".format( defaults.object_id.name)) elif defaults.object_id is not None: # Move the min > max checking to signer. It should be validated after valid 32 # bit integer is checked. Otherwise, int() conversion will throw an exception oid_min_config_str = oid_min oid_max_config_str = oid_max if oid_min_config_str and oid_max_config_str: oid_min = int( oid_min, 16) if oid_min.startswith("0x") else int(oid_min) oid_max = int( oid_max, 16) if oid_max.startswith("0x") else int(oid_max) if oid_min > oid_max: add_error( sign_id, "{0} min must be less than max, min={1} max={2}.". format(defaults.object_id.name, oid_min_config_str, oid_max_config_str)) if int(attributes.sw_id, 16) != 0: add_error( sign_id, "For {0}, sw_id must be 0, sw_id = {1}.".format( defaults.object_id.name, attributes.sw_id)) if int(attributes.msm_part, 16) != 0: add_error( sign_id, "For {0}, msm_part must be 0, msm_part = {1}.".format( defaults.object_id.name, attributes.msm_part)) if int(attributes.oem_id, 16) != 0: add_error( sign_id, "For {0}, oem_id must be 0, oem_id = {1}.".format( defaults.object_id.name, attributes.oem_id)) if int(attributes.model_id, 16) != 0: add_error( sign_id, "For {0}, model_id must be 0, model_id = {1}.".format( defaults.object_id.name, attributes.model_id)) if int(attributes.debug, 16) != 2: add_error( sign_id, "For {0}, debug must be 2, debug = {1}.".format( defaults.object_id.name, attributes.debug)) if attributes.client_id and int(attributes.client_id, 16) == 0: add_error( sign_id, "client_id must be a non-zero value, client_id={0}.". format(attributes.client_id)) if attributes.lib_id and int(attributes.lib_id, 16) == 0: add_error( sign_id, "lib_id must be a non-zero value, lib_id={0}.".format( attributes.lib_id)) if (attributes.UIE_server_cert_path and c_path.validate_file( attributes.UIE_server_cert_path) is False): add_error( sign_id, "UIE_server_cert_path is invalid, path={0}".format( attributes.UIE_server_cert_path)) return retval[0], "".join(sorted(remove_duplicates(errors)))