Kernel Integrity Measurement Architecture (IMA)

Overview

Introduction to IMA

IMA is a kernel subsystem that measures files accessed through system calls like execve(), mmap(), and open() based on custom policies. These measurements can be used for local or remote attestation or compared against reference values to control file access.

IMA operates in two main modes:

  • Measurement: This mode observes the integrity of files. When protected files are accessed, measurement records are added to the measurement log in kernel memory. If the system has a Trusted Platform Module (TPM), the measurement digest can also be extended into the TPM platform configuration registers (PCRs) to ensure the integrity of the measurement data. This mode does not restrict file access but provides recorded file information to upper-layer applications for remote attestation.
  • Appraisal: This mode verifies file integrity, preventing access to unknown or tampered files. It uses cryptographic methods like hashes, signatures, and hash-based message authentication codes (HMACs) to validate file contents. If verification fails, the file is inaccessible to any process. This feature enhances system resilience by isolating compromised files and preventing further damage during an attack.

In summary, the measurement mode acts as a passive observer, while the appraisal mode enforces strict access control, blocking any file that fails integrity checks.

Introduction to EVM

EVM, or Extended Verification Module, builds on IMA capabilities. While IMA protects file contents, EVM extends this protection to file attributes such as uid, security.ima, and security.selinux.

Introduction to IMA Digest Lists

IMA digest lists enhance the native integrity protection mechanism of the kernel in openEuler, addressing key limitations of the native IMA/EVM mechanism:

File access performance degradation due to extension to TPM

In IMA measurement mode, each measurement requires accessing the TPM. Since the TPM operates at low speeds, typically using the Serial Peripheral Interface (SPI) protocol with clock frequencies in the tens of MHz, system call performance suffers.

File access performance degradation due to asymmetric operations

In IMA appraisal mode, immutable files are protected using a signature mechanism. Each file verification requires signature validation, and the complexity of asymmetric operations further degrades system call performance.

Decreased efficiency and security from complex deployment

In IMA appraisal mode, deployment requires the system to first enter fix mode to mark IMA/EVM extended attributes, then switch to appraisal mode for startup. Additionally, upgrading protected files necessitates rebooting into fix mode to update files and extended attributes. This process reduces deployment efficiency and exposes keys in the runtime environment, compromising security.

IMA digest lists address these issues by managing baseline digest values for multiple files through a single hash list file. This file consolidates the baseline digest values of files (such as all executables in a software package) for centralized management. The baseline digest values can include file content digests (for IMA mode) and file extended attribute digests (for EVM mode). This consolidated file is the IMA digest list file.

When the IMA digest list feature is enabled, the kernel maintains a hash allowlist pool to store digest values from imported IMA digest list files. It also provides interfaces via securityfs for importing, deleting, and querying these files.

In measurement mode, imported digest list files must undergo measurement and extension to TPM before being added to the allowlist pool. If the digest value of a target file matches the allowlist pool, no additional measurement logging or extension to TPM is required. In appraisal mode, imported digest list files must pass signature verification before being added to the allowlist pool. The digest value of the accessed target file is then matched against the allowlist pool to determine the appraisal result.

Compared to the native Linux IMA/EVM mechanism, the IMA digest list extension enhances security, performance, and usability for better practical implementation:

  • Security: IMA digest lists are distributed with software packages. During installation, digest lists are imported simultaneously, ensuring baseline values originate from the software distributor (like the openEuler community). This eliminates the need to generate baseline values in the runtime environment, establishing a complete trust chain.
  • Performance: The IMA digest list mechanism operates on a per-digest-list basis, reducing TPM access and asymmetric operation frequency to 1/n (where n is the average number of file hashes managed by a single digest list). This improves system call and boot performance.
  • Usability: The IMA digest list mechanism supports out-of-the-box functionality, allowing the system to enter appraisal mode immediately after installation. It also enables software package installation and upgrades in appraisal mode without requiring fix mode for file marking, facilitating rapid deployment and seamless updates.

It is worth noting that, unlike the native IMA/EVM, the IMA digest list stores baseline values for measurement/appraisal in kernel memory. This assumes that kernel memory cannot be tampered with by unauthorized entities. Therefore, the IMA digest list relies on additional security mechanisms (including kernel module secure boot and runtime memory measurement) to safeguard kernel memory integrity.

However, both the native IMA mechanism and the IMA digest list extension are only components of the system security chain. Neither can independently ensure system security. Security is inherently a systematic, defense-in-depth engineering effort.

Interface Description

Kernel Boot Parameters

The openEuler IMA/EVM mechanism provides the following kernel boot parameters.

ParameterValueFunction
ima_appraiseenforce-evmEnable IMA appraisal enforce mode (EVM enabled).
log-evmEnable IMA appraisal log mode (EVM enabled).
enforceEnable IMA appraisal enforce mode.
logEnable IMA appraisal log mode.
offDisable IMA appraisal.
ima_appraise_digest_listdigestEnable IMA+EVM appraisal based on digest lists (comparing file content and extended attributes).
digest-nometadataEnable IMA appraisal based on digest lists (comparing file content only).
evmx509Enable portable signature-based EVM directly (regardless of EVM certificate loading)
completePrevent modification of EVM mode via securityfs after boot.
allow_metadata_writesAllow file metadata modifications without EVM interception.
ima_hashsha256/sha1/...Specify the IMA measurement hash algorithm.
ima_templateimaSpecify the IMA measurement template (d or n).
ima-ngSpecify the IMA measurement template (d-ng or n-ng), default template.
ima-sigSpecify the IMA measurement template (d-ng, n-ng, or sig).
ima_policyexec_tcbMeasure all files accessed via execution or mapping, including loaded kernel modules, firmware, and kernel files.
tcbExtend exec_tcb policy to measure files accessed with uid=0 or euid=0.
secure_bootAppraise all loaded kernel modules, firmware, and kernel files, using IMA signature mode.
appraise_exec_tcbExtend secure_boot policy to appraise all files accessed via execution or mapping.
appraise_tcbAppraise all files owned by uid=0.
appraise_exec_immutableUsed with the appraise_exec_tcb policy, making executable file extended attributes immutable.
ima_digest_list_pcr10Extend IMA measurement results based on digest list in PCR 10, disable native IMA measurement.
11Extend IMA measurement results based on digest list in PCR 11, disable native IMA measurement.
+11Extend IMA measurement results based on digest list in PCR 11, extend native IMA measurement results in PCR 10.
ima_digest_db_sizenn[M]Set kernel digest list size limit (0 to 64 MB), defaulting to 16 MB if not configured. ("Not configured" means to omit the parameter, not leaving the value cannot blank like ima_digest_db_size=.)
ima_capacity-1 to 2147483647Set the kernel measurement log entry limit, defaulting to 100,000. -1 means no limit.
initramtmpfsNoneSupport tmpfs in initrd to carry file extended attributes.

Based on user scenarios, the following parameter combinations are recommended:

(1) Native IMA measurement

ini
# Native IMA measurement + custom policy
# No configuration required. This is enabled by default.
# Native IMA measurement + TCB default policy
ima_policy="tcb"

(2) IMA measurement based on digest list

ini
# Digest list IMA measurement + custom policy
ima_digest_list_pcr=11 ima_template=ima-ng initramtmpfs
# Digest list IMA measurement + default policy
ima_digest_list_pcr=11 ima_template=ima-ng ima_policy="exec_tcb" initramtmpfs

(3) IMA appraisal based on digest list, protecting file content only

ini
# IMA appraisal + log mode
ima_appraise=log ima_appraise_digest_list=digest-nometadata ima_policy="appraise_exec_tcb" initramtmpfs
# IMA appraisal + enforce mode
ima_appraise=enforce ima_appraise_digest_list=digest-nometadata ima_policy="appraise_exec_tcb" initramtmpfs

(4) IMA appraisal based on digest list, protecting file content and extended attributes

ini
# IMA appraisal + log mode
ima_appraise=log-evm ima_appraise_digest_list=digest ima_policy="appraise_exec_tcb|appraise_exec_immutable" initramtmpfs evm=x509 evm=complete
# IMA appraisal + enforce mode
ima_appraise=enforce-evm ima_appraise_digest_list=digest ima_policy="appraise_exec_tcb|appraise_exec_immutable" initramtmpfs evm=x509 evm=complete

Note:
All four parameter sets above can be used individually, but only digest list-based measurement and appraisal modes can be combined, such as (2) with (3) or (2) with (4).

securityfs Interface Description

The securityfs interfaces provided by openEuler IMA are located in the /sys/kernel/security directory. Below are the interface names and their descriptions.

PathPermissionsDescription
ima/policy600Display or import IMA policies.
ima/ascii_runtime_measurement440Display IMA measurement logs in ASCII format.
ima/binary_runtime_measurement440Display IMA measurement logs in binary format.
ima/runtime_measurement_count440Display the count of IMA measurement log entries.
ima/violations440Display the number of abnormal IMA measurement logs.
ima/digests_count440Display the total number of digests in the system hash table (IMA+EVM).
ima/digest_list_data200Add digest lists.
ima/digest_list_data_del200Delete digest lists.
evm660Query or set EVM mode.

The /sys/kernel/security/evm interface supports the following values:

  • 0: EVM is not initialized.
  • 1: Use HMAC (symmetric encryption) to verify extended attribute integrity.
  • 2: Use public key signature verification (asymmetric encryption) to verify extended attribute integrity.
  • 6: Disable extended attribute integrity verification.

Digest List Management Tool Description

The digest-list-tools package includes tools for generating and managing IMA digest list files. The primary CLI tools are as follows.

gen_digest_lists

The gen_digest_lists tool allows users to generate digest lists. The command options are defined below.

OptionValueFunction
-d<path>Specify the directory to store the generated digest list files. The directory must be valid.
-fcompactSpecify the format of the generated digest list files. Currently, only the compact format is supported.
-i<option arg>:<option value>Define the target file range for generating digest lists. Specific parameters are listed below.
I:<path>Specify the absolute path of files for which digest lists will be generated. If a directory is specified, recursive generation is performed.
E:<path>Specify paths or directories to exclude.
F:<path>Specify paths or directories to generate digest lists for all files under them (ignores the filtering effect of e: when combined with e:).
e:Generate digest lists only for executable files.
l:policyMatch file security contexts from the SELinux policy instead of reading them directly from file extended attributes.
i:Include the file digest value in the calculated extended attribute information when generating metadata-type digest lists (required).
M:Allow explicit specification of file extended attribute information (requires use with the rpmbuild command).
u:Use the list file name specified by the L: parameter as the name of the generated digest list file (requires use with the rpmbuild command).
L:<path>Specify the path to the list file, which contains the information data required to generate digest lists (requires use with the rpmbuild command).
-oaddSpecify the operation for generating digest lists. Currently, only the add operation is supported, which adds the digest list to the file.
-p-1Specify the position in the file where the digest list will be written. Currently, only -1 is supported.
-tfileGenerate digest lists only for file content.
metadataGenerate digest lists for both file content and extended attributes.
-TN/AIf this option is not used, digest list files are generated. Otherwise, TLV digest list files are generated.
-A<path>Specify the relative root directory to truncate the file path prefix for path matching and SELinux label matching.
-mimmutableSpecify the modifiers attribute for the generated digest list files. Currently, only immutable is supported. In enforce/enforce-evm mode, digest lists can only be opened in read-only mode.
-hN/APrint help information.

Usage examples

  • Scenario 1: Generate a digest list/TLV digest list for a single file.

    shell
    gen_digest_lists -t metadata -f compact -i l:policy -o add -p -1  -m immutable -i I:/usr/bin/ls -d ./ -i i:
    gen_digest_lists -t metadata -f compact -i l:policy -o add -p -1  -m immutable -i I:/usr/bin/ls -d ./ -i i: -T
  • Scenario 2: Generate a digest list/TLV digest list for a single file and specify a relative root directory.

    shell
    gen_digest_lists -t metadata -f compact -i l:policy -o add -p -1  -m immutable -i I:/usr/bin/ls -A /usr/ -d ./ -i i:
    gen_digest_lists -t metadata -f compact -i l:policy -o add -p -1  -m immutable -i I:/usr/bin/ls -A /usr/ -d ./ -i i: -T
  • Scenario 3: Recursively generate a digest list/TLV digest list for files in a directory.

    shell
    gen_digest_lists -t metadata -f compact -i l:policy -o add -p -1  -m immutable -i I:/usr/bin/ -d ./ -i i:
    gen_digest_lists -t metadata -f compact -i l:policy -o add -p -1  -m immutable -i I:/usr/bin/ -d ./ -i i: -T
  • Scenario 4: Recursively generate a digest list/TLV digest list for executable files in a directory.

    shell
    gen_digest_lists -t metadata -f compact -i l:policy -o add -p -1  -m immutable -i I:/usr/bin/ -d ./ -i i: -i e:
    gen_digest_lists -t metadata -f compact -i l:policy -o add -p -1  -m immutable -i I:/usr/bin/ -d ./ -i i: -i e: -T
  • Scenario 5: Recursively generate a digest list/TLV digest list for files in a directory, excluding specific subdirectories.

    shell
    gen_digest_lists -t metadata -f compact -i l:policy -o add -p -1  -m immutable -i I:/usr/ -d ./ -i i: -i E:/usr/bin/
    gen_digest_lists -t metadata -f compact -i l:policy -o add -p -1  -m immutable -i I:/usr/ -d ./ -i i: -i E:/usr/bin/ -T
  • Scenario 6: In an rpmbuild callback script, generate a digest list by reading the list file passed by rpmbuild.

    shell
    gen_digest_lists -i M: -t metadata -f compact -d $DIGEST_LIST_DIR -i l:policy \
        -i i: -o add -p -1 -m immutable -i L:$BIN_PKG_FILES -i u: \
        -A $RPM_BUILD_ROOT -i e: \
        -i E:/usr/src \
        -i E:/boot/efi \
        -i F:/lib \
        -i F:/usr/lib \
        -i F:/lib64 \
        -i F:/usr/lib64 \
        -i F:/lib/modules \
        -i F:/usr/lib/modules \
        -i F:/lib/firmware \
        -i F:/usr/lib/firmware
    
    gen_digest_lists -i M: -t metadata -f compact -d $DIGEST_LIST_DIR.tlv \
        -i l:policy -i i: -o add -p -1 -m immutable -i L:$BIN_PKG_FILES -i u: \
        -T -A $RPM_BUILD_ROOT -i e: \
        -i E:/usr/src \
        -i E:/boot/efi \
        -i F:/lib \
        -i F:/usr/lib \
        -i F:/lib64 \
        -i F:/usr/lib64 \
        -i F:/lib/modules \
        -i F:/usr/lib/modules \
        -i F:/lib/firmware \
        -i F:/usr/lib/firmware

manage_digest_lists

The manage_digest_lists tool is designed to parse and convert binary-format TLV digest list files into a human-readable text format. Below are the command options.

OptionValueFunction
-d<path>Specify the directory containing the TLV digest list files.
-f<filename>Specify the name of the TLV digest list file.
-pdumpDefine the operation type. Currently, only dump is supported, which parses and prints the TLV digest list.
-vN/APrint verbose details.
-hN/ADisplay help information.

Usage example

View TLV digest list information.

ini
manage_digest_lists -p dump -d /etc/ima/digest_lists.tlv/

File Format Description

IMA Policy File Syntax Description

The IMA policy file is a text-based file that can include multiple rule statements separated by newline characters (\n). Each rule statement must begin with an action keyword, followed by one or more filter conditions:

text
<action keyword> <filter condition 1> [filter condition 2] [filter condition 3]...

The action keyword defines the specific action for the policy. Only one action is allowed per policy. Refer to the table below for specific actions (note that the action= prefix can be omitted in practice, for example, use dont_measure instead of action=dont_measure).

Supported filter conditions include:

  • func: indicates the type of file to be measured or appraised. It is typically used with mask. Only one func is allowed per policy.

    • FILE_CHECK can only be paired with MAY_EXEC, MAY_WRITE, or MAY_READ.
    • MODULE_CHECK, MMAP_CHECK, and BPRM_CHECK can only be paired with MAY_EXEC.
    • Other combinations will not take effect.
  • mask: specifies the operation on the file that triggers measurement or appraisal. Only one mask is allowed per policy.

  • fsmagic: represents the hexadecimal magic number of the file system type, as defined in /usr/include/linux/magic.h (by default, all file systems are measured unless excluded using dont_measure or dont_appraise).

  • fsuuid: represents the 16-character hexadecimal string of the system device UUID.

  • objtype: specifies the file security type. Only one file type is allowed per policy. Compared to func, objtype offers finer granularity. For example, obj_type=nova_log_t refers to files with the SELinux type nova_log_t.

  • uid: specifies the user (by user ID) performing the operation on the file. Only one uid is allowed per policy.

  • fowner: specifies the file owner (by user ID). Only one fowner is allowed per policy.

The keywords are detailed as follows.

KeywordValueDescription
actionmeasureEnable IMA measurement.
actiondont_measureDisable IMA measurement.
actionappraiseEnable IMA appraisal.
actiondont_appraiseDisable IMA appraisal.
actionauditEnable auditing.
funcFILE_CHECKFiles to be opened
funcMODULE_CHECKKernel module files to be loaded
funcMMAP_CHECKShared library files to be mapped into process memory
funcBRPM_CHECKFiles to be executed (excluding script files opened via programs like /bin/hash)
funcPOLICY_CHECKIMA policy files to be imported
funcFIRMWARE_CHECKFirmware to be loaded into memory
funcDIGEST_LIST_CHECKDigest list files to be loaded into the kernel
funcKEXEC_KERNEL_CHECKKernel to be switched to using kexec
maskMAY_EXECExecute a file.
maskMAY_WRITEWrite to a file.
maskMAY_READRead a file.
maskMAY_APPENDAppend to a file.
fsmagicfsmagic=xxxHexadecimal magic number representing the file system type
fsuuidfsuuid=xxx16-character hexadecimal string representing the system device UUID
fownerfowner=xxxUser ID of the file owner
uiduid=xxxUser ID of the user performing the operation on the file
obj_typeobj_type=xxx_tFile type based on SELinux labels
pcrpcr=<num>PCR in TPM for extending measurements (defaulting to 10)
appraise_typeimasigIMA appraisal based on signatures
appraise_typemeta_immutableAppraisal based on file extended attributes with signatures (supporting digest lists)

Usage Instructions

Note:
Native IMA/EVM is an open source Linux feature. This section offers a concise overview of its basic usage. For further details, consult the open source wiki: https://sourceforge.net/p/linux-ima/wiki/Home/

Native IMA Usage Instructions

IMA Measurement Mode

To enable IMA measurement, configure the measurement policy.

Step 1: Specify the measurement policy by configuring boot parameters or manually. For example, configure the IMA policy via boot parameters as follows:

ini
ima_policy="tcb"

Alternatively, manually configure the IMA policy like this:

shell
echo "measure func=BPRM_CHECK" > /sys/kernel/security/ima/policy

Step 2: Reboot the system. You can then check the measurement log in real time to monitor the current measurement status:

shell
cat /sys/kernel/security/ima/ascii_runtime_measurements

IMA Appraisal Mode

Enter fix mode, complete IMA labeling for files, and then enable log or enforce mode.

Step 1: Configure boot parameters and reboot to enter fix mode:

ini
ima_appraise=fix ima_policy=appraise_tcb

Step 2: Generate IMA extended attributes for all files requiring appraisal:

For immutable files (such as binary program files), use signature mode to write the signature of the file digest value into the IMA extended attribute. For example (where /path/to/ima.key is the signing private key matching the IMA certificate):

shell
find /usr/bin -fstype ext4 -type f -executable -uid 0 -exec evmctl -a sha256 ima_sign --key /path/to/ima.key '{}' \;

For mutable files (such as data files), use hash mode to write the file digest value into the IMA extended attribute. IMA supports an automatic labeling mechanism, where accessing the file in fix mode will generate the IMA extended attribute:

shell
find / -fstype ext4 -type f -uid 0 -exec dd if='{}' of=/dev/null count=0 status=none \;

To verify if the file has been successfully labeled with the IMA extended attribute (security.ima), use:

shell
getfattr -m - -d /sbin/init

Step 3: Configure boot parameters, switch the IMA appraisal mode to log or enforce, and reboot the system:

ini
ima_appraise=enforce ima_policy=appraise_tcb

IMA Digest List Usage Instructions

Prerequisites

Before using the IMA digest list feature, install the ima-evm-utils and digest-list-tools packages:

shell
yum install ima-evm-utils digest-list-tools

Mechanism Overview

Digest List Files

After installing RPM packages released by openEuler, digest list files are automatically generated in the /etc/ima directory. The following types of files exist:

/etc/ima/digest_lists/0-metadata_list-compact-<RPM_NAME>

This is the IMA digest list file, generated using the gen_digest_lists command (see gen_digest_lists for details). This binary file contains header information and a series of SHA256 hash values, representing the digest values of legitimate file contents and file extended attributes. Once measured or appraised, this file is imported into the kernel, and IMA digest list measurement or appraisal is performed based on the allowlist digest values in this file.

/etc/ima/digest_lists/0-metadata_list-rpm-<RPM_NAME>

This is the RPM digest list file, essentially the header information of the RPM package. After the RPM package is installed, if the IMA digest list file does not contain a signature, the RPM header information is written into this file, and the signature of the header information is written into the security.ima extended attribute. This allows the authenticity of the RPM header information to be verified through the signature. Since the RPM header information includes the digest value of the digest list file, indirect verification of the digest list is achieved.

/etc/ima/digest_lists/0-parser_list-compact-libexec

This is the IMA parser digest list file, storing the digest value of the /usr/libexec/rpm_parser file. This file is used to establish a trust chain from the RPM digest list to the IMA digest list. The kernel IMA digest list mechanism performs special verification on processes generated by this file. If the process is confirmed to be the rpm_parser program, all digest lists imported by it are trusted without requiring signature verification.

/etc/ima/digest_lists.sig/0-metadata_list-compact-<RPM_NAME>.sig

This is the signature file for the IMA digest list. If this file is included in the RPM package, its content is written into the security.ima extended attribute of the corresponding RPM digest list file during the RPM installation phase. This enables signature verification during the IMA digest list import phase.

/etc/ima/digest_lists.tlv/0-metadata_list-compact_tlv-<RPM_NAME>

This is the TLV digest list file, typically generated alongside the IMA digest list file for target files. It stores the integrity information of the target files (such as file content digest values and file extended attributes). The purpose of this file is to assist users in querying or restoring the integrity information of target files.

Digest List File Signing Methods

In IMA digest list appraisal mode, the IMA digest list file must undergo signature verification before it can be imported into the kernel and used for subsequent file whitelist matching. The IMA digest list file supports the following signing methods.

(1) IMA extended attribute signature

This is the native IMA signing mechanism, where the signature information is stored in the security.ima extended attribute in a specific format. It can be generated and added using the evmctl command:

shell
evmctl ima_sign --key /path/to/ima.key -a sha256 <DIGEST_LIST_PATH>

Alternatively, the -f parameter can be added to store the signature and header information in a separate file:

shell
evmctl ima_sign -f --key /path/to/ima.key -a sha256 <DIGEST_LIST_PATH>

When IMA digest list appraisal mode is enabled, you can directly write the path of a a digest list file to the kernel interface to import or delete it. This process automatically triggers appraisal, performing signature verification on the digest list file content based on the security.ima extended attribute:

shell
# Import the IMA digest list file.
echo <DIGEST_LIST_PATH> > /sys/kernel/security/ima/digest_list_data
# Delete the IMA digest list file.
echo <DIGEST_LIST_PATH> > /sys/kernel/security/ima/digest_list_data_del

(2) IMA digest list appended signature (default in openEuler 24.03 LTS)

Starting with openEuler 24.03 LTS, IMA-specific signing keys are supported, and Cryptographic Message Syntax (CMS) signing is used. Since the signature information includes a certificate chain, it may exceed the length limit for the security.ima extended attribute. Therefore, a signature appending method similar to kernel module insertion is adopted:

The signing mechanism is as follows:

  1. Append the CMS signature information to the end of the IMA digest list file.

  2. Fill in the structure and append it to the end of the signature information. The structure is defined as follows:

    c
    struct module_signature {
        u8  algo;       /* Public-key crypto algorithm [0] */
        u8  hash;       /* Digest algorithm [0] */
        u8  id_type;    /* Key identifier type [PKEY_ID_PKCS7] */
        u8  signer_len; /* Length of signer's name [0] */
        u8  key_id_len; /* Length of key identifier [0] */
        u8  __pad[3];
        __be32  sig_len;    /* Length of signature data */
    };
  3. Add the "~Module signature appended~\n" magic string.

A reference script for this step is as follows:

shell
#!/bin/bash
DIGEST_FILE=$1 # Path to the IMA digest list file
SIG_FILE=$2 # Path to save the IMA digest list signature information
OUT=$3 # Output path for the digest list file after adding the signature information

cat $DIGEST_FILE $SIG_FILE > $OUT
echo -n -e "\x00\x00\x02\x00\x00\x00\x00\x00" >> $OUT
echo -n -e $(printf "%08x" "$(ls -l $SIG_FILE | awk '{print $5}')") | xxd -r -ps >> $OUT
echo -n "~Module signature appended~" >> $OUT
echo -n -e "\x0a" >> $OUT

(3) Reusing RPM signatures (default in openEuler 22.03 LTS)

openEuler 22.03 LTS supports reusing the RPM signing mechanism to sign IMA digest list files. This aims to address the lack of dedicated IMA signing keys in the version. Users do not need to be aware of this signing process. When an RPM package contains an IMA digest list file but no IMA digest list signature file, this signing mechanism is automatically used. The core principle is to verify the IMA digest list through the RPM package header information.

For RPM packages released by openEuler, each package file can consist of two parts:

  • RPM header information: Stores RPM package attribute fields, including the package name and file digest list. The integrity of this information is ensured by the RPM header signature.
  • RPM files: The actual files installed into the system, including IMA digest list files generated during the build phase.

During RPM package installation, if the RPM process detects that the digest list file in the package does not contain a signature, it creates an RPM digest list file in the /etc/ima directory, writes the RPM header information into the file content, and writes the RPM header signature into the security.ima extended attribute of the file. This allows indirect verification and import of the IMA digest list through the RPM digest list.

IMA Digest List Import

When IMA measurement mode is enabled, importing IMA digest list files does not require signature verification. The file path can be directly written to the kernel interface to import or delete the digest list:

shell
# Import the IMA digest list file.
echo <DIGEST_LIST_PATH> > /sys/kernel/security/ima/digest_list_data
# Delete the IMA digest list file.
echo <DIGEST_LIST_PATH> > /sys/kernel/security/ima/digest_list_data_del

When IMA appraisal mode is enabled, importing a digest list requires signature verification. Depending on the signing method, there are two import approaches.

Direct import

For IMA digest list files that already contain signature information (IMA extended attribute signature or IMA digest list appended signature), the file path can be directly written to the kernel interface to import or delete the digest list. This process automatically triggers appraisal, performing signature verification on the digest list file content based on the security.ima extended attribute:

shell
# Import the IMA digest list file.
echo <DIGEST_LIST_PATH> > /sys/kernel/security/ima/digest_list_data
# Delete the IMA digest list file.
echo <DIGEST_LIST_PATH> > /sys/kernel/security/ima/digest_list_data_del

Using upload_digest_lists for import

For IMA digest list files that reuse RPM signatures, the upload_digest_lists command must be used for import. The specific commands are as follows (note that the specified path should point to the corresponding RPM digest list):

shell
# Import the IMA digest list file.
upload_digest_lists add <RPM_DIGEST_LIST_PATH>
# Delete the IMA digest list file.
upload_digest_lists del <RPM_DIGEST_LIST_PATH>

This process is relatively complex and requires the following prerequisites:

  1. The system has already imported the digest lists (including IMA digest lists and IMA PARSER digest lists) from the digest_list_tools package released by openEuler.

  2. An IMA appraisal policy for application execution (BPRM_CHECK policy) has been configured.

Operation Guide

Automatic Digest List Generation During RPM Build

The openEuler RPM toolchain supports the %__brp_digest_list macro, which is configured as follows:

text
%__brp_digest_list /usr/lib/rpm/brp-digest-list %{buildroot}

When this macro is configured, the /usr/lib/rpm/brp-digest-list script is invoked when a user runs the rpmbuild command to build a package. This script handles the generation and signing of digest lists. By default, openEuler generates digest lists for critical files such as executables, dynamic libraries, and kernel modules. YOU can also modify the script to customize the scope of digest list generation and specify signing keys. The following example uses a user-defined signing key (/path/to/ima.key) to sign the digest list.

shell
...... (line 66)
DIGEST_LIST_TLV_PATH="$DIGEST_LIST_DIR.tlv/0-metadata_list-compact_tlv-$(basename $BIN_PKG_FILES)"
[ -f $DIGEST_LIST_TLV_PATH ] || exit 0

chmod 644 $DIGEST_LIST_TLV_PATH
echo $DIGEST_LIST_TLV_PATH

evmctl ima_sign -f --key /path/to/ima.key -a sha256 $DIGEST_LIST_PATH &> /dev/null
chmod 400 $DIGEST_LIST_PATH.sig
mkdir -p $DIGEST_LIST_DIR.sig
mv $DIGEST_LIST_PATH.sig $DIGEST_LIST_DIR.sig
echo $DIGEST_LIST_DIR.sig/0-metadata_list-compact-$(basename $BIN_PKG_FILES).sig
IMA Digest List Measurement

Enable IMA digest list measurement using the following steps:

Step 1: Configure the boot parameters to enable IMA measurement. The process is similar to native IMA measurement, but a specific TPM PCR must be configured for measurement. An example boot parameter is as follows:

ini
ima_policy=exec_tcb ima_digest_list_pcr=11

Step 2: Import the IMA digest list. For example, using the digest list of the Bash package:

shell
echo /etc/ima/digest_lists/0-metadata_list-compact-bash-5.1.8-6.oe2203sp1.x86_64 > /sys/kernel/security/ima/digest_list_data

The IMA digest list measurement logs can be queried as follows:

shell
cat /sys/kernel/security/ima/ascii_runtime_measurements

After importing the IMA digest list, if the digest value of the measured file is included in the IMA digest list, no additional measurement logs will be recorded.

IMA Digest List Appraisal
Boot With the Default Policy

You can configure the ima_policy parameter in the boot parameters to specify the IMA default policy. After IMA initialization during kernel startup, the default policy is immediately applied for appraisal. You can enable IMA digest list appraisal using the following steps:

Step 1: Execute the dracut command to write the digest list file into initrd:

shell
dracut -f -e xattr

Step 2: Configure the boot parameters and IMA policy. Typical configurations are as follows:

ini
# IMA appraisal in log/enforce mode based on digest lists, protecting only file content, with the default policy set to appraise_exec_tcb
ima_appraise=log ima_appraise_digest_list=digest-nometadata ima_policy="appraise_exec_tcb" initramtmpfs module.sig_enforce
ima_appraise=enforce ima_appraise_digest_list=digest-nometadata ima_policy="appraise_exec_tcb" initramtmpfs module.sig_enforce
# IMA appraisal in log/enforce mode based on digest lists, protecting file content and extended attributes, with the default policy set to appraise_exec_tcb+appraise_exec_immutable
ima_appraise=log-evm ima_appraise_digest_list=digest ima_policy="appraise_exec_tcb|appraise_exec_immutable" initramtmpfs evm=x509 evm=complete module.sig_enforce
ima_appraise=enforce-evm ima_appraise_digest_list=digest ima_policy="appraise_exec_tcb|appraise_exec_immutable" initramtmpfs evm=x509 evm=complete module.sig_enforce

Reboot the system to enable IMA digest list appraisal. During the boot process, the IMA policy will take effect, and the IMA digest list files will be automatically imported.

Boot Without a Default Policy

You can omit the ima_policy parameter in the boot parameters, indicating that no default policy is applied during system startup. The IMA appraisal mechanism will wait for the you to import a policy before becoming active.

Step 1: Configure the boot parameters. Typical configurations are as follows:

ini
# IMA appraisal in log/enforce mode based on digest lists, protecting only file content, with no default policy
ima_appraise=log ima_appraise_digest_list=digest-nometadata initramtmpfs
ima_appraise=enforce ima_appraise_digest_list=digest-nometadata initramtmpfs
# IMA appraisal in log/enforce mode based on digest lists, protecting file content and extended attributes, with no default policy
ima_appraise=log-evm ima_appraise_digest_list=digest initramtmpfs evm=x509 evm=complete
ima_appraise=enforce-evm ima_appraise_digest_list=digest initramtmpfs evm=x509 evm=complete

Reboot the system. At this point, since no policy is configured, IMA appraisal will not be active.

Step 2: Import the IMA policy by writing the full path of the policy file to the kernel interface:

shell
echo /path/to/policy > /sys/kernel/security/ima/policy

Note:
The policy must include certain fixed rules. Refer to the following policy templates.
For openEuler 22.03 LTS (reusing RPM signatures):

ini
# Do not appraise access behavior for the securityfs file system.
dont_appraise fsmagic=0x73636673
# Other user-defined dont_appraise rules
......
# Appraise imported IMA digest list files.
appraise func=DIGEST_LIST_CHECK appraise_type=imasig
# Appraise all files opened by the /usr/libexec/rpm_parser process.
appraise parser appraise_type=imasig
# Appraise executed applications (triggering appraisal for /usr/libexec/rpm_parser execution, additional conditions such as SELinux labels can be added).
appraise func=BPRM_CHECK appraise_type=imasig
# Other user-defined appraise rules
......

For openEuler 24.03 LTS (IMA extended attribute signatures or appended signatures):

ini
# User-defined dont_appraise rules
......
# Appraise imported IMA digest list files.
appraise func=DIGEST_LIST_CHECK appraise_type=imasig|modsig
# Other user-defined appraise rules.
......

Step 3: Import the IMA digest list files. Different import methods are required for digest lists with different signing methods.

For openEuler 22.03 LTS (IMA digest lists reusing RPM signatures):

ini
# Import digest lists from the digest_list_tools package
echo /etc/ima/digest_lists/0-metadata_list-compact-digest-list-tools-0.3.95-13.x86_64 > /sys/kernel/security/ima/digest_list_data
echo /etc/ima/digest_lists/0-parser_list-compact-libexec > /sys/kernel/security/ima/digest_list_data
# Import other RPM digest lists
upload_digest_lists add /etc/ima/digest_lists
# Check the number of imported digest list entries
cat /sys/kernel/security/ima/digests_count

For openEuler 24.03 LTS (IMA digest lists with appended signatures):

shell
find /etc/ima/digest_lists -name "0-metadata_list-compact-*" -exec echo {} > /sys/kernel/security/ima/digest_list_data \;
Software Upgrade

After the IMA digest list feature is enabled, files covered by IMA protection require synchronized updates to their digest lists during upgrades. For RPM packages released by openEuler, the addition, update, and deletion of digest lists within the RPM packages are automatically handled during package installation, upgrade, or removal, without requiring manual user intervention. For user-maintained non-RPM packages, manual import of digest lists is necessary.

User Certificate Import

You can import custom certificates to measure or appraise software not released by openEuler. The openEuler IMA appraisal mode supports signature verification using certificates from the following two key rings:

  • builtin_trusted_keys: root certificates pre-configured during kernel compilation
  • ima: imported via /etc/keys/x509_ima.der in initrd, which must be a subordinate certificate of any certificate in the builtin_trusted_keys key ring

Steps to import a root certificate into the builtin_trusted_keys key ring:

Step 1: Generate a root certificate using the openssl command:

shell
echo 'subjectKeyIdentifier=hash' > root.cfg
openssl genrsa -out root.key 4096
openssl req -new -sha256 -key root.key -out root.csr -subj "/C=AA/ST=BB/O=CC/OU=DD/CN=openeuler test ca"
openssl x509 -req -days 3650 -extfile root.cfg -signkey root.key -in root.csr -out root.crt
openssl x509 -in root.crt -out root.der -outform DER

Step 2: Obtain the openEuler kernel source code, using the latest OLK-5.10 branch as an example:

shell
git clone https://gitee.com/openeuler/kernel.git -b OLK-5.10

Step 3: Navigate to the source code directory and copy the root certificate into it:

shell
cd kernel
cp /path/to/root.der .

Modify the CONFIG_SYSTEM_TRUSTED_KEYS option in the config file:

shell
CONFIG_SYSTEM_TRUSTED_KEYS="./root.crt"

Step 4: Compile and install the kernel (steps omitted; ensure digest lists are generated for kernel modules).

Step 5: Verify certificate import after rebooting:

shell
keyctl show %:.builtin_trusted_keys

Steps to import a subordinate certificate into the ima key ring (requires the root certificate to be imported into the builtin_trusted_keys key ring first):

Step 1: Generate a subordinate certificate based on the root certificate using the openssl command:

shell
echo 'subjectKeyIdentifier=hash' > ima.cfg
echo 'authorityKeyIdentifier=keyid,issuer' >> ima.cfg
echo 'keyUsage=digitalSignature' >> ima.cfg
openssl genrsa -out ima.key 4096
openssl req -new -sha256 -key ima.key -out ima.csr -subj "/C=AA/ST=BB/O=CC/OU=DD/CN=openeuler test ima"
openssl x509 -req -sha256 -CAcreateserial -CA root.crt -CAkey root.key -extfile ima.cfg -in ima.csr -out ima.crt
openssl x509 -outform DER -in ima.crt -out x509_ima.der

Step 2: Copy the IMA certificate to the /etc/keys directory:

shell
mkdir -p /etc/keys/
cp x509_ima.der /etc/keys/

Step 3: Package initrd, embedding the IMA certificate and digest lists into the initrd image:

shell
echo 'install_items+=" /etc/keys/x509_ima.der "' >> /etc/dracut.conf
dracut -f -e xattr

Step 4: Verify certificate import after rebooting:

shell
keyctl show %:.ima

Typical Use Cases

Depending on the operating mode, IMA digest lists can be applied to trusted measurement scenarios and user-space secure boot scenarios.

Trusted Measurement Scenario

The trusted measurement scenario primarily relies on the IMA digest list measurement mode, where the kernel and hardware root of trust (RoT) like the TPM jointly measure critical files. This is combined with a remote attestation toolchain to prove the trusted state of current system files:

Runtime phase

  • During software package deployment, digest lists are imported synchronously. IMA measures the digest lists and records the measurement logs (synchronously extended to the TPM).

  • When an application is executed, IMA measurement is triggered. If the file digest matches the allowlist, it is ignored. Otherwise, the measurement log is recorded (synchronously extended to the TPM).

Attestation phase (industry standard process)

  • The remote attestation server sends an attestation request, and the client returns the IMA measurement logs along with the signed TPM PCR values.

  • The remote attestation server sequentially verifies the PCR (signature verification), measurement logs (PCR replay), and file measurement information (comparison with local baseline values), reporting the results to the security center.

  • The security management center takes corresponding actions, such as event notification or node isolation.

User-Space Secure Boot Scenario

The user-space secure boot scenario primarily relies on the IMA digest list appraisal mode, similar to secure boot. It aims to perform integrity checks on executed applications or accessed critical files. If the check fails, access is denied:

Runtime phase

  • During application deployment, digest lists are imported. After the kernel verifies the signature, the digest values are loaded into the kernel hash table as an allowlist.

  • When an application is executed, IMA verification is triggered. The file hash value is calculated, and if it matches the baseline value, access is allowed. Otherwise, the event is logged or access is denied.

Appendix

Kernel Compilation Options

The compilation options provided by native IMA/EVM and their descriptions are as follows.

Compilation OptionFunctionality
CONFIG_INTEGRITYEnable IMA/EVM compilation.
CONFIG_INTEGRITY_SIGNATUREEnable IMA signature verification.
CONFIG_INTEGRITY_ASYMMETRIC_KEYSEnable IMA asymmetric signature verification.
CONFIG_INTEGRITY_TRUSTED_KEYRINGEnable IMA/EVM keyring.
CONFIG_INTEGRITY_AUDITCompile IMA audit module.
CONFIG_IMAEnable IMA.
CONFIG_IMA_WRITE_POLICYAllow updating IMA policies during runtime.
CONFIG_IMA_MEASURE_PCR_IDXAllow specifying IMA measurement PCR index.
CONFIG_IMA_LSM_RULESAllow configuring LSM rules.
CONFIG_IMA_APPRAISEEnable IMA appraisal.
IMA_APPRAISE_BOOTPARAMEnable IMA appraisal boot parameters.
CONFIG_EVMEnable EVM.

The compilation options provided by the openEuler IMA digest list feature and their descriptions are as follows (enabled by default in openEuler kernel compilation).

Compilation OptionFunctionality
CONFIG_DIGEST_LISTEnable the IMA digest list feature.

IMA Digest List Root Certificate

In openEuler 22.03, the RPM key pair is used to sign IMA digest lists. To ensure the IMA feature is usable out-of-the-box, the openEuler kernel compilation process imports the RPM root certificate (PGP certificate) into the kernel by default. This includes the OBS certificate used in older versions and the openEuler certificate introduced in openEuler 22.03 LTS SP1:

shell
# cat /proc/keys | grep PGP
1909b4ad I------     1 perm 1f030000     0     0 asymmetri private OBS b25e7f66: PGP.rsa b25e7f66 []
2f10cd36 I------     1 perm 1f030000     0     0 asymmetri openeuler <openeuler@compass-ci.com> fb37bc6f: PGP.rsa fb37bc6f []

Since the current kernel does not support importing PGP subkeys, and the openEuler certificate uses subkey signing, the openEuler kernel preprocesses the certificate before compilation by extracting the subkey and importing it into the kernel. The specific process can be found in the process_pgp_certs.sh script in the kernel package repository.

Starting from openEuler 24.03, dedicated IMA certificates are supported. For details, refer to the relevant section in Introduction to Signature Certificates.

If you do not intend to use the IMA digest list feature or prefer other keys for signing/verification, you can remove the related code and implement your own kernel root certificate configuration.