Re: [RFC PATCH v3 00/13] Clavis LSM
From: Mimi Zohar
Date: Mon Dec 23 2024 - 07:11:55 EST
On Thu, 2024-10-17 at 09:55 -0600, Eric Snowberg wrote:
> Motivation:
>
> Each end-user has their own security threat model. What is important to one
> end-user may not be important to another. There is not a right or wrong threat
> model.
>
> A common request made when adding new kernel changes that could impact the
> threat model around system kernel keys is to add additional Kconfig options.
> As kernel developers, it is challenging to both add and keep track of all the
> Kconfig options around security features that may limit or restrict
> system key usage. It is also difficult for a general purpose distro to take
> advantage of some of these features, since it may prevent some users from
> executing their workload.
>
> It is the author's belief that it is better left up to the end-user on how
> kernel keys should be used within their system.
>
> Throughout the Linux kernel, key usage is tracked when doing signature
> verification with keys contained within one of the system keyrings; however,
> there isn't a way for the end-user to enforce this usage. This series gives the
> end-user the ability to configure key usage based on their threat model.
> Having the ability to enforce key usage also improves security by reducing the
> attack surface should a system key be compromised. It allows new features to be
> added without the need for additional Kconfig options for fear of changing the
> end-user's threat model. It also allows a distro to build a kernel that suits
> various end-user's needs without resorting to selecting Kconfig options with
> the least restrictive security options.
The motivation for this patch set is convincing and addresses limiting the usage
of keys loaded directly or indirectly onto the system trusted keyrings -
.builtin, .machine, and .secondary_trusted_keys keyrings. Pre-loading the build
time ephemeral kernel module signing key is a nice improvement from the previous
versions. My main concern is not with Clavis per-se, but that the LSM
infrastructure allows configuring all the LSMs, but enabling at build time and
modifying at runtime a subset of them. Without Clavis enabled, nothing changes
- any key on the system trusted keyrings remains usable for any purpose. With
the current LSM design, the end user security threat model cannot be guaranteed.
Mimi
>
> Solution:
>
> This series introduces a new LSM called Clavis (Latin word meaning key).
> This LSM leaves it up to the end-user to determine what system keys they want
> to use and for what purpose.
>
> The Clavis LSM adds the ability to do access control for all system keys. When
> enabled, until an ACL entry is added for a specific key, none of the system keys
> may be used for any type of verification purpose. When the kernel is built,
> typically kernel modules are signed with an ephemeral key, an ACL entry for the
> ephemeral key is pre-loaded, allowing the kernel modules to load during boot. At
> build time other ACL entries may also be included.
>
> The Clavis LSM requires the end-user to have their own public key infrastructure
> (PKI). In order for a Clavis ACL entry to be added, the ACL must be signed by
> what is being called the Clavis key. The Clavis key is owned by the end-user.
> The Clavis public key can be contained within the machine keyring, or it can be
> added after the machine boots.
>
> Not only is there a new Clavis key being introduced, but there is also a new
> .clavis keyring. The .clavis keyring contains a single Clavis key. It also
> contains any number of ACL entries that are signed by the Clavis key.
>
> It is believed that the most common setup would be to have the Clavis key
> contained within the machine keyring. Enabling the Clavis LSM during boot is
> accomplished by passing in the asymmetric key id for the Clavis key within a
> new "clavis=" boot param. The asymmetric key id must match one already
> contained within any of the system keyrings. If a match is found, a link is
> created into the new .clavis keyring. This Clavis key shall be used as the
> root of trust for any keyring ACL updates afterwards.
>
> On UEFI systems the "clavis" boot param is mirrored into a new UEFI variable
> within the EFI stub code. This variable will persist until the next reboot.
> This same type of functionality is done within shim. Since this variable is
> created before ExitBootServices (EBS) it will not have the NVRAM bit set,
> signifying it was created during the Boot Services phase. This is being used
> so the "clavis" boot param can not be changed via kexec, thereby preventing a
> pivot of the root of trust.
>
> As mentioned earlier, this LSM introduces a new .clavis keyring. Following
> boot, no new keys can be added to this keyring and only the key designated via
> the initial boot param may be used. If the clavis boot param was not used, the
> LSM can be enabled afterwards using the keyctl command. The end-user may add
> their Clavis key into the .clavis keyring and the Clavis LSM shall be enabled.
>
> The .clavis keyring also holds the access control list for system keys. A new
> key type called clavis_key_acl is being introduced. This contains the usage
> followed by the asymmetric key id. To be added to the clavis keyring, the
> clavis_key_acl must be S/MIME signed by the Clavis key. New ACL additions to
> the .clavis keyring may be added at any time.
>
> Currently this LSM does not require new changes or modifications to any user
> space tools. It also does not have a securityfs interface. Everything is
> done using the existing keyctl tool through the new .clavis keyring. The
> S/MIME signing can be done with a simple OpenSSL command. If additions or
> updates need to be added in the future, new ACL key types could be created.
> With this approach, maintainability should not be an issue in the future
> if missing items are identified.
>
> Clavis must be configured at build time with CONFIG_SECURITY_CLAVIS=y. The list
> of security modules enabled by default is set with CONFIG_LSM. The kernel
> configuration must contain CONFIG_LSM=[...],clavis with [...] as the list of
> other security modules for the running system.
>
> For setup and usage instructions, a clavis admin-guide has been included
> in Documentation/admin-guide/LSM/clavis.rst.
>
> Future enhancements to this LSM could include:
>
> 1. Subsystems that currently use system keys with
> VERIFYING_UNSPECIFIED_SIGNATURE could be updated with their specific usage
> type. For example, a usage type for IMA, BPF, etc could be added.
>
> 2. Having the ability to allow platform keys to be on par with all other
> system keys when using this LSM. This would be useful for a user that
> controls their entire UEFI SB DB key chain and doesn't want to use MOK keys.
> This could also potentially remove the need for the machine keyring all
> together.
>
> 3. Some of the Kconfig options around key usage and types could be deprecated.
>
> I would appreciate any feedback on this approach. Thanks.
>
> Changes in v3:
> Rebased to 6.12-rc3
> Added Kunit test code
> Preload an ACL in the clavis keyring with the ephemeral module signing key
> Preload user defined ACL data into the clavis keyring with build time data
> Changes to the second patch recommended by Jarkko
> Reordered patches recommended by Mimi
> Documentation improvements recommended by Randy
>
> Changes in v2:
> Rebased to 6.10-rc1
> Various cleanup in the first patch recommended by Jarkko
> Documentation improvements recommended by Randy
> Fixed lint warnings
> Other cleanup
>
> Eric Snowberg (13):
> certs: Remove CONFIG_INTEGRITY_PLATFORM_KEYRING check
> certs: Introduce ability to link to a system key
> clavis: Introduce a new system keyring called clavis
> keys: Add new verification type (VERIFYING_CLAVIS_SIGNATURE)
> clavis: Introduce a new key type called clavis_key_acl
> clavis: Populate clavis keyring acl with kernel module signature
> keys: Add ability to track intended usage of the public key
> clavis: Introduce new LSM called clavis
> clavis: Allow user to define acl at build time
> efi: Make clavis boot param persist across kexec
> clavis: Prevent boot param change during kexec
> clavis: Add function redirection for Kunit support
> clavis: Kunit support
>
> Documentation/admin-guide/LSM/clavis.rst | 191 ++++++
> .../admin-guide/kernel-parameters.txt | 6 +
> MAINTAINERS | 7 +
> certs/.gitignore | 1 +
> certs/Makefile | 20 +
> certs/blacklist.c | 3 +
> certs/clavis_module_acl.c | 7 +
> certs/system_keyring.c | 36 +-
> crypto/asymmetric_keys/asymmetric_type.c | 1 +
> crypto/asymmetric_keys/pkcs7_trust.c | 20 +
> crypto/asymmetric_keys/pkcs7_verify.c | 5 +
> crypto/asymmetric_keys/signature.c | 4 +
> drivers/firmware/efi/Kconfig | 12 +
> drivers/firmware/efi/libstub/Makefile | 1 +
> drivers/firmware/efi/libstub/clavis.c | 33 +
> .../firmware/efi/libstub/efi-stub-helper.c | 2 +
> drivers/firmware/efi/libstub/efi-stub.c | 2 +
> drivers/firmware/efi/libstub/efistub.h | 8 +
> drivers/firmware/efi/libstub/x86-stub.c | 2 +
> include/crypto/pkcs7.h | 3 +
> include/crypto/public_key.h | 4 +
> include/keys/system_keyring.h | 7 +-
> include/linux/efi.h | 1 +
> include/linux/integrity.h | 8 +
> include/linux/lsm_count.h | 8 +-
> include/linux/lsm_hook_defs.h | 2 +
> include/linux/security.h | 7 +
> include/linux/verification.h | 2 +
> include/uapi/linux/lsm.h | 1 +
> security/Kconfig | 11 +-
> security/Makefile | 1 +
> security/clavis/.gitignore | 2 +
> security/clavis/.kunitconfig | 4 +
> security/clavis/Kconfig | 37 ++
> security/clavis/Makefile | 156 +++++
> security/clavis/clavis.c | 26 +
> security/clavis/clavis.h | 62 ++
> security/clavis/clavis_builtin_acl.c | 7 +
> security/clavis/clavis_efi.c | 50 ++
> security/clavis/clavis_keyring.c | 426 +++++++++++++
> security/clavis/clavis_test.c | 566 ++++++++++++++++++
> security/integrity/iint.c | 2 +
> security/security.c | 13 +
> .../selftests/lsm/lsm_list_modules_test.c | 3 +
> 44 files changed, 1757 insertions(+), 13 deletions(-)
> create mode 100644 Documentation/admin-guide/LSM/clavis.rst
> create mode 100644 certs/clavis_module_acl.c
> create mode 100644 drivers/firmware/efi/libstub/clavis.c
> create mode 100644 security/clavis/.gitignore
> create mode 100644 security/clavis/.kunitconfig
> create mode 100644 security/clavis/Kconfig
> create mode 100644 security/clavis/Makefile
> create mode 100644 security/clavis/clavis.c
> create mode 100644 security/clavis/clavis.h
> create mode 100644 security/clavis/clavis_builtin_acl.c
> create mode 100644 security/clavis/clavis_efi.c
> create mode 100644 security/clavis/clavis_keyring.c
> create mode 100644 security/clavis/clavis_test.c
>
>
> base-commit: 8e929cb546ee42c9a61d24fae60605e9e3192354