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.
Parameter | Value | Function |
---|---|---|
ima_appraise | enforce-evm | Enable IMA appraisal enforce mode (EVM enabled). |
log-evm | Enable IMA appraisal log mode (EVM enabled). | |
enforce | Enable IMA appraisal enforce mode. | |
log | Enable IMA appraisal log mode. | |
off | Disable IMA appraisal. | |
ima_appraise_digest_list | digest | Enable IMA+EVM appraisal based on digest lists (comparing file content and extended attributes). |
digest-nometadata | Enable IMA appraisal based on digest lists (comparing file content only). | |
evm | x509 | Enable portable signature-based EVM directly (regardless of EVM certificate loading) |
complete | Prevent modification of EVM mode via securityfs after boot. | |
allow_metadata_writes | Allow file metadata modifications without EVM interception. | |
ima_hash | sha256/sha1/... | Specify the IMA measurement hash algorithm. |
ima_template | ima | Specify the IMA measurement template (d or n ). |
ima-ng | Specify the IMA measurement template (d-ng or n-ng ), default template. | |
ima-sig | Specify the IMA measurement template (d-ng , n-ng , or sig ). | |
ima_policy | exec_tcb | Measure all files accessed via execution or mapping, including loaded kernel modules, firmware, and kernel files. |
tcb | Extend exec_tcb policy to measure files accessed with uid=0 or euid=0 . | |
secure_boot | Appraise all loaded kernel modules, firmware, and kernel files, using IMA signature mode. | |
appraise_exec_tcb | Extend secure_boot policy to appraise all files accessed via execution or mapping. | |
appraise_tcb | Appraise all files owned by uid=0 . | |
appraise_exec_immutable | Used with the appraise_exec_tcb policy, making executable file extended attributes immutable. | |
ima_digest_list_pcr | 10 | Extend IMA measurement results based on digest list in PCR 10, disable native IMA measurement. |
11 | Extend IMA measurement results based on digest list in PCR 11, disable native IMA measurement. | |
+11 | Extend IMA measurement results based on digest list in PCR 11, extend native IMA measurement results in PCR 10. | |
ima_digest_db_size | nn[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 2147483647 | Set the kernel measurement log entry limit, defaulting to 100,000. -1 means no limit. |
initramtmpfs | None | Support tmpfs in initrd to carry file extended attributes. |
Based on user scenarios, the following parameter combinations are recommended:
(1) Native IMA measurement
# 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
# 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
# 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
# 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.
Path | Permissions | Description |
---|---|---|
ima/policy | 600 | Display or import IMA policies. |
ima/ascii_runtime_measurement | 440 | Display IMA measurement logs in ASCII format. |
ima/binary_runtime_measurement | 440 | Display IMA measurement logs in binary format. |
ima/runtime_measurement_count | 440 | Display the count of IMA measurement log entries. |
ima/violations | 440 | Display the number of abnormal IMA measurement logs. |
ima/digests_count | 440 | Display the total number of digests in the system hash table (IMA+EVM). |
ima/digest_list_data | 200 | Add digest lists. |
ima/digest_list_data_del | 200 | Delete digest lists. |
evm | 660 | Query 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.
Option | Value | Function |
---|---|---|
-d | <path> | Specify the directory to store the generated digest list files. The directory must be valid. |
-f | compact | Specify 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:policy | Match 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). | |
-o | add | Specify the operation for generating digest lists. Currently, only the add operation is supported, which adds the digest list to the file. |
-p | -1 | Specify the position in the file where the digest list will be written. Currently, only -1 is supported. |
-t | file | Generate digest lists only for file content. |
metadata | Generate digest lists for both file content and extended attributes. | |
-T | N/A | If 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. |
-m | immutable | Specify 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. |
-h | N/A | Print help information. |
Usage examples
Scenario 1: Generate a digest list/TLV digest list for a single file.
shellgen_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.
shellgen_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.
shellgen_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.
shellgen_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.
shellgen_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 byrpmbuild
.shellgen_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.
Option | Value | Function |
---|---|---|
-d | <path> | Specify the directory containing the TLV digest list files. |
-f | <filename> | Specify the name of the TLV digest list file. |
-p | dump | Define the operation type. Currently, only dump is supported, which parses and prints the TLV digest list. |
-v | N/A | Print verbose details. |
-h | N/A | Display help information. |
Usage example
View TLV digest list information.
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:
<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 withmask
. Only onefunc
is allowed per policy.FILE_CHECK
can only be paired withMAY_EXEC
,MAY_WRITE
, orMAY_READ
.MODULE_CHECK
,MMAP_CHECK
, andBPRM_CHECK
can only be paired withMAY_EXEC
.- Other combinations will not take effect.
mask
: specifies the operation on the file that triggers measurement or appraisal. Only onemask
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 usingdont_measure
ordont_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 tofunc
,objtype
offers finer granularity. For example,obj_type=nova_log_t
refers to files with the SELinux typenova_log_t
.uid
: specifies the user (by user ID) performing the operation on the file. Only oneuid
is allowed per policy.fowner
: specifies the file owner (by user ID). Only onefowner
is allowed per policy.
The keywords are detailed as follows.
Keyword | Value | Description |
---|---|---|
action | measure | Enable IMA measurement. |
action | dont_measure | Disable IMA measurement. |
action | appraise | Enable IMA appraisal. |
action | dont_appraise | Disable IMA appraisal. |
action | audit | Enable auditing. |
func | FILE_CHECK | Files to be opened |
func | MODULE_CHECK | Kernel module files to be loaded |
func | MMAP_CHECK | Shared library files to be mapped into process memory |
func | BRPM_CHECK | Files to be executed (excluding script files opened via programs like /bin/hash ) |
func | POLICY_CHECK | IMA policy files to be imported |
func | FIRMWARE_CHECK | Firmware to be loaded into memory |
func | DIGEST_LIST_CHECK | Digest list files to be loaded into the kernel |
func | KEXEC_KERNEL_CHECK | Kernel to be switched to using kexec |
mask | MAY_EXEC | Execute a file. |
mask | MAY_WRITE | Write to a file. |
mask | MAY_READ | Read a file. |
mask | MAY_APPEND | Append to a file. |
fsmagic | fsmagic=xxx | Hexadecimal magic number representing the file system type |
fsuuid | fsuuid=xxx | 16-character hexadecimal string representing the system device UUID |
fowner | fowner=xxx | User ID of the file owner |
uid | uid=xxx | User ID of the user performing the operation on the file |
obj_type | obj_type=xxx_t | File type based on SELinux labels |
pcr | pcr=<num> | PCR in TPM for extending measurements (defaulting to 10) |
appraise_type | imasig | IMA appraisal based on signatures |
appraise_type | meta_immutable | Appraisal 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:
ima_policy="tcb"
Alternatively, manually configure the IMA policy like this:
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:
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:
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):
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:
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:
getfattr -m - -d /sbin/init
Step 3: Configure boot parameters, switch the IMA appraisal mode to log or enforce, and reboot the system:
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:
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:
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:
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:
# 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:
Append the CMS signature information to the end of the IMA digest list file.
Fill in the structure and append it to the end of the signature information. The structure is defined as follows:
cstruct 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 */ };
Add the
"~Module signature appended~\n"
magic string.
A reference script for this step is as follows:
#!/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:
# 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:
# 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):
# 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:
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.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:
%__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.
...... (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:
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:
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:
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:
dracut -f -e xattr
Step 2: Configure the boot parameters and IMA policy. Typical configurations are as follows:
# 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:
# 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:
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):
# 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):
# 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):
# 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):
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:
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:
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:
cd kernel
cp /path/to/root.der .
Modify the CONFIG_SYSTEM_TRUSTED_KEYS
option in the config file:
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:
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:
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:
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:
echo 'install_items+=" /etc/keys/x509_ima.der "' >> /etc/dracut.conf
dracut -f -e xattr
Step 4: Verify certificate import after rebooting:
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 Option | Functionality |
---|---|
CONFIG_INTEGRITY | Enable IMA/EVM compilation. |
CONFIG_INTEGRITY_SIGNATURE | Enable IMA signature verification. |
CONFIG_INTEGRITY_ASYMMETRIC_KEYS | Enable IMA asymmetric signature verification. |
CONFIG_INTEGRITY_TRUSTED_KEYRING | Enable IMA/EVM keyring. |
CONFIG_INTEGRITY_AUDIT | Compile IMA audit module. |
CONFIG_IMA | Enable IMA. |
CONFIG_IMA_WRITE_POLICY | Allow updating IMA policies during runtime. |
CONFIG_IMA_MEASURE_PCR_IDX | Allow specifying IMA measurement PCR index. |
CONFIG_IMA_LSM_RULES | Allow configuring LSM rules. |
CONFIG_IMA_APPRAISE | Enable IMA appraisal. |
IMA_APPRAISE_BOOTPARAM | Enable IMA appraisal boot parameters. |
CONFIG_EVM | Enable 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 Option | Functionality |
---|---|
CONFIG_DIGEST_LIST | Enable 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:
# 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.