The keylime-policy tool

keylime-policy is a tool that is able to create both runtime and measured boot policies, as well as sign runtime policies. It emerged by consolidating this existing functionality that was available from a few scripts scattered across the Keylime source tree.

Creating runtime policies

A runtime policy in its most basic form is a set of “golden” cryptographic hashes of files’ un-tampered state or of keys that may be loaded onto keyrings for IMA verification (see more on Keylime Runtime Policies).

To create runtime policies, we use the keylime-policy create runtime subcommand. This subcommand supports multiple options, which can be seen by issuing the command keylime-policy create runtime --help. The next table list some of the common options:

Common options for creating runtime policies

Option

Description

-o or --output

This option specifies where the tool will output the data. If not specified, it will print the data to the standard output

-m or --ima-measurement-list

This option specifies an IMA measurement list to use for obtaining data such as hashes and keyring. If not specified, it will attempt to use /sys/kernel/security/ima/ascii_runtime_measurements by default. If you want an empty list, you can use /dev/null instead

-a or --alowlist

Indicates a plain text allow list to read checksums from

-e or --excludelist

This option specifies an exclude list file whose contents will be added to the policy. Files and directories matching the entries in this list – which also supports Python regular expressions with one regular expression per line – will be ignored by Keylime in the sense that it will not fail validation if those files change

--ramdisk-dir

This option specifies a path where the initial ramdisks (e.g. initrds or initramfs’) are located, e.g.: /boot

--rootfs

This option specifies a path to a root file system, e.g.: /

--local-rpm-repo

This option specifies a local RPM repository directory; keylime-policy will create a runtime policy based on the files that are part of the RPMs of this repo

--remote-rpm-repo

This option specifies a remote RPM repository; similar to --local-rpm-repo, keylime-policy will create a runtime policy based on the files that are part of the RPMs of this repo

Let us look at some examples next:

Converting a legacy allow list into a runtime policy

Legacy allow lists are files in which each line is of the form <digest> <file>. To convert such a file – allowlist.txt, in this example – into a runtime policy, you can do the following:

keylime-policy create runtime --allowlist allowlist.txt

Converting an exclude list into a runtime policy

An exclude list file contains a list of files or directories that are to be excluded from Keylime measurements. To convert an exclude list named excludelist.txt into a runtime policy, issue the following command:

keylime-policy create runtime --excludelist excludelist.txt

Creating a runtime policy with files from a rootfs

To create a runtime policy including files from a given root file system, specify the --rootfs <directory> argument, as in the next example:

keylime-policy create runtime --rootfs /mnt/rootfs

Creating a runtime policy with files from the initial ramdisks

To have a runtime policy including files from the initial ramdisks (initrd, initramfs), specify the direcory where they are located with --ramdisk-dir:

keylime-policy create runtime --ramdisk-dir /boot

Creating a runtime policy from RPM repositories

The keylime-policy tool is able to create runtime policies from RPM repositories, both local and remote:

Local repository

To create a policy from a local RPM repository, we can use the --local-rpm-repo switch:

keylime-policy create runtime --local-rpm-repo /tmp/local-rpm-repo

Note that, in this case, /tmp/local-rpm-repo should be a valid RPM repository, i.e., it should contain the repodata subdirectory with the relevant metadata files, such as repomd.xml.

For reference, createrepo_c is a tool capable of creating such repositories.

Remote repository

We can also create policies from remote RPM repositories, and in this case, the relevant keylime-policy switch is --remote-rpm-repo:

keylime-policy create runtime --remote-rpm-repo https://composes.stream.centos.org/stream-10/production/latest-CentOS-Stream/compose/BaseOS/x86_64/os/

Similar to when we created a policy from a local repository, we need to make sure to give the address of a valid RPM repository to keylime-policy.

Also note that this operation may take a long time, especially in the case the filelists-ext metadata is not available from the repository.

Creating a runtime policy from multiple sources

The previous examples show how to generate a runtime policy based on a single source of data, e.g., from a local or remote RPM repository, from a legacy allowlist, from a root file system, etc. The keylime-policy tool is able to combine multiple sources while generating the runtime policy, as we can see in the next example:

keylime-policy create runtime --rootfs /mnt/rootfs --ramdisk-dir /boot --allowlist allowlist.txt --excludelist excludelist.txt --local-rpm-repo /tmp/local-rpm-repo --remote-rpm-repo https://composes.stream.centos.org/stream-10/production/latest-CentOS-Stream/compose/BaseOS/x86_64/os/

Have in mind that, depending on the options used, the operation may take a long time.

Creating measured boot policies

keylime-policy supports consuming the UEFI event log file to generate a JSON file for a measured boot policy that can be later tweaked and customized to make it more generic, through the keylime-policy create measured-boot subcommand. The following table list the available options for it:

Options for creating measured boot policies

Option

Description

-o or --output

This option specifies where the tool will output the data. If not specified, it will print the data to the standard output

-e or --eventlog-file

This option specifies the binary UEFI event log file, which is normally /sys/kernel/security/tpm0/binary_bios_measurements. This option is required

-i or --without-secureboot

This option indicates you want to create a measured boot reference policy without SecureBoot (only measured boot)

Create a measured boot policy

To create a measured boot policy with keylime-tool using the /sys/kernel/security/tpm0/binary_bios_measurements event log file, you can issue the following command:

keylime-policy create measured-boot -e /sys/kernel/security/tpm0/binary_bios_measurements

It may be required to add the -i switch to the above command, if the provided event log file has Secure Boot disabled; in this case, you should see a message like this, after running the previous command: Provided eventlog has SecureBoot disabled, but -i flag was not set.

Signing runtime policies

keylime-policy also supports signing Keylime runtime policies with DSSE (Dead Simple Signing Envelope) through the keylime-policy sign runtime subcommand. The available options for this subcommand are listed next:

Options for signing runtime policies

Option

Description

-o or --output

This option specifies where the tool will output the data. If not specified, it will print the data to the standard output

-r or --runtime-policy

This option specifies the location of the runtime policy file. This option is required

-k or --keyfile

This option specifies the Elliptic-curve private key to sign the policy with

-p or keypath

This option specifies where the private key will be written to, if one is not specified via the --keyfile argument

-b or --backend

This option specifies the DSSE backend to use, which can be either ecdsa or x509. The default backend is ecdsa

-c or --cert-outfile

This option specifies the output file for the x509 certificate, when using the x509 DSSE backend

When signing runtime policies, we need to select a DSSE backend, which can be either ecdsa or x509; if we don’t explicitly select one of them, keylime-policy will use ecdsa as the default option.

The only strictly required option is the runtime policy to be signed, which can be provided via the -r switch. If you select the x509 DSSE backend, you will also need to provide the output file for the x509 certificate with the -c option.

As for the private Elliptic-curve key to be used for the signing, you can either specify one with the -k switch, or keylime-policy will generate one for you. If it does generate one automatically, it will save this key with the name keylime-ecdsa-key.pem, in the current directory; if you want the generated key to have a different file name, you can specify the desired file name with the -p switch.

For the next examples, we will sign the policy.json runtime policy file and will not specify an output file with -o, so keylime-policy should output its result to stdout.

Signing a runtime policy with a provided private key

In this example, we have an EC private key ec-p521-private.pem and want to use it to sign our policy:

keylime-policy sign runtime -r policy.json -k ec-p521-private.pem

Signing a runtime policy without providing a private key

In this other example, we will not provida en EC private key, so keylime-policy will generate one for us and save it as keylime-ecdsa-key.pem:

keylime-policy sign runtime -r policy.json

You can verify that you now have a keylime-ecdsa-key.pem file with a content that looks like this:

-----BEGIN EC PRIVATE KEY-----
<key content here>
-----END EC PRIVATE KEY-----

Not providing a private key but specifying a custom name for the autogenerated key

Here we will not specify a private EC key for the signing, but we want the autogenerated key to have the name autogen-ec-key.pem:

keylime-policy sign runtime -r policy.json -p autogen-ec-key.pem

You can verify that you now have a autogen-ec-key.pem private key file.

Signing a policy using the x509 DSSE backend

In this example we will use the x509 DSSE backend. To do that, we need to specify the backend with -b x509 and we also need to specify the output file for the x509 certificate with the -c switch:

keylime-policy sign runtime -r policy.json -k ec-p521-private.pem -b x509 -c x509.pem

You can verify that you now have a x509.pem file with the contents that look like this:

-----BEGIN CERTIFICATE-----
<certificate content here>
-----END CERTIFICATE-----