Red Hat Training

A Red Hat training course is available for RHEL 8

Chapter 29. Enhancing security with the kernel integrity subsystem

You can improve the protection of your system by using components of the kernel integrity subsystem. Learn more about the relevant components and their configuration.

29.1. The kernel integrity subsystem

The integrity subsystem is the part of the kernel that maintains overall integrity of system data. This subsystem helps to keep the state of a system the same from the time it was built. By using this subsystem, you can prevent undesired modification of specific system files.

The kernel integrity subsystem consists of two major components:

Integrity Measurement Architecture (IMA)
  • IMA measures file content whenever it is executed or opened by cryptographically hashing or signing with cryptographic keys. The keys are stored in the kernel keyring subsystem.
  • IMA places the measured values within the kernel’s memory space. This prevents users of the system from modifying the measured values.
  • IMA allows local and remote parties to verify the measured values.
  • IMA provides local validation of the current content of files against the values previously stored in the measurement list within the kernel memory. This extension forbids performing any operation on a specific file in case the current and the previous measures do not match.
Extended Verification Module (EVM)
  • EVM protects extended attributes of files (also known as xattr) that are related to system security, such as IMA measurements and SELinux attributes. EVM cryptographically hashes their corresponding values or signs them with cryptographic keys. The keys are stored in the kernel keyring subsystem.

The kernel integrity subsystem can use the Trusted Platform Module (TPM) to further harden system security.

A TPM is a hardware, firmware, or virtual component with integrated cryptographic keys, which is built according to the TPM specification by the Trusted Computing Group (TCG) for important cryptographic functions. TPMs are usually built as dedicated hardware attached to the platform’s motherboard. By providing cryptographic functions from a protected and tamper-proof area of the hardware chip, TPMs are protected from software-based attacks. TPMs provide the following features:

  • Random-number generator
  • Generator and secure storage for cryptographic keys
  • Hashing generator
  • Remote attestation

29.2. Trusted and encrypted keys

Trusted keys and encrypted keys are an important part of enhancing system security.

Trusted and encrypted keys are variable-length symmetric keys generated by the kernel that use the kernel keyring service. The integrity of the keys can be verified, which means that they can be used, for example, by the extended verification module (EVM) to verify and confirm the integrity of a running system. User-level programs can only access the keys in the form of encrypted blobs.

Trusted keys

Trusted keys need the Trusted Platform Module (TPM) chip, which is used to both create and encrypt (seal) the keys. Each TPM has a master wrapping key, called the storage root key, which is stored within the TPM itself.

Note

Red Hat Enterprise Linux 8 supports both TPM 1.2 and TPM 2.0. For more information, see the Is Trusted Platform Module (TPM) supported by Red Hat? solution.

You can verify that a TPM 2.0 chip has been enabled by entering the following command:

$ cat /sys/class/tpm/tpm0/tpm_version_major
2

You can also enable a TPM 2.0 chip and manage the TPM 2.0 device through settings in the machine firmware.

In addition to that, you can seal the trusted keys with a specific set of the TPM’s platform configuration register (PCR) values. PCR contains a set of integrity-management values that reflect the firmware, boot loader, and operating system. This means that PCR-sealed keys can only be decrypted by the TPM on the same system on which they were encrypted. However, when a PCR-sealed trusted key is loaded (added to a keyring), and thus its associated PCR values are verified, it can be updated with new (or future) PCR values, so that a new kernel, for example, can be booted. You can save a single key also as multiple blobs, each with a different PCR value.

Encrypted keys
Encrypted keys do not require a TPM, because they use the kernel Advanced Encryption Standard (AES), which makes them faster than trusted keys. Encrypted keys are created using kernel-generated random numbers and encrypted by a master key when they are exported into user-space blobs.

The master key is either a trusted key or a user key. If the master key is not trusted, the encrypted key is only as secure as the user key used to encrypt it.

29.3. Working with trusted keys

You can improve system security by using the keyctl utility to create, export, load and update trusted keys.

Prerequisites

Note

Red Hat Enterprise Linux 8 supports both TPM 1.2 and TPM 2.0. If you use TPM 1.2, skip step 1.

Procedure

  1. Create a 2048-bit RSA key with an SHA-256 primary storage key with a persistent handle of, for example, 81000001, by using one of the following utilities:

    1. By using the tss2 package:

      # TPM_DEVICE=/dev/tpm0 tsscreateprimary -hi o -st
      Handle 80000000
      # TPM_DEVICE=/dev/tpm0 tssevictcontrol -hi o -ho 80000000 -hp 81000001
    2. By using the tpm2-tools package:

      # tpm2_createprimary --key-algorithm=rsa2048 --key-context=key.ctxt
      name-alg:
        value: sha256
        raw: 0xb
      …
      sym-keybits: 128
      rsa: xxxxxx…
      
      # tpm2_evictcontrol -c key.ctxt 0x81000001
      persistentHandle: 0x81000001
      action: persisted
  2. Create a trusted key:

    1. By using a TPM 2.0 with the syntax of keyctl add trusted <NAME> "new <KEY_LENGTH> keyhandle=<PERSISTENT-HANDLE> [options]" <KEYRING>. In this example, the persistent handle is 81000001.

      # keyctl add trusted kmk "new 32 keyhandle=0x81000001" @u
      642500861

      The command creates a trusted key called kmk with the length of 32 bytes (256 bits) and places it in the user keyring (@u). The keys may have a length of 32 to 128 bytes (256 to 1024 bits).

    2. By using a TPM 1.2 with the syntax of keyctl add trusted <NAME> "new <KEY_LENGTH>" <KEYRING>:

      # keyctl add trusted kmk "new 32" @u
  3. List the current structure of the kernel keyrings:

    # keyctl show
    Session Keyring
           -3 --alswrv    500   500  keyring: ses 97833714 --alswrv 500 -1 \ keyring: uid.1000 642500861 --alswrv 500 500 \ trusted: kmk
  4. Export the key to a user-space blob by using the serial number of the trusted key:

    # keyctl pipe 642500861 > kmk.blob

    The command uses the pipe subcommand and the serial number of kmk.

  5. Load the trusted key from the user-space blob:

    # keyctl add trusted kmk "load `cat kmk.blob`" @u
    268728824
  6. Create secure encrypted keys that use the TPM-sealed trusted key (kmk). Follow this syntax: keyctl add encrypted <NAME> "new [FORMAT] <KEY_TYPE>:<PRIMARY_KEY_NAME> <KEY_LENGTH>" <KEYRING>:

    # keyctl add encrypted encr-key "new trusted:kmk 32" @u
    159771175

29.4. Working with encrypted keys

You can improve system security on systems where a Trusted Platform Module (TPM) is not available by managing encrypted keys.

Prerequisites

  • For the 64-bit ARM architecture and IBM Z, the encrypted-keys kernel module is loaded:

    # modprobe encrypted-keys

    For more information about how to load kernel modules, see Loading kernel modules at system runtime.

Procedure

  1. Generate a user key by using a random sequence of numbers.

    # keyctl add user kmk-user "$(dd if=/dev/urandom bs=1 count=32 2>/dev/null)" @u
    427069434

    The command generates a user key called kmk-user which acts as a primary key and is used to seal the actual encrypted keys.

  2. Generate an encrypted key using the primary key from the previous step:

    # keyctl add encrypted encr-key "new user:kmk-user 32" @u
    1012412758
  3. Optionally, list all keys in the specified user keyring:

    # keyctl list @u
    2 keys in keyring:
    427069434: --alswrv  1000  1000 user: kmk-user
    1012412758: --alswrv  1000  1000 encrypted: encr-key
Important

Encrypted keys that are not sealed by a trusted primary key are only as secure as the user primary key (random-number key) that was used to encrypt them. Therefore, load the primary user key as securely as possible and preferably early during the boot process.

Additional resources

29.5. Enabling IMA and EVM

You can enable and configure Integrity measurement architecture (IMA) and extended verification module (EVM) to improve the security of the operating system.

Prerequisites

  • Secure Boot is temporarily disabled.

    Note

    When Secure Boot is enabled, the ima_appraise=fix kernel command-line parameter does not work.

  • The securityfs file system is mounted on the /sys/kernel/security/ directory and the /sys/kernel/security/integrity/ima/ directory exists. You can verify where securityfs is mounted by using the mount command:

    # mount
    ...
    securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
    ...
  • The systemd service manager is patched to support IMA and EVM on boot time. Verify by using the following command:

    # grep <options> pattern <files>

    For example:

    # dmesg | grep -i -e EVM -e IMA -w
    [ 0.598533] ima: No TPM chip found, activating TPM-bypass!
    [ 0.599435] ima: Allocated hash algorithm: sha256
    [ 0.600266] ima: No architecture policies found
    [ 0.600813] evm: Initialising EVM extended attributes:
    [ 0.601581] evm: security.selinux
    [ 0.601963] evm: security.ima
    [ 0.602353] evm: security.capability
    [ 0.602713] evm: HMAC attrs: 0x1
    [ 1.455657] systemd[1]: systemd 239 (239-74.el8_8) running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=legacy)
    [ 2.532639] systemd[1]: systemd 239 (239-74.el8_8) running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=legacy)

    Procedure

    1. Enable IMA and EVM in the fix mode for the current boot entry and allow users to gather and update the IMA measurements by adding the following kernel command-line parameters:

      # grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="ima_policy=appraise_tcb ima_appraise=fix evm=fix"

      The command enables IMA and EVM in the fix mode for the current boot entry and allows users to gather and update the IMA measurements.

      The ima_policy=appraise_tcb kernel command-line parameter ensures that the kernel uses the default Trusted Computing Base (TCB) measurement policy and the appraisal step. The appraisal step forbids access to files whose prior and current measures do not match.

    2. Reboot to make the changes come into effect.
    3. Optional: Verify that the parameters have been added to the kernel command line:

      # cat /proc/cmdline
      BOOT_IMAGE=(hd0,msdos1)/vmlinuz-4.18.0-167.el8.x86_64 root=/dev/mapper/rhel-root ro crashkernel=auto resume=/dev/mapper/rhel-swap rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet ima_policy=appraise_tcb ima_appraise=fix evm=fix
    4. Create a kernel master key to protect the EVM key:

      # keyctl add user kmk "$(dd if=/dev/urandom bs=1 count=32 2> /dev/null)" @u
      748544121

      The kmk is kept entirely in the kernel space memory. The 32-byte long value of the kmk is generated from random bytes from the /dev/urandom file and placed in the user (@u) keyring. The key serial number is on the first line of the previous output.

    5. Create an encrypted EVM key based on the kmk:

      # keyctl add encrypted evm-key "new user:kmk 64" @u
      641780271

      The command uses the kmk to generate and encrypt a 64-byte long user key (named evm-key) and places it in the user (@u) keyring. The key serial number is on the first line of the previous output.

      Important

      It is necessary to name the user key as evm-key because that is the name the EVM subsystem is expecting and is working with.

    6. Create a directory for exported keys.

      # mkdir -p /etc/keys/
    7. Search for the kmk and export its unencrypted value into the new directory.

      # keyctl pipe $(keyctl search @u user kmk) > /etc/keys/kmk
    8. Search for the evm-key and export its encrypted value into the new directory.

      # keyctl pipe $(keyctl search @u encrypted evm-key) > /etc/keys/evm-key

      The evm-key has been encrypted by the kernel master key earlier.

    9. Optional: View the newly created keys.

      # keyctl show
      Session Keyring
      974575405   --alswrv     0        0      keyring: ses 299489774 --alswrv 0 65534 \ keyring: uid.0 748544121 --alswrv 0 0 \ user: kmk
      641780271   --alswrv     0        0           \_ encrypted: evm-key
      
      # ls -l /etc/keys/
      total 8
      -rw-r--r--. 1 root root 246 Jun 24 12:44 evm-key
      -rw-r--r--. 1 root root  32 Jun 24 12:43 kmk
    10. Optional: If the keys have been removed from the keyring, for example after system reboot, you can import the already exported kmk and evm-key instead of creating new ones.

      1. Import the kmk.

        # keyctl add user kmk "$(cat /etc/keys/kmk)" @u
        451342217
      2. Import the evm-key.

        # keyctl add encrypted evm-key "load $(cat /etc/keys/evm-key)" @u
        924537557
    11. Activate EVM.

      # echo 1 > /sys/kernel/security/evm
    12. Relabel the whole system.

      # find / -fstype xfs -type f -uid 0 -exec head -n 1 '{}' >/dev/null \;
      Warning

      Enabling IMA and EVM without relabeling the system might make the majority of the files on the system inaccessible.

Verification

  • Verify that EVM has been initialized.

    # dmesg | tail -1
    […​] evm: key initialized

29.6. Collecting file hashes with integrity measurement architecture

In the measurement phase, you can create file hashes and store them as extended attributes (xattrs) of those files. With the file hashes, you can generate either an RSA-based digital signature or a Hash-based Message Authentication Code (HMAC-SHA1) and thus prevent offline tampering attacks on the extended attributes.

Prerequisites

Procedure

  1. Create a test file:

    # echo <Test_text> > test_file

    IMA and EVM ensure that the test_file example file has assigned hash values that are stored as its extended attributes.

  2. Inspect the file’s extended attributes:

    # getfattr -m . -d test_file
    # file: test_file
    security.evm=0sAnDIy4VPA0HArpPO/EqiutnNyBql
    security.ima=0sAQOEDeuUnWzwwKYk+n66h/vby3eD

    The example output shows extended attributes with the IMA and EVM hash values and SELinux context. EVM adds a security.evm extended attribute related to the other attributes. At this point, you can use the evmctl utility on security.evm to generate either an RSA-based digital signature or a Hash-based Message Authentication Code (HMAC-SHA1).

Additional resources