[RFC PATCH v2 0/8] Clavis LSM
From: Eric Snowberg
Date: Thu May 30 2024 - 20:43:24 EST
Introduce a new LSM called Clavis (Latin word meaning key). The motivation
behind this LSM is to provide access control for system keys. Before spending
more time on this LSM, I am sending this as an RFC to start a discussion to see
if the current direction taken has a possibility of being accepted in the
future.
Today the kernel has the following system keyrings: .builtin_trusted_keyring,
secondary_trusted_keyring, and the .machine. It also has the .platform
keyring which has limited capabilities; it can only be used to verify a kernel
for kexec.
Today the kernel also tracks key usage for verification done with any of these
keys. Current verification usage includes: VERIFYING_MODULE_SIGNATURE,
VERIFYING_FIRMWARE_SIGNATURE, VERIFYING_KEXEC_PE_SIGNATURE,
VERIFYING_KEY_SIGNATURE, VERIFYING_KEY_SELF_SIGNATURE, and
VERIFYING_UNSPECIFIED_SIGNATURE. After these usage types were originally
introduced, most additions have typically used the
VERIFYING_UNSPECIFIED_SIGNATURE.
At the moment, besides the usage enforcement for .platform keys, any key
contained within the system keyrings can be used for any verification
purpose. For example, a key that was originally created to sign kernel
modules could be used for BPF verification.
This new LSM adds the ability to do access control for all system keys. When
enabled, only the .builtin_trusted_keys are available for loading kernel
modules and doing a kexec. Until an ACL entry is added for a specific key, no
other system key may be used for any other purpose.
Enabling the LSM is done during initial boot by passing in a single asymmetric
key id 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 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 power on
reset. 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 asymmetric keys can be added to this keyring and only the key
designated via the initial boot param may be used. This LSM can not be started
at any other point in time. 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 sole asymmetric
key contained within it. 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, the final patch includes an admin-guide.
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. Currently, each clavis_key_acl must be individually signed. Add the ability
to sign multiple clavis_key_acl entries within the same file.
3. Currently, this LSM does not place key usage restrictions on the builtin
keys for kexec and kernel module verification. This was done to prevent a
regression that could prevent the kernel from booting. This could be
changed if there was a way at compile time to pre-populate the .clavis
keyring. This would allow the ephemeral key used to sign the kernel
modules to be included within the .clavis keyring, allowing the kernel
to boot.
4. UEFI Secure Boot Advanced Targeting (SBAT) support. Since
the boot param is mirrored into UEFI before EBS is called,
this LSM could be enhanced to not only enforce key usage,
but also SBAT levels across kexec.
5. 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.
I would appreciate any feedback on this approach. Thanks.
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 (8):
certs: Introduce ability to link to a system key
clavis: Introduce a new system keyring called clavis
efi: Make clavis boot param persist across kexec
clavis: Prevent clavis boot param from changing during kexec
keys: Add new verification type (VERIFYING_CLAVIS_SIGNATURE)
keys: Add ability to track intended usage of the public key
clavis: Introduce a new key type called clavis_key_acl
clavis: Introduce new LSM called clavis
Documentation/admin-guide/LSM/clavis.rst | 198 +++++++++++
.../admin-guide/kernel-parameters.txt | 8 +
MAINTAINERS | 7 +
certs/blacklist.c | 3 +
certs/system_keyring.c | 31 ++
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_hook_defs.h | 2 +
include/linux/security.h | 7 +
include/linux/verification.h | 1 +
include/uapi/linux/lsm.h | 1 +
security/Kconfig | 11 +-
security/Makefile | 1 +
security/clavis/Kconfig | 9 +
security/clavis/Makefile | 7 +
security/clavis/clavis.c | 25 ++
security/clavis/clavis.h | 20 ++
security/clavis/clavis_efi.c | 50 +++
security/clavis/clavis_keyring.c | 314 ++++++++++++++++++
security/integrity/iint.c | 2 +
security/security.c | 16 +-
35 files changed, 819 insertions(+), 7 deletions(-)
create mode 100644 Documentation/admin-guide/LSM/clavis.rst
create mode 100644 drivers/firmware/efi/libstub/clavis.c
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_efi.c
create mode 100644 security/clavis/clavis_keyring.c
base-commit: 1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0
--
2.43.0