2023-08-13 03:19:21

by Nayna Jain

[permalink] [raw]
Subject: [PATCH v3 0/6] Enable loading local and third party keys on PowerVM guest

On a secure boot enabled PowerVM guest, local and third party code signing
keys are needed to verify signed applications, configuration files, and
kernel modules.

Loading these keys onto either the .secondary_trusted_keys or .ima
keyrings requires the certificates be signed by keys on the
.builtin_trusted_keys, .machine or .secondary_trusted_keys keyrings.

Keys on the .builtin_trusted_keys keyring are trusted because of the chain
of trust from secure boot up to and including the linux kernel. Keys on
the .machine keyring that derive their trust from an entity such as a
security officer, administrator, system owner, or machine owner are said
to have "imputed trust." The type of certificates and the mechanism for
loading them onto the .machine keyring is platform dependent.

Userspace may load certificates onto the .secondary_trusted_keys or .ima
keyrings. However, keys may also need to be loaded by the kernel if they
are needed for verification in early boot time. On PowerVM guest, third
party code signing keys are loaded from the moduledb variable in the
Platform KeyStore(PKS) onto the .secondary_trusted_keys.

The purpose of this patch set is to allow loading of local and third party
code signing keys on PowerVM.

Changelog:

v3:

* Included Jarkko's feedback for Patch 6/6.

v2:

* Patch 5/6: Update CA restriction to allow only key signing CA's.
* Rebase on Jarkko's master tree - https://kernel.googlesource.com/pub/scm/linux/kernel/git/jarkko/linux-tpmdd
* Tested after reverting cfa7522f280aa95 because of build failure due to
this commit.

Nayna Jain (6):
integrity: PowerVM support for loading CA keys on machine keyring
integrity: ignore keys failing CA restrictions on non-UEFI platform
integrity: remove global variable from machine_keyring.c
integrity: check whether imputed trust is enabled
integrity: PowerVM machine keyring enablement
integrity: PowerVM support for loading third party code signing keys

certs/system_keyring.c | 30 +++++++++++++++++
include/keys/system_keyring.h | 7 ++++
security/integrity/Kconfig | 4 ++-
security/integrity/digsig.c | 2 +-
security/integrity/integrity.h | 6 ++--
.../platform_certs/keyring_handler.c | 19 ++++++++++-
.../platform_certs/keyring_handler.h | 10 ++++++
.../integrity/platform_certs/load_powerpc.c | 33 +++++++++++++++++++
.../platform_certs/machine_keyring.c | 22 ++++++++++---
9 files changed, 124 insertions(+), 9 deletions(-)

--
2.31.1


2023-08-13 03:40:47

by Nayna Jain

[permalink] [raw]
Subject: [PATCH v3 5/6] integrity: PowerVM machine keyring enablement

Update Kconfig to enable machine keyring and limit to CA certificates
on PowerVM. Only key signing CA keys are allowed.

Signed-off-by: Nayna Jain <[email protected]>
Reviewed-and-tested-by: Mimi Zohar <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
---
security/integrity/Kconfig | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index ec6e0d789da1..232191ee09e3 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -67,7 +67,9 @@ config INTEGRITY_MACHINE_KEYRING
depends on SECONDARY_TRUSTED_KEYRING
depends on INTEGRITY_ASYMMETRIC_KEYS
depends on SYSTEM_BLACKLIST_KEYRING
- depends on LOAD_UEFI_KEYS
+ depends on LOAD_UEFI_KEYS || LOAD_PPC_KEYS
+ select INTEGRITY_CA_MACHINE_KEYRING if LOAD_PPC_KEYS
+ select INTEGRITY_CA_MACHINE_KEYRING_MAX if LOAD_PPC_KEYS
help
If set, provide a keyring to which Machine Owner Keys (MOK) may
be added. This keyring shall contain just MOK keys. Unlike keys
--
2.31.1


2023-08-13 04:22:40

by Nayna Jain

[permalink] [raw]
Subject: [PATCH v3 2/6] integrity: ignore keys failing CA restrictions on non-UEFI platform

On non-UEFI platforms, handle restrict_link_by_ca failures differently.

Certificates which do not satisfy CA restrictions on non-UEFI platforms
are ignored.

Signed-off-by: Nayna Jain <[email protected]>
Reviewed-and-tested-by: Mimi Zohar <[email protected]>
---
security/integrity/platform_certs/machine_keyring.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/security/integrity/platform_certs/machine_keyring.c b/security/integrity/platform_certs/machine_keyring.c
index 7aaed7950b6e..389a6e7c9245 100644
--- a/security/integrity/platform_certs/machine_keyring.c
+++ b/security/integrity/platform_certs/machine_keyring.c
@@ -36,7 +36,7 @@ void __init add_to_machine_keyring(const char *source, const void *data, size_t
* If the restriction check does not pass and the platform keyring
* is configured, try to add it into that keyring instead.
*/
- if (rc && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
+ if (rc && efi_enabled(EFI_BOOT) && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
rc = integrity_load_cert(INTEGRITY_KEYRING_PLATFORM, source,
data, len, perm);

--
2.31.1


2023-08-13 05:29:07

by Nayna Jain

[permalink] [raw]
Subject: [PATCH v3 1/6] integrity: PowerVM support for loading CA keys on machine keyring

Keys that derive their trust from an entity such as a security officer,
administrator, system owner, or machine owner are said to have "imputed
trust". CA keys with imputed trust can be loaded onto the machine keyring.
The mechanism for loading these keys onto the machine keyring is platform
dependent.

Load keys stored in the variable trustedcadb onto the .machine keyring
on PowerVM platform.

Signed-off-by: Nayna Jain <[email protected]>
Reviewed-and-tested-by: Mimi Zohar <[email protected]>
---
.../integrity/platform_certs/keyring_handler.c | 8 ++++++++
.../integrity/platform_certs/keyring_handler.h | 5 +++++
.../integrity/platform_certs/load_powerpc.c | 17 +++++++++++++++++
3 files changed, 30 insertions(+)

diff --git a/security/integrity/platform_certs/keyring_handler.c b/security/integrity/platform_certs/keyring_handler.c
index 8a1124e4d769..1649d047e3b8 100644
--- a/security/integrity/platform_certs/keyring_handler.c
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -69,6 +69,14 @@ __init efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type)
return NULL;
}

+__init efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type)
+{
+ if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
+ return add_to_machine_keyring;
+
+ return NULL;
+}
+
/*
* Return the appropriate handler for particular signature list types found in
* the UEFI dbx and MokListXRT tables.
diff --git a/security/integrity/platform_certs/keyring_handler.h b/security/integrity/platform_certs/keyring_handler.h
index 212d894a8c0c..6f15bb4cc8dc 100644
--- a/security/integrity/platform_certs/keyring_handler.h
+++ b/security/integrity/platform_certs/keyring_handler.h
@@ -29,6 +29,11 @@ efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type);
*/
efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type);

+/*
+ * Return the handler for particular signature list types for CA keys.
+ */
+efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type);
+
/*
* Return the handler for particular signature list types found in the dbx.
*/
diff --git a/security/integrity/platform_certs/load_powerpc.c b/security/integrity/platform_certs/load_powerpc.c
index 170789dc63d2..6263ce3b3f1e 100644
--- a/security/integrity/platform_certs/load_powerpc.c
+++ b/security/integrity/platform_certs/load_powerpc.c
@@ -59,6 +59,7 @@ static __init void *get_cert_list(u8 *key, unsigned long keylen, u64 *size)
static int __init load_powerpc_certs(void)
{
void *db = NULL, *dbx = NULL, *data = NULL;
+ void *trustedca = NULL;
u64 dsize = 0;
u64 offset = 0;
int rc = 0;
@@ -120,6 +121,22 @@ static int __init load_powerpc_certs(void)
kfree(data);
}

+ data = get_cert_list("trustedcadb", 12, &dsize);
+ if (!data) {
+ pr_info("Couldn't get trustedcadb list from firmware\n");
+ } else if (IS_ERR(data)) {
+ rc = PTR_ERR(data);
+ pr_err("Error reading trustedcadb from firmware: %d\n", rc);
+ } else {
+ extract_esl(trustedca, data, dsize, offset);
+
+ rc = parse_efi_signature_list("powerpc:trustedca", trustedca, dsize,
+ get_handler_for_ca_keys);
+ if (rc)
+ pr_err("Couldn't parse trustedcadb signatures: %d\n", rc);
+ kfree(data);
+ }
+
return rc;
}
late_initcall(load_powerpc_certs);
--
2.31.1


2023-08-13 06:57:17

by Nayna Jain

[permalink] [raw]
Subject: [PATCH v3 4/6] integrity: check whether imputed trust is enabled

trust_moklist() is specific to UEFI enabled systems. Other platforms
rely only on the Kconfig.

Define a generic wrapper named imputed_trust_enabled().

Signed-off-by: Nayna Jain <[email protected]>
Reviewed-off-by: Mimi Zohar <[email protected]>
---
security/integrity/digsig.c | 2 +-
security/integrity/integrity.h | 5 +++--
.../integrity/platform_certs/keyring_handler.c | 3 ++-
.../integrity/platform_certs/machine_keyring.c | 18 ++++++++++++++++--
4 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index d0704b1597d4..df387de29bfa 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -113,7 +113,7 @@ static int __init __integrity_init_keyring(const unsigned int id,
} else {
if (id == INTEGRITY_KEYRING_PLATFORM)
set_platform_trusted_keys(keyring[id]);
- if (id == INTEGRITY_KEYRING_MACHINE && trust_moklist())
+ if (id == INTEGRITY_KEYRING_MACHINE && imputed_trust_enabled())
set_machine_trusted_keys(keyring[id]);
if (id == INTEGRITY_KEYRING_IMA)
load_module_cert(keyring[id]);
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 7167a6e99bdc..d7553c93f5c0 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -320,13 +320,14 @@ static inline void __init add_to_platform_keyring(const char *source,

#ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
void __init add_to_machine_keyring(const char *source, const void *data, size_t len);
-bool __init trust_moklist(void);
+bool __init imputed_trust_enabled(void);
#else
static inline void __init add_to_machine_keyring(const char *source,
const void *data, size_t len)
{
}
-static inline bool __init trust_moklist(void)
+
+static inline bool __init imputed_trust_enabled(void)
{
return false;
}
diff --git a/security/integrity/platform_certs/keyring_handler.c b/security/integrity/platform_certs/keyring_handler.c
index 1649d047e3b8..586027b9a3f5 100644
--- a/security/integrity/platform_certs/keyring_handler.c
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -61,7 +61,8 @@ __init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type)
__init efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type)
{
if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0) {
- if (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING) && trust_moklist())
+ if (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING) &&
+ imputed_trust_enabled())
return add_to_machine_keyring;
else
return add_to_platform_keyring;
diff --git a/security/integrity/platform_certs/machine_keyring.c b/security/integrity/platform_certs/machine_keyring.c
index 9482e16cb2ca..a401640a63cd 100644
--- a/security/integrity/platform_certs/machine_keyring.c
+++ b/security/integrity/platform_certs/machine_keyring.c
@@ -34,7 +34,8 @@ void __init add_to_machine_keyring(const char *source, const void *data, size_t
* If the restriction check does not pass and the platform keyring
* is configured, try to add it into that keyring instead.
*/
- if (rc && efi_enabled(EFI_BOOT) && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
+ if (rc && efi_enabled(EFI_BOOT) &&
+ IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
rc = integrity_load_cert(INTEGRITY_KEYRING_PLATFORM, source,
data, len, perm);

@@ -60,7 +61,7 @@ static __init bool uefi_check_trust_mok_keys(void)
return false;
}

-bool __init trust_moklist(void)
+static bool __init trust_moklist(void)
{
static bool initialized;
static bool trust_mok;
@@ -75,3 +76,16 @@ bool __init trust_moklist(void)

return trust_mok;
}
+
+/*
+ * Provides platform specific check for trusting imputed keys before loading
+ * on .machine keyring. UEFI systems enable this trust based on a variable,
+ * and for other platforms, it is always enabled.
+ */
+bool __init imputed_trust_enabled(void)
+{
+ if (efi_enabled(EFI_BOOT))
+ return trust_moklist();
+
+ return true;
+}
--
2.31.1


2023-08-13 10:02:57

by Nayna Jain

[permalink] [raw]
Subject: [PATCH v3 3/6] integrity: remove global variable from machine_keyring.c

trust_mok variable is accessed within a single function locally.

Change trust_mok from global to local static variable.

Signed-off-by: Nayna Jain <[email protected]>
Reviewed-and-tested-by: Mimi Zohar <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
---
security/integrity/platform_certs/machine_keyring.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/security/integrity/platform_certs/machine_keyring.c b/security/integrity/platform_certs/machine_keyring.c
index 389a6e7c9245..9482e16cb2ca 100644
--- a/security/integrity/platform_certs/machine_keyring.c
+++ b/security/integrity/platform_certs/machine_keyring.c
@@ -8,8 +8,6 @@
#include <linux/efi.h>
#include "../integrity.h"

-static bool trust_mok;
-
static __init int machine_keyring_init(void)
{
int rc;
@@ -65,9 +63,11 @@ static __init bool uefi_check_trust_mok_keys(void)
bool __init trust_moklist(void)
{
static bool initialized;
+ static bool trust_mok;

if (!initialized) {
initialized = true;
+ trust_mok = false;

if (uefi_check_trust_mok_keys())
trust_mok = true;
--
2.31.1


2023-08-14 18:25:49

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH v3 2/6] integrity: ignore keys failing CA restrictions on non-UEFI platform

On Sun Aug 13, 2023 at 5:15 AM EEST, Nayna Jain wrote:
> On non-UEFI platforms, handle restrict_link_by_ca failures differently.
>
> Certificates which do not satisfy CA restrictions on non-UEFI platforms
> are ignored.
>
> Signed-off-by: Nayna Jain <[email protected]>
> Reviewed-and-tested-by: Mimi Zohar <[email protected]>
> ---
> security/integrity/platform_certs/machine_keyring.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/security/integrity/platform_certs/machine_keyring.c b/security/integrity/platform_certs/machine_keyring.c
> index 7aaed7950b6e..389a6e7c9245 100644
> --- a/security/integrity/platform_certs/machine_keyring.c
> +++ b/security/integrity/platform_certs/machine_keyring.c
> @@ -36,7 +36,7 @@ void __init add_to_machine_keyring(const char *source, const void *data, size_t
> * If the restriction check does not pass and the platform keyring
> * is configured, try to add it into that keyring instead.
> */
> - if (rc && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
> + if (rc && efi_enabled(EFI_BOOT) && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
> rc = integrity_load_cert(INTEGRITY_KEYRING_PLATFORM, source,
> data, len, perm);
>
> --
> 2.31.1

Acked-by: Jarkko Sakkinen <[email protected]>

BR, Jarkko

2023-08-14 19:23:03

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH v3 1/6] integrity: PowerVM support for loading CA keys on machine keyring

On Sun Aug 13, 2023 at 5:15 AM EEST, Nayna Jain wrote:
> Keys that derive their trust from an entity such as a security officer,
> administrator, system owner, or machine owner are said to have "imputed
> trust". CA keys with imputed trust can be loaded onto the machine keyring.
> The mechanism for loading these keys onto the machine keyring is platform
> dependent.
>
> Load keys stored in the variable trustedcadb onto the .machine keyring
> on PowerVM platform.
>
> Signed-off-by: Nayna Jain <[email protected]>
> Reviewed-and-tested-by: Mimi Zohar <[email protected]>
> ---
> .../integrity/platform_certs/keyring_handler.c | 8 ++++++++
> .../integrity/platform_certs/keyring_handler.h | 5 +++++
> .../integrity/platform_certs/load_powerpc.c | 17 +++++++++++++++++
> 3 files changed, 30 insertions(+)
>
> diff --git a/security/integrity/platform_certs/keyring_handler.c b/security/integrity/platform_certs/keyring_handler.c
> index 8a1124e4d769..1649d047e3b8 100644
> --- a/security/integrity/platform_certs/keyring_handler.c
> +++ b/security/integrity/platform_certs/keyring_handler.c
> @@ -69,6 +69,14 @@ __init efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type)
> return NULL;
> }
>
> +__init efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type)
> +{
> + if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
> + return add_to_machine_keyring;
> +
> + return NULL;
> +}
> +
> /*
> * Return the appropriate handler for particular signature list types found in
> * the UEFI dbx and MokListXRT tables.
> diff --git a/security/integrity/platform_certs/keyring_handler.h b/security/integrity/platform_certs/keyring_handler.h
> index 212d894a8c0c..6f15bb4cc8dc 100644
> --- a/security/integrity/platform_certs/keyring_handler.h
> +++ b/security/integrity/platform_certs/keyring_handler.h
> @@ -29,6 +29,11 @@ efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type);
> */
> efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type);
>
> +/*
> + * Return the handler for particular signature list types for CA keys.
> + */
> +efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type);
> +
> /*
> * Return the handler for particular signature list types found in the dbx.
> */
> diff --git a/security/integrity/platform_certs/load_powerpc.c b/security/integrity/platform_certs/load_powerpc.c
> index 170789dc63d2..6263ce3b3f1e 100644
> --- a/security/integrity/platform_certs/load_powerpc.c
> +++ b/security/integrity/platform_certs/load_powerpc.c
> @@ -59,6 +59,7 @@ static __init void *get_cert_list(u8 *key, unsigned long keylen, u64 *size)
> static int __init load_powerpc_certs(void)
> {
> void *db = NULL, *dbx = NULL, *data = NULL;
> + void *trustedca = NULL;

Could this be just "void *trustedca;" ?

> u64 dsize = 0;
> u64 offset = 0;
> int rc = 0;
> @@ -120,6 +121,22 @@ static int __init load_powerpc_certs(void)
> kfree(data);
> }
>
> + data = get_cert_list("trustedcadb", 12, &dsize);
> + if (!data) {
> + pr_info("Couldn't get trustedcadb list from firmware\n");
> + } else if (IS_ERR(data)) {
> + rc = PTR_ERR(data);
> + pr_err("Error reading trustedcadb from firmware: %d\n", rc);
> + } else {
> + extract_esl(trustedca, data, dsize, offset);
> +
> + rc = parse_efi_signature_list("powerpc:trustedca", trustedca, dsize,
> + get_handler_for_ca_keys);
> + if (rc)
> + pr_err("Couldn't parse trustedcadb signatures: %d\n", rc);
> + kfree(data);
> + }
> +
> return rc;
> }
> late_initcall(load_powerpc_certs);
> --
> 2.31.1

BR, Jarkko

2023-08-16 22:55:11

by Jarkko Sakkinen

[permalink] [raw]
Subject: Re: [PATCH v3 2/6] integrity: ignore keys failing CA restrictions on non-UEFI platform

On Wed Aug 16, 2023 at 3:58 PM EEST, Mimi Zohar wrote:
> On Mon, 2023-08-14 at 20:38 +0300, Jarkko Sakkinen wrote:
> > On Sun Aug 13, 2023 at 5:15 AM EEST, Nayna Jain wrote:
> > > On non-UEFI platforms, handle restrict_link_by_ca failures differently.
> > >
> > > Certificates which do not satisfy CA restrictions on non-UEFI platforms
> > > are ignored.
> > >
> > > Signed-off-by: Nayna Jain <[email protected]>
> > > Reviewed-and-tested-by: Mimi Zohar <[email protected]>
> > > ---
> > > security/integrity/platform_certs/machine_keyring.c | 2 +-
> > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/security/integrity/platform_certs/machine_keyring.c b/security/integrity/platform_certs/machine_keyring.c
> > > index 7aaed7950b6e..389a6e7c9245 100644
> > > --- a/security/integrity/platform_certs/machine_keyring.c
> > > +++ b/security/integrity/platform_certs/machine_keyring.c
> > > @@ -36,7 +36,7 @@ void __init add_to_machine_keyring(const char *source, const void *data, size_t
> > > * If the restriction check does not pass and the platform keyring
> > > * is configured, try to add it into that keyring instead.
> > > */
> > > - if (rc && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
> > > + if (rc && efi_enabled(EFI_BOOT) && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
> > > rc = integrity_load_cert(INTEGRITY_KEYRING_PLATFORM, source,
> > > data, len, perm);
> > >
> > > --
> > > 2.31.1
> >
> > Acked-by: Jarkko Sakkinen <[email protected]>
>
> Hi Jarkko,
>
> Without the following two commits in your master branch, the last patch
> in this series "[PATCH v4 6/6] integrity: PowerVM support for loading
> third party code signing keys" doesn't apply cleanly.
>
> - commit 409b465f8a83 ("integrity: Enforce digitalSignature usage in
> the ima and evm keyrings")
> - commit e34a6c7dd192 ("KEYS: DigitalSignature link restriction")
>
> If you're not planning on upstreaming this patch set, I'd appreciate
> your creating a topic branch with these two commits.

They reside now in my -next. I'll send PR for the next release Fri.

> --
> thanks,
>
> Mimi

BR, Jarkko