mbox series

[RFC,v3,00/13] Clavis LSM

Message ID 20241017155516.2582369-1-eric.snowberg@oracle.com
Headers show
Series Clavis LSM | expand

Message

Eric Snowberg Oct. 17, 2024, 3:55 p.m. UTC
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.

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

Comments

Jarkko Sakkinen Oct. 17, 2024, 4:13 p.m. UTC | #1
On Thu, 2024-10-17 at 09:55 -0600, Eric Snowberg wrote:
> Remove the CONFIG_INTEGRITY_PLATFORM_KEYRING ifdef check so this
> pattern does not need to be repeated with new code.
> 
> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
> ---
>  certs/system_keyring.c | 6 ------
>  1 file changed, 6 deletions(-)
> 
> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
> index 9de610bf1f4b..e344cee10d28 100644
> --- a/certs/system_keyring.c
> +++ b/certs/system_keyring.c
> @@ -24,9 +24,7 @@ static struct key *secondary_trusted_keys;
>  #ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
>  static struct key *machine_trusted_keys;
>  #endif
> -#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
>  static struct key *platform_trusted_keys;
> -#endif
>  
>  extern __initconst const u8 system_certificate_list[];
>  extern __initconst const unsigned long system_certificate_list_size;
> @@ -345,11 +343,7 @@ int verify_pkcs7_message_sig(const void *data,
> size_t len,
>  		trusted_keys = builtin_trusted_keys;
>  #endif
>  	} else if (trusted_keys == VERIFY_USE_PLATFORM_KEYRING) {
> -#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
>  		trusted_keys = platform_trusted_keys;
> -#else
> -		trusted_keys = NULL;
> -#endif
>  		if (!trusted_keys) {
>  			ret = -ENOKEY;
>  			pr_devel("PKCS#7 platform keyring is not
> available\n");

Just to check with the argument that any commit should bring the Git
tree to another "good state". Why this was flagged? What would be the
collateral damage if only this commit was picked and put to a pull
request? No intentions to do that, this more like forming a better
understanding what is at stake here.

I.e. I get that you need this for subsequent commits but I think the
commit message should also have like explanation why this is a legit
change otherwise.

I mean, less flagging better if it does not cause harm is already
great without higher level goals.

BR, Jarkko
Eric Snowberg Oct. 17, 2024, 4:50 p.m. UTC | #2
> On Oct 17, 2024, at 10:13 AM, Jarkko Sakkinen <jarkko@kernel.org> wrote:
> 
> On Thu, 2024-10-17 at 09:55 -0600, Eric Snowberg wrote:
>> Remove the CONFIG_INTEGRITY_PLATFORM_KEYRING ifdef check so this
>> pattern does not need to be repeated with new code.
>> 
>> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
>> ---
>>  certs/system_keyring.c | 6 ------
>>  1 file changed, 6 deletions(-)
>> 
>> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
>> index 9de610bf1f4b..e344cee10d28 100644
>> --- a/certs/system_keyring.c
>> +++ b/certs/system_keyring.c
>> @@ -24,9 +24,7 @@ static struct key *secondary_trusted_keys;
>>  #ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
>>  static struct key *machine_trusted_keys;
>>  #endif
>> -#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
>>  static struct key *platform_trusted_keys;
>> -#endif
>>  
>>  extern __initconst const u8 system_certificate_list[];
>>  extern __initconst const unsigned long system_certificate_list_size;
>> @@ -345,11 +343,7 @@ int verify_pkcs7_message_sig(const void *data,
>> size_t len,
>>   trusted_keys = builtin_trusted_keys;
>>  #endif
>>   } else if (trusted_keys == VERIFY_USE_PLATFORM_KEYRING) {
>> -#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
>>   trusted_keys = platform_trusted_keys;
>> -#else
>> - trusted_keys = NULL;
>> -#endif
>>   if (!trusted_keys) {
>>   ret = -ENOKEY;
>>   pr_devel("PKCS#7 platform keyring is not
>> available\n");
> 
> Just to check with the argument that any commit should bring the Git
> tree to another "good state". Why this was flagged? What would be the
> collateral damage if only this commit was picked and put to a pull
> request? No intentions to do that, this more like forming a better
> understanding what is at stake here.
> 
> I.e. I get that you need this for subsequent commits but I think the
> commit message should also have like explanation why this is a legit
> change otherwise.

Thanks for taking a look at this, I will add a better explanation in the
next round.
Jarkko Sakkinen Oct. 17, 2024, 4:50 p.m. UTC | #3
On Thu, 2024-10-17 at 09:55 -0600, Eric Snowberg wrote:
> +static struct asymmetric_key_id *clavis_parse_boot_param(char *kid,
> struct asymmetric_key_id *akid,
> +							 int
> akid_max_len)
> +{
> +	int error, hex_len;
> +
> +	if (!kid)
> +		return 0;
> +
> +	hex_len = strlen(kid) / 2;

Hmmm... I'd consider sanity checking this:

	size_t len;

	/* ... */

	len = strlen(kid);
	if (len % 2) {
		pr_err("Clavis key id has invalid length %lu\n", len);
		return 0;
	}

	hex_len = len / 2;
	
BR, Jarkko
Jarkko Sakkinen Oct. 17, 2024, 7:20 p.m. UTC | #4
On Thu, 2024-10-17 at 09:55 -0600, Eric Snowberg wrote:
> Add a new verification type called VERIFYING_CLAVIS_SIGNATURE.  This
> new
> usage will be used for validating keys added to the new clavis LSM
> keyring.
> This will be introduced in a follow-on patch.
> 
> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
> ---
>  crypto/asymmetric_keys/asymmetric_type.c | 1 +
>  crypto/asymmetric_keys/pkcs7_verify.c    | 1 +
>  include/linux/verification.h             | 2 ++
>  3 files changed, 4 insertions(+)
> 
> diff --git a/crypto/asymmetric_keys/asymmetric_type.c
> b/crypto/asymmetric_keys/asymmetric_type.c
> index 43af5fa510c0..d7bf95c77f4a 100644
> --- a/crypto/asymmetric_keys/asymmetric_type.c
> +++ b/crypto/asymmetric_keys/asymmetric_type.c
> @@ -25,6 +25,7 @@ const char *const
> key_being_used_for[NR__KEY_BEING_USED_FOR] = {
>  	[VERIFYING_KEY_SIGNATURE]		= "key sig",
>  	[VERIFYING_KEY_SELF_SIGNATURE]		= "key self sig",
>  	[VERIFYING_UNSPECIFIED_SIGNATURE]	= "unspec sig",
> +	[VERIFYING_CLAVIS_SIGNATURE]		= "clavis sig",
>  };
>  EXPORT_SYMBOL_GPL(key_being_used_for);
>  
> diff --git a/crypto/asymmetric_keys/pkcs7_verify.c
> b/crypto/asymmetric_keys/pkcs7_verify.c
> index f0d4ff3c20a8..1dc80e68ce96 100644
> --- a/crypto/asymmetric_keys/pkcs7_verify.c
> +++ b/crypto/asymmetric_keys/pkcs7_verify.c
> @@ -428,6 +428,7 @@ int pkcs7_verify(struct pkcs7_message *pkcs7,
>  		}
>  		/* Authattr presence checked in parser */
>  		break;
> +	case VERIFYING_CLAVIS_SIGNATURE:
>  	case VERIFYING_UNSPECIFIED_SIGNATURE:
>  		if (pkcs7->data_type != OID_data) {
>  			pr_warn("Invalid unspecified sig (not pkcs7-
> data)\n");
> diff --git a/include/linux/verification.h
> b/include/linux/verification.h
> index cb2d47f28091..02d2d70e2324 100644
> --- a/include/linux/verification.h
> +++ b/include/linux/verification.h
> @@ -36,6 +36,8 @@ enum key_being_used_for {
>  	VERIFYING_KEY_SIGNATURE,
>  	VERIFYING_KEY_SELF_SIGNATURE,
>  	VERIFYING_UNSPECIFIED_SIGNATURE,
> +	/* Add new entries above, keep VERIFYING_CLAVIS_SIGNATURE at
> the end. */
> +	VERIFYING_CLAVIS_SIGNATURE,
>  	NR__KEY_BEING_USED_FOR
>  };
>  extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];

This looks as good as it can get. Just wondering that does this Clavis
thing connect with the TPM2 asymmetric keys that I've been working on?
I.e. can they be used in tandem. I should really update that patch set
(latest from April).

BR, Jarkko
Jarkko Sakkinen Oct. 17, 2024, 7:27 p.m. UTC | #5
On Thu, 2024-10-17 at 09:55 -0600, Eric Snowberg wrote:
> If the kernel is built with CONFIG_MODULE_SIG_KEY, get the subject
> key identifier and add an ACL for it within the .clavis keyring.
> 
> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>

Super sound splits! Nice to review, have to give credit on this
:-)

> ---
>  certs/.gitignore                 |  1 +
>  certs/Makefile                   | 20 ++++++++++++++++++++
>  certs/clavis_module_acl.c        |  7 +++++++
>  security/clavis/clavis.h         |  9 +++++++++
>  security/clavis/clavis_keyring.c | 27 +++++++++++++++++++++++++++
>  5 files changed, 64 insertions(+)
>  create mode 100644 certs/clavis_module_acl.c
> 
> diff --git a/certs/.gitignore b/certs/.gitignore
> index cec5465f31c1..dc99ae5a2585 100644
> --- a/certs/.gitignore
> +++ b/certs/.gitignore
> @@ -3,3 +3,4 @@
>  /extract-cert
>  /x509_certificate_list
>  /x509_revocation_list
> +/module_acl
> diff --git a/certs/Makefile b/certs/Makefile
> index f6fa4d8d75e0..f2555e5296f5 100644
> --- a/certs/Makefile
> +++ b/certs/Makefile
> @@ -6,6 +6,7 @@
>  obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o
> system_certificates.o
>  obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o
> blacklist_hashes.o
>  obj-$(CONFIG_SYSTEM_REVOCATION_LIST) += revocation_certificates.o
> +obj-$(CONFIG_SECURITY_CLAVIS) += clavis_module_acl.o
>  
>  $(obj)/blacklist_hashes.o: $(obj)/blacklist_hash_list
>  CFLAGS_blacklist_hashes.o := -I $(obj)
> @@ -75,6 +76,25 @@ $(obj)/signing_key.x509: $(filter-out
> $(PKCS11_URI),$(CONFIG_MODULE_SIG_KEY)) $(
>  
>  targets += signing_key.x509
>  
> +ifeq ($(CONFIG_MODULE_SIG_KEY),)
> +quiet_cmd_make_module_acl = GEN   $@
> +      cmd_make_module_acl = \
> +	echo > $@
> +else
> +quiet_cmd_make_module_acl = GEN   $@
> +      cmd_make_module_acl = \
> +	openssl x509 -in $< -inform der -ext subjectKeyIdentifier  -
> nocert | \
> +	tail -n +2 | cut -f2 -d '='| tr -d ':' | tr '[:upper:]'
> '[:lower:]' | \
> +	sed 's/^[ \t]*//; s/.*/"00:&",/' > $@
> +endif
> +
> +$(obj)/module_acl: $(obj)/signing_key.x509 FORCE
> +		$(call if_changed,make_module_acl)
> +
> +$(obj)/clavis_module_acl.o: $(obj)/module_acl
> +
> +targets += module_acl
> +
>  $(obj)/revocation_certificates.o: $(obj)/x509_revocation_list
>  
>  $(obj)/x509_revocation_list: $(CONFIG_SYSTEM_REVOCATION_KEYS)
> $(obj)/extract-cert FORCE
> diff --git a/certs/clavis_module_acl.c b/certs/clavis_module_acl.c
> new file mode 100644
> index 000000000000..fc2f694c48f9
> --- /dev/null
> +++ b/certs/clavis_module_acl.c
> @@ -0,0 +1,7 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <linux/kernel.h>
> +
> +const char __initconst *const clavis_module_acl[] = {
> +#include "module_acl"
> +	NULL
> +};
> diff --git a/security/clavis/clavis.h b/security/clavis/clavis.h
> index 7b55a6050440..92f77a1939ad 100644
> --- a/security/clavis/clavis.h
> +++ b/security/clavis/clavis.h
> @@ -11,4 +11,13 @@ struct asymmetric_setup_kid {
>  	struct asymmetric_key_id id;
>  	unsigned char data[CLAVIS_BIN_KID_MAX];
>  };
> +
> +#ifndef CONFIG_SYSTEM_TRUSTED_KEYRING
> +const char __initconst *const clavis_module_acl[] = {
> +	 NULL
> +};
> +#else
> +extern const char __initconst *const clavis_module_acl[];
> +#endif
> +
>  #endif /* _SECURITY_CLAVIS_H_ */
> diff --git a/security/clavis/clavis_keyring.c
> b/security/clavis/clavis_keyring.c
> index 00163e7f0fe9..2a18d0e77189 100644
> --- a/security/clavis/clavis_keyring.c
> +++ b/security/clavis/clavis_keyring.c
> @@ -259,6 +259,31 @@ static struct key_restriction
> *clavis_restriction_alloc(key_restrict_link_func_t
>  	return restriction;
>  }
>  
> +static void clavis_add_acl(const char *const *skid_list, struct key
> *keyring)
> +{
> +	const char *const *acl;
> +	key_ref_t key;
> +
> +	for (acl = skid_list; *acl; acl++) {
> +		key = key_create(make_key_ref(keyring, true),
> +				 "clavis_key_acl",
> +				  *acl,
> +				  NULL,
> +				  0,
> +				  KEY_POS_SEARCH | KEY_POS_VIEW |
> KEY_USR_SEARCH | KEY_USR_VIEW,
> +				  KEY_ALLOC_NOT_IN_QUOTA |
> KEY_ALLOC_BUILT_IN |
> +				  KEY_ALLOC_BYPASS_RESTRICTION);
> +		if (IS_ERR(key)) {
> +			if (PTR_ERR(key) == -EEXIST)
> +				pr_info("Duplicate clavis_key_acl
> %s\n", *acl);
> +			else
> +				pr_info("Problem with clavis_key_acl
> %s: %pe\n", *acl, key);
> +		} else {
> +			pr_info("Added clavis_key_acl %s\n", *acl);
> +		}
> +	}
> +}
> +
>  static int __init clavis_keyring_init(void)
>  {
>  	struct key_restriction *restriction;
> @@ -274,6 +299,8 @@ static int __init clavis_keyring_init(void)
>  	if (IS_ERR(clavis_keyring))
>  		panic("Can't allocate clavis keyring\n");
>  
> +	clavis_add_acl(clavis_module_acl, clavis_keyring);
> +
>  	return 0;
>  }
>  

Not yet tagging, but neither anything to complain. LGTM

BR, Jarkko
Eric Snowberg Oct. 17, 2024, 8:34 p.m. UTC | #6
> On Oct 17, 2024, at 10:50 AM, Jarkko Sakkinen <jarkko@kernel.org> wrote:
> 
> On Thu, 2024-10-17 at 09:55 -0600, Eric Snowberg wrote:
>> +static struct asymmetric_key_id *clavis_parse_boot_param(char *kid,
>> struct asymmetric_key_id *akid,
>> + int
>> akid_max_len)
>> +{
>> + int error, hex_len;
>> +
>> + if (!kid)
>> + return 0;
>> +
>> + hex_len = strlen(kid) / 2;
> 
> Hmmm... I'd consider sanity checking this:
> 
> size_t len;
> 
> /* ... */
> 
> len = strlen(kid);
> if (len % 2) {
> pr_err("Clavis key id has invalid length %lu\n", len);
> return 0;
> }
> 
> hex_len = len / 2;
> 

Good catch, I will include this in the next round.  I have also added a kunit test 
for this as well.  Thanks.
Jarkko Sakkinen Oct. 17, 2024, 9:16 p.m. UTC | #7
On Thu, 2024-10-17 at 20:34 +0000, Eric Snowberg wrote:
> 
> 
> > On Oct 17, 2024, at 10:50 AM, Jarkko Sakkinen <jarkko@kernel.org>
> > wrote:
> > 
> > On Thu, 2024-10-17 at 09:55 -0600, Eric Snowberg wrote:
> > > +static struct asymmetric_key_id *clavis_parse_boot_param(char
> > > *kid,
> > > struct asymmetric_key_id *akid,
> > > + int
> > > akid_max_len)
> > > +{
> > > + int error, hex_len;
> > > +
> > > + if (!kid)
> > > + return 0;
> > > +
> > > + hex_len = strlen(kid) / 2;
> > 
> > Hmmm... I'd consider sanity checking this:
> > 
> > size_t len;
> > 
> > /* ... */
> > 
> > len = strlen(kid);
> > if (len % 2) {
> > pr_err("Clavis key id has invalid length %lu\n", len);
> > return 0;
> > }
> > 
> > hex_len = len / 2;
> > 
> 
> Good catch, I will include this in the next round.  I have also added
> a kunit test 
> for this as well.  Thanks.

I guess hex2bin() would eventually catch this issue, i.e. not an actual
bug, but I still think that you are better off doing also check here and
get an appropriate message to klog if that ever happens :-)

BR, Jarkko
Eric Snowberg Oct. 17, 2024, 9:42 p.m. UTC | #8
> On Oct 17, 2024, at 1:20 PM, Jarkko Sakkinen <jarkko@kernel.org> wrote:
> 
> On Thu, 2024-10-17 at 09:55 -0600, Eric Snowberg wrote:
>> Add a new verification type called VERIFYING_CLAVIS_SIGNATURE.  This
>> new
>> usage will be used for validating keys added to the new clavis LSM
>> keyring.
>> This will be introduced in a follow-on patch.
>> 
>> Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
>> ---
>>  crypto/asymmetric_keys/asymmetric_type.c | 1 +
>>  crypto/asymmetric_keys/pkcs7_verify.c    | 1 +
>>  include/linux/verification.h             | 2 ++
>>  3 files changed, 4 insertions(+)
>> 
>> diff --git a/crypto/asymmetric_keys/asymmetric_type.c
>> b/crypto/asymmetric_keys/asymmetric_type.c
>> index 43af5fa510c0..d7bf95c77f4a 100644
>> --- a/crypto/asymmetric_keys/asymmetric_type.c
>> +++ b/crypto/asymmetric_keys/asymmetric_type.c
>> @@ -25,6 +25,7 @@ const char *const
>> key_being_used_for[NR__KEY_BEING_USED_FOR] = {
>>   [VERIFYING_KEY_SIGNATURE] = "key sig",
>>   [VERIFYING_KEY_SELF_SIGNATURE] = "key self sig",
>>   [VERIFYING_UNSPECIFIED_SIGNATURE] = "unspec sig",
>> + [VERIFYING_CLAVIS_SIGNATURE] = "clavis sig",
>>  };
>>  EXPORT_SYMBOL_GPL(key_being_used_for);
>>  
>> diff --git a/crypto/asymmetric_keys/pkcs7_verify.c
>> b/crypto/asymmetric_keys/pkcs7_verify.c
>> index f0d4ff3c20a8..1dc80e68ce96 100644
>> --- a/crypto/asymmetric_keys/pkcs7_verify.c
>> +++ b/crypto/asymmetric_keys/pkcs7_verify.c
>> @@ -428,6 +428,7 @@ int pkcs7_verify(struct pkcs7_message *pkcs7,
>>   }
>>   /* Authattr presence checked in parser */
>>   break;
>> + case VERIFYING_CLAVIS_SIGNATURE:
>>   case VERIFYING_UNSPECIFIED_SIGNATURE:
>>   if (pkcs7->data_type != OID_data) {
>>   pr_warn("Invalid unspecified sig (not pkcs7-
>> data)\n");
>> diff --git a/include/linux/verification.h
>> b/include/linux/verification.h
>> index cb2d47f28091..02d2d70e2324 100644
>> --- a/include/linux/verification.h
>> +++ b/include/linux/verification.h
>> @@ -36,6 +36,8 @@ enum key_being_used_for {
>>   VERIFYING_KEY_SIGNATURE,
>>   VERIFYING_KEY_SELF_SIGNATURE,
>>   VERIFYING_UNSPECIFIED_SIGNATURE,
>> + /* Add new entries above, keep VERIFYING_CLAVIS_SIGNATURE at
>> the end. */
>> + VERIFYING_CLAVIS_SIGNATURE,
>>   NR__KEY_BEING_USED_FOR
>>  };
>>  extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
> 
> This looks as good as it can get. Just wondering that does this Clavis
> thing connect with the TPM2 asymmetric keys that I've been working on?
> I.e. can they be used in tandem. I should really update that patch set
> (latest from April).

With some changes, I think they could be used in tandem.  If I'm looking at 
the correct series, tpm2_key_rsa_describe would need to be changed to 
return a unique identifier, instead of "TPM2/RSA".  This identifier could be 
used instead of the skid when creating a Clavis ACL.  There would probably 
also need to be a new system kernel keyring containing these TPM keys. 
Similar to the builtin, secondary, machine, etc.
Jarkko Sakkinen Oct. 17, 2024, 9:58 p.m. UTC | #9
On Thu, 2024-10-17 at 21:42 +0000, Eric Snowberg wrote:
> 
> 
> > On Oct 17, 2024, at 1:20 PM, Jarkko Sakkinen <jarkko@kernel.org>
> > wrote:
> > 
> > On Thu, 2024-10-17 at 09:55 -0600, Eric Snowberg wrote:
> > > Add a new verification type called VERIFYING_CLAVIS_SIGNATURE. 
> > > This
> > > new
> > > usage will be used for validating keys added to the new clavis
> > > LSM
> > > keyring.
> > > This will be introduced in a follow-on patch.
> > > 
> > > Signed-off-by: Eric Snowberg <eric.snowberg@oracle.com>
> > > ---
> > >  crypto/asymmetric_keys/asymmetric_type.c | 1 +
> > >  crypto/asymmetric_keys/pkcs7_verify.c    | 1 +
> > >  include/linux/verification.h             | 2 ++
> > >  3 files changed, 4 insertions(+)
> > > 
> > > diff --git a/crypto/asymmetric_keys/asymmetric_type.c
> > > b/crypto/asymmetric_keys/asymmetric_type.c
> > > index 43af5fa510c0..d7bf95c77f4a 100644
> > > --- a/crypto/asymmetric_keys/asymmetric_type.c
> > > +++ b/crypto/asymmetric_keys/asymmetric_type.c
> > > @@ -25,6 +25,7 @@ const char *const
> > > key_being_used_for[NR__KEY_BEING_USED_FOR] = {
> > >   [VERIFYING_KEY_SIGNATURE] = "key sig",
> > >   [VERIFYING_KEY_SELF_SIGNATURE] = "key self sig",
> > >   [VERIFYING_UNSPECIFIED_SIGNATURE] = "unspec sig",
> > > + [VERIFYING_CLAVIS_SIGNATURE] = "clavis sig",
> > >  };
> > >  EXPORT_SYMBOL_GPL(key_being_used_for);
> > >  
> > > diff --git a/crypto/asymmetric_keys/pkcs7_verify.c
> > > b/crypto/asymmetric_keys/pkcs7_verify.c
> > > index f0d4ff3c20a8..1dc80e68ce96 100644
> > > --- a/crypto/asymmetric_keys/pkcs7_verify.c
> > > +++ b/crypto/asymmetric_keys/pkcs7_verify.c
> > > @@ -428,6 +428,7 @@ int pkcs7_verify(struct pkcs7_message *pkcs7,
> > >   }
> > >   /* Authattr presence checked in parser */
> > >   break;
> > > + case VERIFYING_CLAVIS_SIGNATURE:
> > >   case VERIFYING_UNSPECIFIED_SIGNATURE:
> > >   if (pkcs7->data_type != OID_data) {
> > >   pr_warn("Invalid unspecified sig (not pkcs7-
> > > data)\n");
> > > diff --git a/include/linux/verification.h
> > > b/include/linux/verification.h
> > > index cb2d47f28091..02d2d70e2324 100644
> > > --- a/include/linux/verification.h
> > > +++ b/include/linux/verification.h
> > > @@ -36,6 +36,8 @@ enum key_being_used_for {
> > >   VERIFYING_KEY_SIGNATURE,
> > >   VERIFYING_KEY_SELF_SIGNATURE,
> > >   VERIFYING_UNSPECIFIED_SIGNATURE,
> > > + /* Add new entries above, keep VERIFYING_CLAVIS_SIGNATURE at
> > > the end. */
> > > + VERIFYING_CLAVIS_SIGNATURE,
> > >   NR__KEY_BEING_USED_FOR
> > >  };
> > >  extern const char *const
> > > key_being_used_for[NR__KEY_BEING_USED_FOR];
> > 
> > This looks as good as it can get. Just wondering that does this
> > Clavis
> > thing connect with the TPM2 asymmetric keys that I've been working
> > on?
> > I.e. can they be used in tandem. I should really update that patch
> > set
> > (latest from April).
> 
> With some changes, I think they could be used in tandem.  If I'm
> looking at 
> the correct series, tpm2_key_rsa_describe would need to be changed to
> return a unique identifier, instead of "TPM2/RSA".  This identifier
> could be 
> used instead of the skid when creating a Clavis ACL.  There would
> probably 
> also need to be a new system kernel keyring containing these TPM
> keys. 
> Similar to the builtin, secondary, machine, etc.

I think when I finally get into working on this again I focus on
purely to get ECDSA right. Thanks for the tip, most likely this
revamp will happen post your patch set. I'm still busy fixing
corner cases with the bus encryption that James Bottomley
contributed.

BR, Jarkko