[PATCH v4] powerpc/pseries: make max polling consistent for longer H_CALLs

2024-04-17 Thread Nayna Jain
Currently, plpks_confirm_object_flushed() function polls for 5msec in
total instead of 5sec.

Keep max polling time consistent for all the H_CALLs, which take longer
than expected, to be 5sec. Also, make use of fsleep() everywhere to
insert delay.

Reported-by: Nageswara R Sastry 
Fixes: 2454a7af0f2a ("powerpc/pseries: define driver for Platform KeyStore")
Signed-off-by: Nayna Jain 
Tested-by: Nageswara R Sastry 
---
v4:
 * As per Andrew's feedback, squashed Patch 2 with Patch 1.
Now it is single patch.

v3:
 * Addition to Patch 1 timeout patch based on Andrew's feedback.

v2:
* Updated based on feedback from Michael Ellerman
Replaced usleep_range with fsleep.
Since there is no more need to specify range, sleep time is
reverted back to 10 msec.

 arch/powerpc/include/asm/plpks.h   |  5 ++---
 arch/powerpc/platforms/pseries/plpks.c | 10 +-
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
index 23b77027c916..7a84069759b0 100644
--- a/arch/powerpc/include/asm/plpks.h
+++ b/arch/powerpc/include/asm/plpks.h
@@ -44,9 +44,8 @@
 #define PLPKS_MAX_DATA_SIZE4000
 
 // Timeouts for PLPKS operations
-#define PLPKS_MAX_TIMEOUT  5000 // msec
-#define PLPKS_FLUSH_SLEEP  10 // msec
-#define PLPKS_FLUSH_SLEEP_RANGE400
+#define PLPKS_MAX_TIMEOUT  (5 * USEC_PER_SEC)
+#define PLPKS_FLUSH_SLEEP  1 // usec
 
 struct plpks_var {
char *component;
diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
index febe18f251d0..4a595493d28a 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -415,8 +415,7 @@ static int plpks_confirm_object_flushed(struct label *label,
break;
}
 
-   usleep_range(PLPKS_FLUSH_SLEEP,
-PLPKS_FLUSH_SLEEP + PLPKS_FLUSH_SLEEP_RANGE);
+   fsleep(PLPKS_FLUSH_SLEEP);
timeout = timeout + PLPKS_FLUSH_SLEEP;
} while (timeout < PLPKS_MAX_TIMEOUT);
 
@@ -464,9 +463,10 @@ int plpks_signed_update_var(struct plpks_var *var, u64 
flags)
 
continuetoken = retbuf[0];
if (pseries_status_to_err(rc) == -EBUSY) {
-   int delay_ms = get_longbusy_msecs(rc);
-   mdelay(delay_ms);
-   timeout += delay_ms;
+   int delay_us = get_longbusy_msecs(rc) * 1000;
+
+   fsleep(delay_us);
+   timeout += delay_us;
}
rc = pseries_status_to_err(rc);
} while (rc == -EBUSY && timeout < PLPKS_MAX_TIMEOUT);
-- 
2.31.1



[PATCH v3 2/2] powerpc/pseries: increase timeout value for plpks_signed_update_var() H_CALL

2024-03-28 Thread Nayna Jain
Signed update H_CALL currently polls PHYP for 5msec. Update this to
5sec.

Signed-off-by: Nayna Jain 
Tested-by: Nageswara R Sastry 
---
v3:
 * Addition to Patch 1 timeout patch based on Andrew's feedback.

 arch/powerpc/platforms/pseries/plpks.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
index bcfcd5acc5c2..4a595493d28a 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -463,9 +463,10 @@ int plpks_signed_update_var(struct plpks_var *var, u64 
flags)
 
continuetoken = retbuf[0];
if (pseries_status_to_err(rc) == -EBUSY) {
-   int delay_ms = get_longbusy_msecs(rc);
-   mdelay(delay_ms);
-   timeout += delay_ms;
+   int delay_us = get_longbusy_msecs(rc) * 1000;
+
+   fsleep(delay_us);
+   timeout += delay_us;
}
rc = pseries_status_to_err(rc);
} while (rc == -EBUSY && timeout < PLPKS_MAX_TIMEOUT);
-- 
2.31.1



[PATCH v3 1/2] powerpc/pseries: fix max polling time in plpks_confirm_object_flushed() function

2024-03-28 Thread Nayna Jain
usleep_range() function takes input time and range in usec. However,
currently it is assumed in msec in the function
plpks_confirm_object_flushed().

Fix the total polling time for the object flushing from 5msec to 5sec.

Reported-by: Nageswara R Sastry 
Fixes: 2454a7af0f2a ("powerpc/pseries: define driver for Platform KeyStore")
Signed-off-by: Nayna Jain 
Tested-by: Nageswara R Sastry 
---
v3:
No change

v2:
* Updated based on feedback from Michael Ellerman
Replaced usleep_range with fsleep.
Since there is no more need to specify range, sleep time is
reverted back to 10 msec.

 arch/powerpc/include/asm/plpks.h   | 5 ++---
 arch/powerpc/platforms/pseries/plpks.c | 3 +--
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
index 23b77027c916..7a84069759b0 100644
--- a/arch/powerpc/include/asm/plpks.h
+++ b/arch/powerpc/include/asm/plpks.h
@@ -44,9 +44,8 @@
 #define PLPKS_MAX_DATA_SIZE4000
 
 // Timeouts for PLPKS operations
-#define PLPKS_MAX_TIMEOUT  5000 // msec
-#define PLPKS_FLUSH_SLEEP  10 // msec
-#define PLPKS_FLUSH_SLEEP_RANGE400
+#define PLPKS_MAX_TIMEOUT  (5 * USEC_PER_SEC)
+#define PLPKS_FLUSH_SLEEP  1 // usec
 
 struct plpks_var {
char *component;
diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
index febe18f251d0..bcfcd5acc5c2 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -415,8 +415,7 @@ static int plpks_confirm_object_flushed(struct label *label,
break;
}
 
-   usleep_range(PLPKS_FLUSH_SLEEP,
-PLPKS_FLUSH_SLEEP + PLPKS_FLUSH_SLEEP_RANGE);
+   fsleep(PLPKS_FLUSH_SLEEP);
timeout = timeout + PLPKS_FLUSH_SLEEP;
} while (timeout < PLPKS_MAX_TIMEOUT);
 
-- 
2.31.1



[PATCH v2] powerpc/pseries: fix max polling time in plpks_confirm_object_flushed() function

2024-03-13 Thread Nayna Jain
usleep_range() function takes input time and range in usec. However,
currently it is assumed in msec in the function
plpks_confirm_object_flushed().

Fix the total polling time for the object flushing from 5msec to 5sec.

Reported-by: Nageswara R Sastry 
Fixes: 2454a7af0f2a ("powerpc/pseries: define driver for Platform KeyStore")
Suggested-by: Michael Ellerman 
Signed-off-by: Nayna Jain 
Tested-by: Nageswara R Sastry 
---
v2:
* Updated based on feedback from Michael Ellerman
Replaced usleep_range with fsleep.
Since there is no more need to specify range, sleep time is
reverted back to 10 msec.

 arch/powerpc/include/asm/plpks.h   | 5 ++---
 arch/powerpc/platforms/pseries/plpks.c | 3 +--
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
index 23b77027c916..7a84069759b0 100644
--- a/arch/powerpc/include/asm/plpks.h
+++ b/arch/powerpc/include/asm/plpks.h
@@ -44,9 +44,8 @@
 #define PLPKS_MAX_DATA_SIZE4000
 
 // Timeouts for PLPKS operations
-#define PLPKS_MAX_TIMEOUT  5000 // msec
-#define PLPKS_FLUSH_SLEEP  10 // msec
-#define PLPKS_FLUSH_SLEEP_RANGE400
+#define PLPKS_MAX_TIMEOUT  (5 * USEC_PER_SEC)
+#define PLPKS_FLUSH_SLEEP  1 // usec
 
 struct plpks_var {
char *component;
diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
index febe18f251d0..bcfcd5acc5c2 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -415,8 +415,7 @@ static int plpks_confirm_object_flushed(struct label *label,
break;
}
 
-   usleep_range(PLPKS_FLUSH_SLEEP,
-PLPKS_FLUSH_SLEEP + PLPKS_FLUSH_SLEEP_RANGE);
+   fsleep(PLPKS_FLUSH_SLEEP);
timeout = timeout + PLPKS_FLUSH_SLEEP;
} while (timeout < PLPKS_MAX_TIMEOUT);
 
-- 
2.31.1



[PATCH] powerpc/pseries: fix max polling time in plpks_confirm_object_flushed() function

2024-03-03 Thread Nayna Jain
usleep_range() function takes input time and range in usec. However,
currently it is assumed in msec in the function
plpks_confirm_object_flushed().

Fix the total polling time for the object flushing from 5msec to 5sec.

Reported-by: Nageswara R Sastry 
Fixes: 2454a7af0f2a ("powerpc/pseries: define driver for Platform KeyStore")
Signed-off-by: Nayna Jain 
Tested-by: Nageswara R Sastry 
---
 arch/powerpc/include/asm/plpks.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
index 23b77027c916..8721d97f32c1 100644
--- a/arch/powerpc/include/asm/plpks.h
+++ b/arch/powerpc/include/asm/plpks.h
@@ -44,9 +44,9 @@
 #define PLPKS_MAX_DATA_SIZE4000
 
 // Timeouts for PLPKS operations
-#define PLPKS_MAX_TIMEOUT  5000 // msec
-#define PLPKS_FLUSH_SLEEP  10 // msec
-#define PLPKS_FLUSH_SLEEP_RANGE400
+#define PLPKS_MAX_TIMEOUT  500 // usec
+#define PLPKS_FLUSH_SLEEP  5000 // usec
+#define PLPKS_FLUSH_SLEEP_RANGE5000
 
 struct plpks_var {
char *component;
-- 
2.31.1



[PATCH v4 5/6] integrity: PowerVM machine keyring enablement

2023-08-15 Thread Nayna Jain
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 
Reviewed-and-tested-by: Mimi Zohar 
Reviewed-by: Jarkko Sakkinen 
---
 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



[PATCH v4 1/6] integrity: PowerVM support for loading CA keys on machine keyring

2023-08-15 Thread Nayna Jain
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 
Reviewed-and-tested-by: Mimi Zohar 
---
 .../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..339053d9726d 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;
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,  );
+   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



[PATCH v4 0/6] Enable loading local and third party keys on PowerVM guest

2023-08-15 Thread Nayna Jain
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:

v4:

* Fixed build error reported by Nageswara R Sastry
, as part of his testing of patches.
* Included Jarkko's and Mimi's feedback

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 |  4 +++
 security/integrity/Kconfig|  4 ++-
 security/integrity/digsig.c   |  2 +-
 security/integrity/integrity.h|  5 +--
 .../platform_certs/keyring_handler.c  | 19 ++-
 .../platform_certs/keyring_handler.h  | 10 ++
 .../integrity/platform_certs/load_powerpc.c   | 34 +++
 .../platform_certs/machine_keyring.c  | 22 +---
 9 files changed, 121 insertions(+), 9 deletions(-)

-- 
2.31.1


[PATCH v4 4/6] integrity: check whether imputed trust is enabled

2023-08-15 Thread Nayna Jain
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 
Reviewed-off-by: Mimi Zohar 
---
 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



[PATCH v4 6/6] integrity: PowerVM support for loading third party code signing keys

2023-08-15 Thread Nayna Jain
On secure boot enabled PowerVM LPAR, third party code signing keys are
needed during early boot to verify signed third party modules. These
third party keys are stored in moduledb object in the Platform
KeyStore (PKS).

Load third party code signing keys onto .secondary_trusted_keys keyring.

Signed-off-by: Nayna Jain 
---
 certs/system_keyring.c| 30 +++
 include/keys/system_keyring.h |  4 +++
 .../platform_certs/keyring_handler.c  |  8 +
 .../platform_certs/keyring_handler.h  |  5 
 .../integrity/platform_certs/load_powerpc.c   | 17 +++
 5 files changed, 64 insertions(+)

diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index b348e0898d34..33841c91f12c 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -152,6 +152,36 @@ static __init struct key_restriction 
*get_builtin_and_secondary_restriction(void
 
return restriction;
 }
+
+/**
+ * add_to_secondary_keyring - Add to secondary keyring.
+ * @source: Source of key
+ * @data: The blob holding the key
+ * @len: The length of the data blob
+ *
+ * Add a key to the secondary keyring. The key must be vouched for by a key in 
the builtin,
+ * machine or secondary keyring itself.
+ */
+void __init add_to_secondary_keyring(const char *source, const void *data, 
size_t len)
+{
+   key_ref_t key;
+   key_perm_t perm;
+
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW;
+
+   key = key_create_or_update(make_key_ref(secondary_trusted_keys, 1),
+  "asymmetric",
+  NULL, data, len, perm,
+  KEY_ALLOC_NOT_IN_QUOTA);
+   if (IS_ERR(key)) {
+   pr_err("Problem loading X.509 certificate from %s to secondary 
keyring %ld\n",
+  source, PTR_ERR(key));
+   return;
+   }
+
+   pr_notice("Loaded X.509 cert '%s'\n", key_ref_to_ptr(key)->description);
+   key_ref_put(key);
+}
 #endif
 #ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
 void __init set_machine_trusted_keys(struct key *keyring)
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 7e2583208820..8365adf842ef 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -50,9 +50,13 @@ int restrict_link_by_digsig_builtin_and_secondary(struct key 
*keyring,
  const struct key_type *type,
  const union key_payload 
*payload,
  struct key *restriction_key);
+void __init add_to_secondary_keyring(const char *source, const void *data, 
size_t len);
 #else
 #define restrict_link_by_builtin_and_secondary_trusted 
restrict_link_by_builtin_trusted
 #define restrict_link_by_digsig_builtin_and_secondary 
restrict_link_by_digsig_builtin
+static inline void __init add_to_secondary_keyring(const char *source, const 
void *data, size_t len)
+{
+}
 #endif
 
 #ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
diff --git a/security/integrity/platform_certs/keyring_handler.c 
b/security/integrity/platform_certs/keyring_handler.c
index 586027b9a3f5..13ea17207902 100644
--- a/security/integrity/platform_certs/keyring_handler.c
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -78,6 +78,14 @@ __init efi_element_handler_t get_handler_for_ca_keys(const 
efi_guid_t *sig_type)
return NULL;
 }
 
+__init efi_element_handler_t get_handler_for_code_signing_keys(const 
efi_guid_t *sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
+   return add_to_secondary_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 6f15bb4cc8dc..f92895cc50f6 100644
--- a/security/integrity/platform_certs/keyring_handler.h
+++ b/security/integrity/platform_certs/keyring_handler.h
@@ -34,6 +34,11 @@ efi_element_handler_t get_handler_for_mok(const efi_guid_t 
*sig_type);
  */
 efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type);
 
+/*
+ * Return the handler for particular signature list types for code signing 
keys.
+ */
+efi_element_handler_t get_handler_for_code_signing_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 339053d9726d..c85febca3343 100644
--- a/security/integrity/platform_certs/load_powerpc.c
+++ b/security/integrity/platform_certs/load_powerpc.c
@@ -60,6 +60,7 @@ static int __init load_powerpc_certs(void)
 {
void *db = NULL, *dbx = NULL, *data = NULL;

[PATCH v4 3/6] integrity: remove global variable from machine_keyring.c

2023-08-15 Thread Nayna Jain
trust_mok variable is accessed within a single function locally.

Change trust_mok from global to local static variable.

Signed-off-by: Nayna Jain 
Reviewed-and-tested-by: Mimi Zohar 
Reviewed-by: Jarkko Sakkinen 
---
 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 
 #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



[PATCH v4 2/6] integrity: ignore keys failing CA restrictions on non-UEFI platform

2023-08-15 Thread Nayna Jain
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 
Reviewed-and-tested-by: Mimi Zohar 
Acked-by: Jarkko Sakkinen 
---
 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



[PATCH v3 6/6] integrity: PowerVM support for loading third party code signing keys

2023-08-12 Thread Nayna Jain
On secure boot enabled PowerVM LPAR, third party code signing keys are
needed during early boot to verify signed third party modules. These
third party keys are stored in moduledb object in the Platform
KeyStore(PKS).

Load third party code signing keys onto .secondary_trusted_keys keyring.

Signed-off-by: Nayna Jain 
---
 certs/system_keyring.c| 30 +++
 include/keys/system_keyring.h |  7 +
 security/integrity/integrity.h|  1 +
 .../platform_certs/keyring_handler.c  |  8 +
 .../platform_certs/keyring_handler.h  |  5 
 .../integrity/platform_certs/load_powerpc.c   | 18 ++-
 6 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index b348e0898d34..e458d414918d 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -396,3 +396,33 @@ void __init set_platform_trusted_keys(struct key *keyring)
platform_trusted_keys = keyring;
 }
 #endif
+
+/**
+ * add_to_secondary_keyring - Add to secondary keyring.
+ * @source: Source of key
+ * @data: The blob holding the key
+ * @len: The length of the data blob
+ *
+ * Add a key to the secondary keyring. The key must be vouched for by a key in 
the builtin,
+ * machine or secondary keyring itself.
+ */
+void __init add_to_secondary_keyring(const char *source, const void *data, 
size_t len)
+{
+   key_ref_t key;
+   key_perm_t perm;
+
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW;
+
+   key = key_create_or_update(make_key_ref(secondary_trusted_keys, 1),
+  "asymmetric",
+  NULL, data, len, perm,
+  KEY_ALLOC_NOT_IN_QUOTA);
+   if (IS_ERR(key)) {
+   pr_err("Problem loading X.509 certificate from %s to secondary 
keyring %ld\n",
+  source, PTR_ERR(key));
+   return;
+   }
+
+   pr_notice("Loaded X.509 cert '%s'\n", key_ref_to_ptr(key)->description);
+   key_ref_put(key);
+}
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 7e2583208820..4188f75d1bac 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -50,9 +50,16 @@ int restrict_link_by_digsig_builtin_and_secondary(struct key 
*keyring,
  const struct key_type *type,
  const union key_payload 
*payload,
  struct key *restriction_key);
+void __init add_to_secondary_keyring(const char *source, const void *data,
+size_t len);
+
 #else
 #define restrict_link_by_builtin_and_secondary_trusted 
restrict_link_by_builtin_trusted
 #define restrict_link_by_digsig_builtin_and_secondary 
restrict_link_by_digsig_builtin
+void __init add_to_secondary_keyring(const char *source, const void *data,
+size_t len)
+{
+}
 #endif
 
 #ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index d7553c93f5c0..efaa2eb789ad 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -228,6 +228,7 @@ static inline int __init integrity_load_cert(const unsigned 
int id,
 {
return 0;
 }
+
 #endif /* CONFIG_INTEGRITY_SIGNATURE */
 
 #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
diff --git a/security/integrity/platform_certs/keyring_handler.c 
b/security/integrity/platform_certs/keyring_handler.c
index 586027b9a3f5..13ea17207902 100644
--- a/security/integrity/platform_certs/keyring_handler.c
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -78,6 +78,14 @@ __init efi_element_handler_t get_handler_for_ca_keys(const 
efi_guid_t *sig_type)
return NULL;
 }
 
+__init efi_element_handler_t get_handler_for_code_signing_keys(const 
efi_guid_t *sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
+   return add_to_secondary_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 6f15bb4cc8dc..f92895cc50f6 100644
--- a/security/integrity/platform_certs/keyring_handler.h
+++ b/security/integrity/platform_certs/keyring_handler.h
@@ -34,6 +34,11 @@ efi_element_handler_t get_handler_for_mok(const efi_guid_t 
*sig_type);
  */
 efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type);
 
+/*
+ * Return the handler for particular signature list types for code signing 
keys.
+ */
+efi_element_handler_t get_handler_for_code_signing_keys(const efi_guid_t 
*sig_type);
+
 /*
  * Return the handler for particular signature l

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

2023-08-12 Thread Nayna Jain
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 
Reviewed-and-tested-by: Mimi Zohar 
Reviewed-by: Jarkko Sakkinen 
---
 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



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

2023-08-12 Thread Nayna Jain
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 
Reviewed-and-tested-by: Mimi Zohar 
---
 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



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

2023-08-12 Thread Nayna Jain
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 
Reviewed-off-by: Mimi Zohar 
---
 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



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

2023-08-12 Thread Nayna Jain
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 
Reviewed-and-tested-by: Mimi Zohar 
---
 .../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,  );
+   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



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

2023-08-12 Thread Nayna Jain
trust_mok variable is accessed within a single function locally.

Change trust_mok from global to local static variable.

Signed-off-by: Nayna Jain 
Reviewed-and-tested-by: Mimi Zohar 
Reviewed-by: Jarkko Sakkinen 
---
 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 
 #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



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

2023-08-12 Thread Nayna Jain
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


[PATCH v2 1/6] integrity: PowerVM support for loading CA keys on machine keyring

2023-08-09 Thread Nayna Jain
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 
Reviewed-and-tested-by: Mimi Zohar 
---
 .../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,  );
+   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



[PATCH v2 6/6] integrity: PowerVM support for loading third party code signing keys

2023-08-09 Thread Nayna Jain
On secure boot enabled PowerVM LPAR, third party code signing keys are
needed during early boot to verify signed third party modules. These
third party keys are stored in moduledb object in the Platform
KeyStore(PKS).

Load third party code signing keys onto .secondary_trusted_keys keyring.

Signed-off-by: Nayna Jain 
---
 certs/system_keyring.c| 23 +++
 include/keys/system_keyring.h |  7 ++
 security/integrity/integrity.h|  1 +
 .../platform_certs/keyring_handler.c  |  8 +++
 .../platform_certs/keyring_handler.h  |  5 
 .../integrity/platform_certs/load_powerpc.c   | 18 ++-
 6 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index b348e0898d34..3435d4936fb2 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -396,3 +396,26 @@ void __init set_platform_trusted_keys(struct key *keyring)
platform_trusted_keys = keyring;
 }
 #endif
+
+void __init add_to_secondary_keyring(const char *source, const void *data,
+size_t len)
+{
+   key_ref_t key;
+   key_perm_t perm;
+   int rc = 0;
+
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW;
+
+   key = key_create_or_update(make_key_ref(secondary_trusted_keys, 1),
+  "asymmetric",
+  NULL, data, len, perm,
+  KEY_ALLOC_NOT_IN_QUOTA);
+   if (IS_ERR(key)) {
+   rc = PTR_ERR(key);
+   pr_err("Problem loading X.509 certificate %d\n", rc);
+   } else {
+   pr_notice("Loaded X.509 cert '%s'\n",
+ key_ref_to_ptr(key)->description);
+   key_ref_put(key);
+   }
+}
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 7e2583208820..4188f75d1bac 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -50,9 +50,16 @@ int restrict_link_by_digsig_builtin_and_secondary(struct key 
*keyring,
  const struct key_type *type,
  const union key_payload 
*payload,
  struct key *restriction_key);
+void __init add_to_secondary_keyring(const char *source, const void *data,
+size_t len);
+
 #else
 #define restrict_link_by_builtin_and_secondary_trusted 
restrict_link_by_builtin_trusted
 #define restrict_link_by_digsig_builtin_and_secondary 
restrict_link_by_digsig_builtin
+void __init add_to_secondary_keyring(const char *source, const void *data,
+size_t len)
+{
+}
 #endif
 
 #ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index d7553c93f5c0..efaa2eb789ad 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -228,6 +228,7 @@ static inline int __init integrity_load_cert(const unsigned 
int id,
 {
return 0;
 }
+
 #endif /* CONFIG_INTEGRITY_SIGNATURE */
 
 #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
diff --git a/security/integrity/platform_certs/keyring_handler.c 
b/security/integrity/platform_certs/keyring_handler.c
index 586027b9a3f5..13ea17207902 100644
--- a/security/integrity/platform_certs/keyring_handler.c
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -78,6 +78,14 @@ __init efi_element_handler_t get_handler_for_ca_keys(const 
efi_guid_t *sig_type)
return NULL;
 }
 
+__init efi_element_handler_t get_handler_for_code_signing_keys(const 
efi_guid_t *sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
+   return add_to_secondary_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 6f15bb4cc8dc..f92895cc50f6 100644
--- a/security/integrity/platform_certs/keyring_handler.h
+++ b/security/integrity/platform_certs/keyring_handler.h
@@ -34,6 +34,11 @@ efi_element_handler_t get_handler_for_mok(const efi_guid_t 
*sig_type);
  */
 efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type);
 
+/*
+ * Return the handler for particular signature list types for code signing 
keys.
+ */
+efi_element_handler_t get_handler_for_code_signing_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 6263ce3b3f1e..32c4e5fbf0fb 100644
--- a/security/integrity/platform_certs/load_powerpc.c
++

[PATCH v2 5/6] integrity: PowerVM machine keyring enablement

2023-08-09 Thread Nayna Jain
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 
Reviewed-and-tested-by: Mimi Zohar 

---
 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



[PATCH v2 4/6] integrity: check whether imputed trust is enabled

2023-08-09 Thread Nayna Jain
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 
Reviewed-off-by: Mimi Zohar 
---
 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



[PATCH v2 3/6] integrity: remove global variable from machine_keyring.c

2023-08-09 Thread Nayna Jain
trust_mok variable is accessed within a single function locally.

Change trust_mok from global to local static variable.

Signed-off-by: Nayna Jain 
Reviewed-and-tested-by: Mimi Zohar 
---
 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 
 #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



[PATCH v2 2/6] integrity: ignore keys failing CA restrictions on non-UEFI platform

2023-08-09 Thread Nayna Jain
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 
Reviewed-and-tested-by: Mimi Zohar 
---
 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



[PATCH v2 0/6] Enable loading local and third party keys on PowerVM guest

2023-08-09 Thread Nayna Jain
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:

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| 23 +
 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, 117 insertions(+), 9 deletions(-)

-- 
2.31.1


[PATCH 6/6] integrity: PowerVM support for loading third party code signing keys

2023-07-14 Thread Nayna Jain
On secure boot enabled PowerVM LPAR, third party code signing keys are
needed during early boot to verify signed third party modules. These
third party keys are stored in moduledb object in the Platform
KeyStore(PKS).

Load third party code signing keys onto .secondary_trusted_keys keyring.

Signed-off-by: Nayna Jain 
---
Jarkko, this patch is based on Linus master tree branch, which does
not contain the following commits yet:

c9d004712300 integrity: Enforce digitalSignature usage in the ima and
evm keyrings
59b656eb58fe KEYS: DigitalSignature link restriction

 certs/system_keyring.c| 22 +++
 include/keys/system_keyring.h |  8 +++
 security/integrity/integrity.h|  1 +
 .../platform_certs/keyring_handler.c  |  8 +++
 .../platform_certs/keyring_handler.h  |  5 +
 .../integrity/platform_certs/load_powerpc.c   | 18 ++-
 6 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index a7a49b17ceb1..b0235732c1d4 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -347,3 +347,25 @@ void __init set_platform_trusted_keys(struct key *keyring)
platform_trusted_keys = keyring;
 }
 #endif
+
+void __init add_to_secondary_keyring(const char *source, const void *data,
+size_t len)
+{
+   key_ref_t key;
+   key_perm_t perm;
+   int rc = 0;
+
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW;
+
+   key = key_create_or_update(make_key_ref(secondary_trusted_keys, 1), 
"asymmetric",
+  NULL, data, len, perm,
+  KEY_ALLOC_NOT_IN_QUOTA);
+   if (IS_ERR(key)) {
+   rc = PTR_ERR(key);
+   pr_err("Problem loading X.509 certificate %d\n", rc);
+   } else {
+   pr_notice("Loaded X.509 cert '%s'\n",
+ key_ref_to_ptr(key)->description);
+   key_ref_put(key);
+   }
+}
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 91e080efb918..a57a77ccf003 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -41,8 +41,16 @@ extern int restrict_link_by_builtin_and_secondary_trusted(
const struct key_type *type,
const union key_payload *payload,
struct key *restriction_key);
+
+void __init add_to_secondary_keyring(const char *source, const void *data,
+size_t len);
+
 #else
 #define restrict_link_by_builtin_and_secondary_trusted 
restrict_link_by_builtin_trusted
+void __init add_to_secondary_keyring(const char *source, const void *data,
+size_t len)
+{
+}
 #endif
 
 #ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index d7553c93f5c0..efaa2eb789ad 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -228,6 +228,7 @@ static inline int __init integrity_load_cert(const unsigned 
int id,
 {
return 0;
 }
+
 #endif /* CONFIG_INTEGRITY_SIGNATURE */
 
 #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
diff --git a/security/integrity/platform_certs/keyring_handler.c 
b/security/integrity/platform_certs/keyring_handler.c
index b3e5df136e50..6095df043498 100644
--- a/security/integrity/platform_certs/keyring_handler.c
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -77,6 +77,14 @@ __init efi_element_handler_t get_handler_for_ca_keys(const 
efi_guid_t *sig_type)
return NULL;
 }
 
+__init efi_element_handler_t get_handler_for_code_signing_keys(const 
efi_guid_t *sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
+   return add_to_secondary_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 6f15bb4cc8dc..f92895cc50f6 100644
--- a/security/integrity/platform_certs/keyring_handler.h
+++ b/security/integrity/platform_certs/keyring_handler.h
@@ -34,6 +34,11 @@ efi_element_handler_t get_handler_for_mok(const efi_guid_t 
*sig_type);
  */
 efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type);
 
+/*
+ * Return the handler for particular signature list types for code signing 
keys.
+ */
+efi_element_handler_t get_handler_for_code_signing_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 6263ce3b3f1e..32c4e5fbf0fb 100644
--- a/security/integrity/platform_certs/load_powerpc.c
+++ b/security/in

[PATCH 5/6] integrity: PowerVM machine keyring enablement.

2023-07-14 Thread Nayna Jain
Update Kconfig to enable machine keyring and limit to CA certificates
on PowerVM.

Signed-off-by: Nayna Jain 
---
 security/integrity/Kconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index ec6e0d789da1..03c40ade0214 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -67,7 +67,8 @@ 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
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



[PATCH 4/6] integrity: check whether imputed trust is enabled

2023-07-14 Thread Nayna Jain
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 
---
 security/integrity/digsig.c   |  2 +-
 security/integrity/integrity.h|  5 +++--
 .../integrity/platform_certs/keyring_handler.c|  2 +-
 .../integrity/platform_certs/machine_keyring.c| 15 ++-
 4 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 6f31ffe23c48..48d505cacd81 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..b3e5df136e50 100644
--- a/security/integrity/platform_certs/keyring_handler.c
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -61,7 +61,7 @@ __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..58cd72b193e6 100644
--- a/security/integrity/platform_certs/machine_keyring.c
+++ b/security/integrity/platform_certs/machine_keyring.c
@@ -60,7 +60,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 +75,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



[PATCH 3/6] integrity: remove global variable from machine_keyring.c

2023-07-14 Thread Nayna Jain
trust_mok variable is accessed within a single function locally.

Change trust_mok from global to local static variable.

Signed-off-by: Nayna Jain 
---
 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 
 #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



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

2023-07-14 Thread Nayna Jain
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 
---
 .../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,  );
+   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



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

2023-07-14 Thread Nayna Jain
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 
---
 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



[PATCH 0/6] Enable loading local and third party keys on PowerVM guest

2023-07-14 Thread Nayna Jain
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.

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| 22 +
 include/keys/system_keyring.h |  8 +
 security/integrity/Kconfig|  3 +-
 security/integrity/digsig.c   |  2 +-
 security/integrity/integrity.h|  6 ++--
 .../platform_certs/keyring_handler.c  | 18 +-
 .../platform_certs/keyring_handler.h  | 10 ++
 .../integrity/platform_certs/load_powerpc.c   | 33 +++
 .../platform_certs/machine_keyring.c  | 21 +---
 9 files changed, 114 insertions(+), 9 deletions(-)


base-commit: 06c2afb862f9da8dc5efa4b6076a0e48c3fbaaa5
-- 
2.31.1


[PATCH v2] security/integrity: fix pointer to ESL data and its size on pseries

2023-06-08 Thread Nayna Jain
On PowerVM guest, variable data is prefixed with 8 bytes of timestamp.
Extract ESL by stripping off the timestamp before passing to ESL parser.

Fixes: 4b3e71e9a34c ("integrity/powerpc: Support loading keys from PLPKS")
Cc: sta...@vger.kenrnel.org # v6.3
Signed-off-by: Nayna Jain 
---
Changelog:
v2: Fixed feedback from Jarkko
  * added CC to stable
  * moved *data declaration to same line as *db,*dbx
Renamed extract_data() macro to extract_esl() for clarity
 .../integrity/platform_certs/load_powerpc.c   | 40 ---
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/security/integrity/platform_certs/load_powerpc.c 
b/security/integrity/platform_certs/load_powerpc.c
index b9de70b90826..170789dc63d2 100644
--- a/security/integrity/platform_certs/load_powerpc.c
+++ b/security/integrity/platform_certs/load_powerpc.c
@@ -15,6 +15,9 @@
 #include "keyring_handler.h"
 #include "../integrity.h"
 
+#define extract_esl(db, data, size, offset)\
+   do { db = data + offset; size = size - offset; } while (0)
+
 /*
  * Get a certificate list blob from the named secure variable.
  *
@@ -55,8 +58,9 @@ 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;
-   u64 dbsize = 0, dbxsize = 0;
+   void *db = NULL, *dbx = NULL, *data = NULL;
+   u64 dsize = 0;
+   u64 offset = 0;
int rc = 0;
ssize_t len;
char buf[32];
@@ -74,38 +78,46 @@ static int __init load_powerpc_certs(void)
return -ENODEV;
}
 
+   if (strcmp("ibm,plpks-sb-v1", buf) == 0)
+   /* PLPKS authenticated variables ESL data is prefixed with 8 
bytes of timestamp */
+   offset = 8;
+
/*
 * Get db, and dbx. They might not exist, so it isn't an error if we
 * can't get them.
 */
-   db = get_cert_list("db", 3, );
-   if (!db) {
+   data = get_cert_list("db", 3, );
+   if (!data) {
pr_info("Couldn't get db list from firmware\n");
-   } else if (IS_ERR(db)) {
-   rc = PTR_ERR(db);
+   } else if (IS_ERR(data)) {
+   rc = PTR_ERR(data);
pr_err("Error reading db from firmware: %d\n", rc);
return rc;
} else {
-   rc = parse_efi_signature_list("powerpc:db", db, dbsize,
+   extract_esl(db, data, dsize, offset);
+
+   rc = parse_efi_signature_list("powerpc:db", db, dsize,
  get_handler_for_db);
if (rc)
pr_err("Couldn't parse db signatures: %d\n", rc);
-   kfree(db);
+   kfree(data);
}
 
-   dbx = get_cert_list("dbx", 4,  );
-   if (!dbx) {
+   data = get_cert_list("dbx", 4,  );
+   if (!data) {
pr_info("Couldn't get dbx list from firmware\n");
-   } else if (IS_ERR(dbx)) {
-   rc = PTR_ERR(dbx);
+   } else if (IS_ERR(data)) {
+   rc = PTR_ERR(data);
pr_err("Error reading dbx from firmware: %d\n", rc);
return rc;
} else {
-   rc = parse_efi_signature_list("powerpc:dbx", dbx, dbxsize,
+   extract_esl(dbx, data, dsize, offset);
+
+   rc = parse_efi_signature_list("powerpc:dbx", dbx, dsize,
  get_handler_for_dbx);
if (rc)
pr_err("Couldn't parse dbx signatures: %d\n", rc);
-   kfree(dbx);
+   kfree(data);
}
 
return rc;
-- 
2.31.1



[PATCH] security/integrity: fix pointer to ESL data and its size on pseries

2023-06-06 Thread Nayna Jain
On PowerVM guest, variable data is prefixed with 8 bytes of timestamp.
Extract ESL by stripping off the timestamp before passing to ESL parser.

Fixes: 4b3e71e9a34c ("integrity/powerpc: Support loading keys from PLPKS")
Signed-off-by: Nayna Jain 
---
 .../integrity/platform_certs/load_powerpc.c   | 39 ---
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/security/integrity/platform_certs/load_powerpc.c 
b/security/integrity/platform_certs/load_powerpc.c
index b9de70b90826..57768cbf1fd3 100644
--- a/security/integrity/platform_certs/load_powerpc.c
+++ b/security/integrity/platform_certs/load_powerpc.c
@@ -15,6 +15,9 @@
 #include "keyring_handler.h"
 #include "../integrity.h"
 
+#define extract_data(db, data, size, offset)   \
+   do { db = data + offset; size = size - offset; } while (0)
+
 /*
  * Get a certificate list blob from the named secure variable.
  *
@@ -55,8 +58,10 @@ static __init void *get_cert_list(u8 *key, unsigned long 
keylen, u64 *size)
  */
 static int __init load_powerpc_certs(void)
 {
+   void *data = NULL;
+   u64 dsize = 0;
+   u64 offset = 0;
void *db = NULL, *dbx = NULL;
-   u64 dbsize = 0, dbxsize = 0;
int rc = 0;
ssize_t len;
char buf[32];
@@ -74,38 +79,46 @@ static int __init load_powerpc_certs(void)
return -ENODEV;
}
 
+   if (strcmp("ibm,plpks-sb-v1", buf) == 0)
+   /* PLPKS authenticated variables ESL data is prefixed with 8 
bytes of timestamp */
+   offset = 8;
+
/*
 * Get db, and dbx. They might not exist, so it isn't an error if we
 * can't get them.
 */
-   db = get_cert_list("db", 3, );
-   if (!db) {
+   data = get_cert_list("db", 3, );
+   if (!data) {
pr_info("Couldn't get db list from firmware\n");
-   } else if (IS_ERR(db)) {
-   rc = PTR_ERR(db);
+   } else if (IS_ERR(data)) {
+   rc = PTR_ERR(data);
pr_err("Error reading db from firmware: %d\n", rc);
return rc;
} else {
-   rc = parse_efi_signature_list("powerpc:db", db, dbsize,
+   extract_data(db, data, dsize, offset);
+
+   rc = parse_efi_signature_list("powerpc:db", db, dsize,
  get_handler_for_db);
if (rc)
pr_err("Couldn't parse db signatures: %d\n", rc);
-   kfree(db);
+   kfree(data);
}
 
-   dbx = get_cert_list("dbx", 4,  );
-   if (!dbx) {
+   data = get_cert_list("dbx", 4,  );
+   if (!data) {
pr_info("Couldn't get dbx list from firmware\n");
-   } else if (IS_ERR(dbx)) {
-   rc = PTR_ERR(dbx);
+   } else if (IS_ERR(data)) {
+   rc = PTR_ERR(data);
pr_err("Error reading dbx from firmware: %d\n", rc);
return rc;
} else {
-   rc = parse_efi_signature_list("powerpc:dbx", dbx, dbxsize,
+   extract_data(dbx, data, dsize, offset);
+
+   rc = parse_efi_signature_list("powerpc:dbx", dbx, dsize,
  get_handler_for_dbx);
if (rc)
pr_err("Couldn't parse dbx signatures: %d\n", rc);
-   kfree(dbx);
+   kfree(data);
}
 
return rc;
-- 
2.31.1



[PATCH 4/4] powerpc/pseries: expose authenticated variables stored in LPAR PKS

2022-11-06 Thread Nayna Jain
PowerVM Guest Secure boot feature need to expose firmware managed
secure variables for user management. These variables store keys for
grub/kernel verification and also corresponding denied list.

Expose these variables to the userpace via fwsecurityfs.

Example:

$ pwd
/sys/firmware/security/plpks/secvars

$ ls -ltrh
total 0
-rw-r--r-- 1 root root 831 Sep 12 18:34 PK
-rw-r--r-- 1 root root 831 Sep 12 18:34 KEK
-rw-r--r-- 1 root root 831 Sep 12 18:34 db

$ hexdump -C db
  00 00 00 08 a1 59 c0 a5  e4 94 a7 4a 87 b5 ab 15  |.Y.J|
0010  5c 2b f0 72 3f 03 00 00  00 00 00 00 23 03 00 00  |\+.r?...#...|
0020  ca 18 1d 1c 01 7d eb 11  9a 71 08 94 ef 31 fb e4  |.}...q...1..|
0030  30 82 03 0f 30 82 01 f7  a0 03 02 01 02 02 14 22  |0...0.."|
0040  ab 18 2f d5 aa dd c5 ba  98 27 60 26 f1 63 89 54  |../..'`&.c.T|
0050  4c 52 d9 30 0d 06 09 2a  86 48 86 f7 0d 01 01 0b  |LR.0...*.H..|
0060  05 00 30 17 31 15 30 13  06 03 55 04 03 0c 0c 72  |..0.1.0...Ur|
...

Signed-off-by: Nayna Jain 
---
 arch/powerpc/platforms/pseries/Kconfig|  10 +
 arch/powerpc/platforms/pseries/Makefile   |   1 +
 .../platforms/pseries/fwsecurityfs_arch.c |   8 +
 arch/powerpc/platforms/pseries/plpks.h|   3 +
 arch/powerpc/platforms/pseries/secvars.c  | 365 ++
 5 files changed, 387 insertions(+)
 create mode 100644 arch/powerpc/platforms/pseries/secvars.c

diff --git a/arch/powerpc/platforms/pseries/Kconfig 
b/arch/powerpc/platforms/pseries/Kconfig
index 5fb45e601982..41c17f60dfe9 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -172,6 +172,16 @@ config PSERIES_FWSECURITYFS_ARCH
 
  If you are unsure how to use it, say N.
 
+config PSERIES_PLPKS_SECVARS
+   depends on PSERIES_PLPKS
+   select PSERIES_FWSECURITYFS_ARCH
+   tristate "Support for secvars"
+   help
+ This interface exposes authenticated variables stored in the LPAR
+ Platform KeyStore using fwsecurityfs interface.
+
+ If you are unsure how to use it, say N.
+
 config PAPR_SCM
depends on PPC_PSERIES && MEMORY_HOTPLUG && LIBNVDIMM
tristate "Support for the PAPR Storage Class Memory interface"
diff --git a/arch/powerpc/platforms/pseries/Makefile 
b/arch/powerpc/platforms/pseries/Makefile
index 2903cff26258..6833f6b02798 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_PPC_SVM) += svm.o
 obj-$(CONFIG_FA_DUMP)  += rtas-fadump.o
 obj-$(CONFIG_PSERIES_PLPKS) += plpks.o
 obj-$(CONFIG_PSERIES_FWSECURITYFS_ARCH) += fwsecurityfs_arch.o
+obj-$(CONFIG_PSERIES_PLPKS_SECVARS) += secvars.o
 
 obj-$(CONFIG_SUSPEND)  += suspend.o
 obj-$(CONFIG_PPC_VAS)  += vas.o vas-sysfs.o
diff --git a/arch/powerpc/platforms/pseries/fwsecurityfs_arch.c 
b/arch/powerpc/platforms/pseries/fwsecurityfs_arch.c
index b43bd3cf7889..1cc651ad6434 100644
--- a/arch/powerpc/platforms/pseries/fwsecurityfs_arch.c
+++ b/arch/powerpc/platforms/pseries/fwsecurityfs_arch.c
@@ -58,6 +58,7 @@ static int create_plpks_dir(void)
 {
struct dentry *config_dir;
struct dentry *fdentry;
+   int rc;
 
if (!IS_ENABLED(CONFIG_PSERIES_PLPKS) || !plpks_is_available()) {
pr_warn("Platform KeyStore is not available on this LPAR\n");
@@ -107,6 +108,13 @@ static int create_plpks_dir(void)
if (IS_ERR(fdentry))
pr_err("Could not create version %ld\n", PTR_ERR(fdentry));
 
+   if (IS_ENABLED(CONFIG_PSERIES_PLPKS_SECVARS)) {
+   rc = plpks_secvars_init(plpks_dir);
+   if (rc)
+   pr_err("Secure Variables initialization failed with 
error %d\n", rc);
+   return rc;
+   }
+
return 0;
 }
 
diff --git a/arch/powerpc/platforms/pseries/plpks.h 
b/arch/powerpc/platforms/pseries/plpks.h
index fb483658549f..2d572fe4b522 100644
--- a/arch/powerpc/platforms/pseries/plpks.h
+++ b/arch/powerpc/platforms/pseries/plpks.h
@@ -11,6 +11,7 @@
 
 #include 
 #include 
+#include 
 
 #define OSSECBOOTAUDIT 0x4000
 #define OSSECBOOTENFORCE 0x2000
@@ -103,4 +104,6 @@ u32 plpks_get_totalsize(void);
  */
 u32 plpks_get_usedspace(void);
 
+int plpks_secvars_init(struct dentry *parent);
+
 #endif
diff --git a/arch/powerpc/platforms/pseries/secvars.c 
b/arch/powerpc/platforms/pseries/secvars.c
new file mode 100644
index ..3d5a251d0571
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/secvars.c
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Expose secure(authenticated) variables for user key management.
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ */
+
+#include 
+#include "plpks.h"
+
+static struct dentry *secvar_dir;
+
+static const char * const 

[PATCH 1/4] powerpc/pseries: Add new functions to PLPKS driver

2022-11-06 Thread Nayna Jain
PowerVM stores authenticated variables in the PowerVM LPAR Platform
KeyStore(PLPKS).

Add signed update H_CALL to PLPKS driver to support authenticated
variables. Additionally, expose config values outside the PLPKS
driver.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/hvcall.h  |   3 +-
 arch/powerpc/platforms/pseries/plpks.c | 112 +++--
 arch/powerpc/platforms/pseries/plpks.h |  35 
 3 files changed, 144 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/hvcall.h 
b/arch/powerpc/include/asm/hvcall.h
index 95fd7f9485d5..33b26c0cb69b 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -336,7 +336,8 @@
 #define H_SCM_FLUSH0x44C
 #define H_GET_ENERGY_SCALE_INFO0x450
 #define H_WATCHDOG 0x45C
-#define MAX_HCALL_OPCODE   H_WATCHDOG
+#define H_PKS_SIGNED_UPDATE0x454
+#define MAX_HCALL_OPCODE   H_PKS_SIGNED_UPDATE
 
 /* Scope args for H_SCM_UNBIND_ALL */
 #define H_UNBIND_SCOPE_ALL (0x1)
diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
index 4edd1585e245..d0fa7b55a900 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -40,6 +40,10 @@ static u16 ospasswordlength;
 // Retrieved with H_PKS_GET_CONFIG
 static u16 maxpwsize;
 static u16 maxobjsize;
+static s16 maxobjlabelsize;
+static u32 totalsize;
+static u32 usedspace;
+static u8 version;
 
 struct plpks_auth {
u8 version;
@@ -87,6 +91,12 @@ static int pseries_status_to_err(int rc)
err = -ENOENT;
break;
case H_BUSY:
+   case H_LONG_BUSY_ORDER_1_MSEC:
+   case H_LONG_BUSY_ORDER_10_MSEC:
+   case H_LONG_BUSY_ORDER_100_MSEC:
+   case H_LONG_BUSY_ORDER_1_SEC:
+   case H_LONG_BUSY_ORDER_10_SEC:
+   case H_LONG_BUSY_ORDER_100_SEC:
err = -EBUSY;
break;
case H_AUTHORITY:
@@ -187,14 +197,17 @@ static struct label *construct_label(char *component, u8 
varos, u8 *name,
 u16 namelen)
 {
struct label *label;
-   size_t slen;
+   size_t slen = 0;
 
if (!name || namelen > MAX_NAME_SIZE)
return ERR_PTR(-EINVAL);
 
-   slen = strlen(component);
-   if (component && slen > sizeof(label->attr.prefix))
-   return ERR_PTR(-EINVAL);
+   /* Support NULL component for signed updates */
+   if (component) {
+   slen = strlen(component);
+   if (slen > sizeof(label->attr.prefix))
+   return ERR_PTR(-EINVAL);
+   }
 
label = kzalloc(sizeof(*label), GFP_KERNEL);
if (!label)
@@ -240,10 +253,51 @@ static int _plpks_get_config(void)
 
maxpwsize = be16_to_cpu(config.maxpwsize);
maxobjsize = be16_to_cpu(config.maxobjsize);
+   maxobjlabelsize = be16_to_cpu(config.maxobjlabelsize) -
+ MAX_LABEL_ATTR_SIZE;
+   maxobjlabelsize = maxobjlabelsize < 0 ? 0 : maxobjlabelsize;
+   totalsize = be32_to_cpu(config.totalsize);
+   usedspace = be32_to_cpu(config.usedspace);
 
return 0;
 }
 
+u8 plpks_get_version(void)
+{
+   return version;
+}
+
+u16 plpks_get_maxobjectsize(void)
+{
+   return maxobjsize;
+}
+
+u16 plpks_get_maxobjectlabelsize(void)
+{
+   return maxobjlabelsize;
+}
+
+u32 plpks_get_totalsize(void)
+{
+   return totalsize;
+}
+
+u32 plpks_get_usedspace(void)
+{
+   return usedspace;
+}
+
+bool plpks_is_available(void)
+{
+   int rc;
+
+   rc = _plpks_get_config();
+   if (rc)
+   return false;
+
+   return true;
+}
+
 static int plpks_confirm_object_flushed(struct label *label,
struct plpks_auth *auth)
 {
@@ -277,6 +331,54 @@ static int plpks_confirm_object_flushed(struct label 
*label,
return rc;
 }
 
+int plpks_signed_update_var(struct plpks_var var, u64 flags)
+{
+   unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
+   int rc;
+   struct label *label;
+   struct plpks_auth *auth;
+   u64 continuetoken = 0;
+
+   if (!var.data || var.datalen <= 0 || var.namelen > MAX_NAME_SIZE)
+   return -EINVAL;
+
+   if (!(var.policy & SIGNEDUPDATE))
+   return -EINVAL;
+
+   auth = construct_auth(PKS_OS_OWNER);
+   if (IS_ERR(auth))
+   return PTR_ERR(auth);
+
+   label = construct_label(var.component, var.os, var.name, var.namelen);
+   if (IS_ERR(label)) {
+   rc = PTR_ERR(label);
+   goto out;
+   }
+
+   do {
+   rc = plpar_hcall9(H_PKS_SIGNED_UPDATE, retbuf,
+ virt_to_phys(auth), virt_to_phys(label),
+ label->size, var.policy, flags,
+ 

[PATCH 3/4] powerpc/pseries: initialize fwsecurityfs with plpks arch-specific structure

2022-11-06 Thread Nayna Jain
PowerVM PLPKS variables are exposed via fwsecurityfs.

Initialize fwsecurityfs arch-specific structure with plpks configuration.

Eg:

[root@ltcfleet35-lp1 config]# pwd
/sys/firmware/security/plpks/config
[root@ltcfleet35-lp1 config]# ls -ltrh
total 0
-r--r--r-- 1 root root 1 Sep 28 15:01 version
-r--r--r-- 1 root root 4 Sep 28 15:01 used_space
-r--r--r-- 1 root root 4 Sep 28 15:01 total_size
-r--r--r-- 1 root root 2 Sep 28 15:01 max_object_size
-r--r--r-- 1 root root 2 Sep 28 15:01 max_object_label_size

Signed-off-by: Nayna Jain 
---
 arch/powerpc/platforms/pseries/Kconfig|  10 ++
 arch/powerpc/platforms/pseries/Makefile   |   1 +
 .../platforms/pseries/fwsecurityfs_arch.c | 116 ++
 include/linux/fwsecurityfs.h  |   4 +
 4 files changed, 131 insertions(+)
 create mode 100644 arch/powerpc/platforms/pseries/fwsecurityfs_arch.c

diff --git a/arch/powerpc/platforms/pseries/Kconfig 
b/arch/powerpc/platforms/pseries/Kconfig
index a3b4d99567cb..5fb45e601982 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -162,6 +162,16 @@ config PSERIES_PLPKS
 
  If unsure, select N.
 
+config PSERIES_FWSECURITYFS_ARCH
+   select FWSECURITYFS
+   bool "Support fwsecurityfs for pseries"
+   help
+ Enable fwsecurityfs arch specific code. This would initialize
+ the firmware security filesystem with initial platform specific
+ structure.
+
+ If you are unsure how to use it, say N.
+
 config PAPR_SCM
depends on PPC_PSERIES && MEMORY_HOTPLUG && LIBNVDIMM
tristate "Support for the PAPR Storage Class Memory interface"
diff --git a/arch/powerpc/platforms/pseries/Makefile 
b/arch/powerpc/platforms/pseries/Makefile
index 92310202bdd7..2903cff26258 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_PPC_SPLPAR)  += vphn.o
 obj-$(CONFIG_PPC_SVM)  += svm.o
 obj-$(CONFIG_FA_DUMP)  += rtas-fadump.o
 obj-$(CONFIG_PSERIES_PLPKS) += plpks.o
+obj-$(CONFIG_PSERIES_FWSECURITYFS_ARCH) += fwsecurityfs_arch.o
 
 obj-$(CONFIG_SUSPEND)  += suspend.o
 obj-$(CONFIG_PPC_VAS)  += vas.o vas-sysfs.o
diff --git a/arch/powerpc/platforms/pseries/fwsecurityfs_arch.c 
b/arch/powerpc/platforms/pseries/fwsecurityfs_arch.c
new file mode 100644
index ..b43bd3cf7889
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/fwsecurityfs_arch.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Initialize fwsecurityfs with POWER LPAR Platform KeyStore (PLPKS)
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ */
+
+#include 
+#include "plpks.h"
+
+static struct dentry *plpks_dir;
+
+static ssize_t plpks_config_file_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+   u8 out[4];
+   u32 outlen;
+   size_t size;
+   char *name;
+   u32 data;
+
+   name = file_dentry(file)->d_iname;
+
+   if (strcmp(name, "max_object_size") == 0) {
+   outlen = sizeof(u16);
+   data = plpks_get_maxobjectsize();
+   } else if (strcmp(name, "max_object_label_size") == 0) {
+   outlen = sizeof(u16);
+   data = plpks_get_maxobjectlabelsize();
+   } else if (strcmp(name, "total_size") == 0) {
+   outlen = sizeof(u32);
+   data = plpks_get_totalsize();
+   } else if (strcmp(name, "used_space") == 0) {
+   outlen = sizeof(u32);
+   data = plpks_get_usedspace();
+   } else if (strcmp(name, "version") == 0) {
+   outlen = sizeof(u8);
+   data = plpks_get_version();
+   } else {
+   return -EINVAL;
+   }
+
+   memcpy(out, , outlen);
+
+   size = simple_read_from_buffer(userbuf, count, ppos, out, outlen);
+
+   return size;
+}
+
+static const struct file_operations plpks_config_file_operations = {
+   .open   = simple_open,
+   .read   = plpks_config_file_read,
+   .llseek = no_llseek,
+};
+
+static int create_plpks_dir(void)
+{
+   struct dentry *config_dir;
+   struct dentry *fdentry;
+
+   if (!IS_ENABLED(CONFIG_PSERIES_PLPKS) || !plpks_is_available()) {
+   pr_warn("Platform KeyStore is not available on this LPAR\n");
+   return 0;
+   }
+
+   plpks_dir = fwsecurityfs_create_dir("plpks", S_IFDIR | 0755, NULL,
+   NULL);
+   if (IS_ERR(plpks_dir)) {
+   pr_err("Unable to create PLPKS dir: %ld\n", PTR_ERR(plpks_dir));
+   return PTR_ERR(plpks_dir);
+   }
+
+   config_dir = fwsecurityfs_create_dir("config", S_IFDIR | 0755, 
plpks_dir, NULL);
+   i

[PATCH 2/4] fs: define a firmware security filesystem named fwsecurityfs

2022-11-06 Thread Nayna Jain
securityfs is meant for Linux security subsystems to expose policies/logs
or any other information. However, there are various firmware security
features which expose their variables for user management via the kernel.
There is currently no single place to expose these variables. Different
platforms use sysfs/platform specific filesystem(efivarfs)/securityfs
interface as they find it appropriate. Thus, there is a gap in kernel
interfaces to expose variables for security features.

Define a firmware security filesystem (fwsecurityfs) to be used by
security features enabled by the firmware. These variables are platform
specific. This filesystem provides platforms a way to implement their
 own underlying semantics by defining own inode and file operations.

Similar to securityfs, the firmware security filesystem is recommended
to be exposed on a well known mount point /sys/firmware/security.
Platforms can define their own directory or file structure under this path.

Example:

# mount -t fwsecurityfs fwsecurityfs /sys/firmware/security

# cd /sys/firmware/security/

Signed-off-by: Nayna Jain 
---
 fs/Kconfig   |   1 +
 fs/Makefile  |   1 +
 fs/fwsecurityfs/Kconfig  |  14 ++
 fs/fwsecurityfs/Makefile |  10 ++
 fs/fwsecurityfs/super.c  | 263 +++
 include/linux/fwsecurityfs.h |  29 
 include/uapi/linux/magic.h   |   1 +
 7 files changed, 319 insertions(+)
 create mode 100644 fs/fwsecurityfs/Kconfig
 create mode 100644 fs/fwsecurityfs/Makefile
 create mode 100644 fs/fwsecurityfs/super.c
 create mode 100644 include/linux/fwsecurityfs.h

diff --git a/fs/Kconfig b/fs/Kconfig
index 2685a4d0d353..2a24f1c779dd 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -275,6 +275,7 @@ config ARCH_HAS_GIGANTIC_PAGE
 
 source "fs/configfs/Kconfig"
 source "fs/efivarfs/Kconfig"
+source "fs/fwsecurityfs/Kconfig"
 
 endmenu
 
diff --git a/fs/Makefile b/fs/Makefile
index 4dea17840761..b945019a9bbe 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -134,6 +134,7 @@ obj-$(CONFIG_F2FS_FS)   += f2fs/
 obj-$(CONFIG_CEPH_FS)  += ceph/
 obj-$(CONFIG_PSTORE)   += pstore/
 obj-$(CONFIG_EFIVAR_FS)+= efivarfs/
+obj-$(CONFIG_FWSECURITYFS) += fwsecurityfs/
 obj-$(CONFIG_EROFS_FS) += erofs/
 obj-$(CONFIG_VBOXSF_FS)+= vboxsf/
 obj-$(CONFIG_ZONEFS_FS)+= zonefs/
diff --git a/fs/fwsecurityfs/Kconfig b/fs/fwsecurityfs/Kconfig
new file mode 100644
index ..1dc2ee831eda
--- /dev/null
+++ b/fs/fwsecurityfs/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 IBM Corporation
+# Author: Nayna Jain 
+#
+
+config FWSECURITYFS
+   bool "Enable the fwsecurityfs filesystem"
+   help
+ This will build fwsecurityfs filesystem which should be mounted
+ on /sys/firmware/security. This filesystem can be used by
+ platform to expose firmware-managed variables.
+
+ If you are unsure how to answer this question, answer N.
diff --git a/fs/fwsecurityfs/Makefile b/fs/fwsecurityfs/Makefile
new file mode 100644
index ..5c7b76228ebb
--- /dev/null
+++ b/fs/fwsecurityfs/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 IBM Corporation
+# Author: Nayna Jain 
+#
+# Makefile for the firmware security filesystem
+
+obj-$(CONFIG_FWSECURITYFS) += fwsecurityfs.o
+
+fwsecurityfs-objs  := super.o
diff --git a/fs/fwsecurityfs/super.c b/fs/fwsecurityfs/super.c
new file mode 100644
index ..99ca4da4ab63
--- /dev/null
+++ b/fs/fwsecurityfs/super.c
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static struct super_block *fwsecsb;
+static struct vfsmount *mount;
+static int mount_count;
+static bool fwsecurityfs_initialized;
+
+static void fwsecurityfs_free_inode(struct inode *inode)
+{
+   free_inode_nonrcu(inode);
+}
+
+static const struct super_operations fwsecurityfs_super_operations = {
+   .statfs = simple_statfs,
+   .free_inode = fwsecurityfs_free_inode,
+};
+
+static int fwsecurityfs_fill_super(struct super_block *sb,
+  struct fs_context *fc)
+{
+   static const struct tree_descr files[] = {{""}};
+   int rc;
+
+   rc = simple_fill_super(sb, FWSECURITYFS_MAGIC, files);
+   if (rc)
+   return rc;
+
+   sb->s_op = _super_operations;
+
+   fwsecsb = sb;
+
+   rc = arch_fwsecurityfs_init();
+
+   if (!rc)
+   fwsecurityfs_initialized = true;
+
+   return rc;
+}
+
+static int fwsecurityfs_get_tree(struct fs_context *fc)
+{
+   return get_tree_single(fc, fwsecurityfs_fill_super);
+}
+
+static const struct fs_context_oper

[PATCH 0/4] powerpc/pseries: expose firmware security variables via filesystem

2022-11-06 Thread Nayna Jain
PowerVM provides an isolated Platform KeyStore (PKS)[1] storage allocation
for each logical partition (LPAR) with individually managed access controls
to store sensitive information securely. The Linux kernel can access this
storage by interfacing with the hypervisor using a new set of hypervisor
calls.
 
The PowerVM guest secure boot feature intends to use PKS for the purpose of
storing public keys. Secure boot requires public keys in order to verify
GRUB and the boot kernel. To allow authenticated manipulation of keys, PKS
supports variables to store key authorities namely, PK and KEK. Other
variables are used to store code signing keys, db and grubdb. It also
supports deny lists to disallow booting GRUB or kernels even if they are
signed with valid keys. This is done via deny list databases stored in dbx
and sbat variables. These variables are stored in PKS and are managed and
controlled by firmware.

The purpose of this patchset is to add the userspace interface to manage
these variables.

Currently, OpenPOWER exposes variables via sysfs, while EFI platforms have
used sysfs and then moved to their own efivarfs filesystem. The recent
coco feature uses securityfs to expose secrets to TEEs. All of these
environments are different both syntactically and semantically.

securityfs is meant for Linux security subsystems to expose policies, logs,
and other information and it does not interact with firmware for managing
these variables. However, there are various firmware security features that
expose their variables for user management via pseudo filesystems as
discussed above. There is currently no single place to expose these
variables. Different platforms use sysfs, platform-specific filesystems
such as efivars, or securityfs as they have found appropriate. This has
resulted in interfaces scattered around the tree. The multiple interfac
 problem can be addressed by providing a single pseudo filesystem for all
platforms to expose their variables for firmware security features. Doing
so simplifies the interface for users of these platforms.

This patchset introduces a new firmware security pseudo filesystem,
fwsecurityfs. Any platform can expose the variables that are required by
firmware security features via this interface. It provides a common place
for exposing variables managed by firmware while still allowing platforms
to implement their own underlying semantics.

This design consists of two parts:

1. Firmware security filesystem (fwsecurityfs) that provides platforms
   with APIs to create their own underlying directory and file structure.
   It should be mounted on a new well-known mountpoint,
   /sys/firmware/security.
2. Platform-specific layer for these variables that implements underlying
   semantics. Platforms can expose their variables as files allowing
   read/write/add/delete operations by defining their own inode and file
   functions.

This patchset adds:
1. An update to the PLPKS driver to support the signed update H_CALL for
   authenticated variables used in guest secure boot.
2. A firmware security filesystem named fwsecurityfs.
3. An interface to expose secure variables stored in the LPAR's PKS via
   fwsecurityfs.
 
Note: This patchset is not intended to modify existing interfaces already
used by OpenPOWER or EFI but rather to ensure that new similar interfaces
have a common base going forward.

The first patch related to PLPKS driver is dependent on bugfixes posted
as part of patchset[4].

Changelog:

First non-RFC version after RFC versions[2,3].
Feedback from non-RFC version are included to update fwsecurityfs.
 * PLPKS driver patch had been upstreamed separately. In this set, Patch 1
 updates existing driver to include signed update support.
 * Fix fwsecurityfs to also pin the file system, refactor and cleanup. The
 consideration of namespacing has been done and is concluded that currently
 no firmware object or entity is handled by namespacing. The purpose of
 fwsecurityfs is to expose firmware space which is similar to exposing
 space in TPM. And TPM is also not currently namespaced. If containers have
 to make use of some such space in the future, it would have to be some
 software space. With that, this currently only considers the host using the
 firmware space.
 * Fix secvars support for powerpc. It supports policy handling within the
 kernel, supports UCS2 naming and cleanups.
 * Read-only PLPKS configuration is exposed.
 * secvars directory is now moved within a new parent directory plpks.
 * Patch is now no more an RFC version.

[1] 
https://community.ibm.com/community/user/power/blogs/chris-engel1/2020/11/20/powervm-introduces-the-platform-keystore
[2] RFC v2: 
https://lore.kernel.org/linuxppc-dev/20220622215648.96723-1-na...@linux.ibm.com/
 
[3] RFC v1: 
https://lore.kernel.org/linuxppc-dev/20220122005637.28199-1-na...@linux.ibm.com/
[4] 
https://lore.kernel.org/linuxppc-dev/20221106205839.600442-1-na...@linux.ibm.com/T/#t

Nayna Jain (4):
  powerpc/pseries: Add new

[PATCH 6/6] powerpc/pseries: fix plpks_read_var() code for different consumers

2022-11-06 Thread Nayna Jain
Even though plpks_read_var() is currently called to read variables
owned by different consumers, it internally supports only OS consumer.

Fix plpks_read_var() to handle different consumers correctly.

Fixes: 2454a7af0f2a ("powerpc/pseries: define driver for Platform KeyStore")
Signed-off-by: Nayna Jain 
---
 arch/powerpc/platforms/pseries/plpks.c | 28 +-
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
index e8c02735b702..4edd1585e245 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -354,22 +354,24 @@ static int plpks_read_var(u8 consumer, struct plpks_var 
*var)
 {
unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
struct plpks_auth *auth;
-   struct label *label;
+   struct label *label = NULL;
u8 *output;
int rc;
 
if (var->namelen > MAX_NAME_SIZE)
return -EINVAL;
 
-   auth = construct_auth(PKS_OS_OWNER);
+   auth = construct_auth(consumer);
if (IS_ERR(auth))
return PTR_ERR(auth);
 
-   label = construct_label(var->component, var->os, var->name,
-   var->namelen);
-   if (IS_ERR(label)) {
-   rc = PTR_ERR(label);
-   goto out_free_auth;
+   if (consumer == PKS_OS_OWNER) {
+   label = construct_label(var->component, var->os, var->name,
+   var->namelen);
+   if (IS_ERR(label)) {
+   rc = PTR_ERR(label);
+   goto out_free_auth;
+   }
}
 
output = kzalloc(maxobjsize, GFP_KERNEL);
@@ -378,9 +380,15 @@ static int plpks_read_var(u8 consumer, struct plpks_var 
*var)
goto out_free_label;
}
 
-   rc = plpar_hcall(H_PKS_READ_OBJECT, retbuf, virt_to_phys(auth),
-virt_to_phys(label), label->size, virt_to_phys(output),
-maxobjsize);
+   if (consumer == PKS_OS_OWNER)
+   rc = plpar_hcall(H_PKS_READ_OBJECT, retbuf, virt_to_phys(auth),
+virt_to_phys(label), label->size, 
virt_to_phys(output),
+maxobjsize);
+   else
+   rc = plpar_hcall(H_PKS_READ_OBJECT, retbuf, virt_to_phys(auth),
+virt_to_phys(var->name), var->namelen, 
virt_to_phys(output),
+maxobjsize);
+
 
if (rc != H_SUCCESS) {
rc = pseries_status_to_err(rc);
-- 
2.31.1



[PATCH 5/6] powerpc/pseries: replace kmalloc with kzalloc in PLPKS driver

2022-11-06 Thread Nayna Jain
Replace kmalloc with kzalloc in construct_auth() function to default
initialize structure with zeroes.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/platforms/pseries/plpks.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
index 72d9debf18c0..e8c02735b702 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -162,19 +162,15 @@ static struct plpks_auth *construct_auth(u8 consumer)
if (consumer > PKS_OS_OWNER)
return ERR_PTR(-EINVAL);
 
-   auth = kmalloc(struct_size(auth, password, maxpwsize), GFP_KERNEL);
+   auth = kzalloc(struct_size(auth, password, maxpwsize), GFP_KERNEL);
if (!auth)
return ERR_PTR(-ENOMEM);
 
auth->version = 1;
auth->consumer = consumer;
-   auth->rsvd0 = 0;
-   auth->rsvd1 = 0;
 
-   if (consumer == PKS_FW_OWNER || consumer == PKS_BOOTLOADER_OWNER) {
-   auth->passwordlength = 0;
+   if (consumer == PKS_FW_OWNER || consumer == PKS_BOOTLOADER_OWNER)
return auth;
-   }
 
memcpy(auth->password, ospassword, ospasswordlength);
 
-- 
2.31.1



[PATCH 4/6] powerpc/pseries: cleanup error logs in plpks driver

2022-11-06 Thread Nayna Jain
Logging H_CALL return codes in PLPKS driver are easy to confuse with
Linux error codes.

Let the caller of the function log the converted linux error code.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/platforms/pseries/plpks.c | 10 --
 1 file changed, 10 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
index cbea447122ca..72d9debf18c0 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -312,10 +312,6 @@ int plpks_write_var(struct plpks_var var)
if (!rc)
rc = plpks_confirm_object_flushed(label, auth);
 
-   if (rc)
-   pr_err("Failed to write variable %s for component %s with error 
%d\n",
-  var.name, var.component, rc);
-
rc = pseries_status_to_err(rc);
kfree(label);
 out:
@@ -350,10 +346,6 @@ int plpks_remove_var(char *component, u8 varos, struct 
plpks_var_name vname)
if (!rc)
rc = plpks_confirm_object_flushed(label, auth);
 
-   if (rc)
-   pr_err("Failed to remove variable %s for component %s with 
error %d\n",
-  vname.name, component, rc);
-
rc = pseries_status_to_err(rc);
kfree(label);
 out:
@@ -395,8 +387,6 @@ static int plpks_read_var(u8 consumer, struct plpks_var 
*var)
 maxobjsize);
 
if (rc != H_SUCCESS) {
-   pr_err("Failed to read variable %s for component %s with error 
%d\n",
-  var->name, var->component, rc);
rc = pseries_status_to_err(rc);
goto out_free_output;
}
-- 
2.31.1



[PATCH 3/6] powerpc/pseries: Return -EIO instead of -EINTR for H_ABORTED error

2022-11-06 Thread Nayna Jain
Some commands for eg. "cat" might continue to retry on encountering
EINTR. This is not expected for original error code H_ABORTED.

Map H_ABORTED to more relevant Linux error code EIO.

Fixes: 2454a7af0f2a ("powerpc/pseries: define driver for Platform KeyStore")
Signed-off-by: Nayna Jain 
---
 arch/powerpc/platforms/pseries/plpks.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
index 32ce4d780d8f..cbea447122ca 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -111,7 +111,7 @@ static int pseries_status_to_err(int rc)
err = -EEXIST;
break;
case H_ABORTED:
-   err = -EINTR;
+   err = -EIO;
break;
default:
err = -EINVAL;
-- 
2.31.1



[PATCH 2/6] powerpc/pseries: Fix the H_CALL error code in PLPKS driver

2022-11-06 Thread Nayna Jain
PAPR Spec defines H_P1 actually as H_PARAMETER and maps H_ABORTED to
a different numerical value.

Fix the error codes as per PAPR Specification.

Fixes: 2454a7af0f2a ("powerpc/pseries: define driver for Platform KeyStore")
Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/hvcall.h  | 3 +--
 arch/powerpc/platforms/pseries/plpks.c | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/include/asm/hvcall.h 
b/arch/powerpc/include/asm/hvcall.h
index 8abae463f6c1..95fd7f9485d5 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -79,7 +79,7 @@
 #define H_NOT_ENOUGH_RESOURCES -44
 #define H_R_STATE   -45
 #define H_RESCINDED -46
-#define H_P1   -54
+#define H_ABORTED  -54
 #define H_P2   -55
 #define H_P3   -56
 #define H_P4   -57
@@ -100,7 +100,6 @@
 #define H_COP_HW   -74
 #define H_STATE-75
 #define H_IN_USE   -77
-#define H_ABORTED  -78
 #define H_UNSUPPORTED_FLAG_START   -256
 #define H_UNSUPPORTED_FLAG_END -511
 #define H_MULTI_THREADS_ACTIVE -9005
diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
index f4b5b5a64db3..32ce4d780d8f 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -75,7 +75,7 @@ static int pseries_status_to_err(int rc)
case H_FUNCTION:
err = -ENXIO;
break;
-   case H_P1:
+   case H_PARAMETER:
case H_P2:
case H_P3:
case H_P4:
-- 
2.31.1



[PATCH 0/6] powerpc/pseries - bugfixes/cleanups for PLPKS driver

2022-11-06 Thread Nayna Jain
This patchset fixes some bugs and does some cleanups.

Nayna Jain (6):
  powerpc/pseries: fix the object owners enum value in plpks driver
  powerpc/pseries: Fix the H_CALL error code in PLPKS driver
  powerpc/pseries: Return -EIO instead of -EINTR for H_ABORTED error
  powerpc/pseries: cleanup error logs in plpks driver
  powerpc/pseries: replace kmalloc with kzalloc in PLPKS driver
  powerpc/pseries: fix plpks_read_var() code for different consumers

 arch/powerpc/include/asm/hvcall.h  |  3 +-
 arch/powerpc/platforms/pseries/plpks.c | 50 --
 arch/powerpc/platforms/pseries/plpks.h |  2 +-
 3 files changed, 24 insertions(+), 31 deletions(-)

-- 
2.31.1


[PATCH 1/6] powerpc/pseries: fix the object owners enum value in plpks driver

2022-11-06 Thread Nayna Jain
OS_VAR_LINUX enum in PLPKS driver should be 0x02 instead of 0x01.

Fixes: 2454a7af0f2a ("powerpc/pseries: define driver for Platform KeyStore")
Signed-off-by: Nayna Jain 
---
 arch/powerpc/platforms/pseries/plpks.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/pseries/plpks.h 
b/arch/powerpc/platforms/pseries/plpks.h
index c6a291367bb1..275ccd86bfb5 100644
--- a/arch/powerpc/platforms/pseries/plpks.h
+++ b/arch/powerpc/platforms/pseries/plpks.h
@@ -17,7 +17,7 @@
 #define WORLDREADABLE 0x0800
 #define SIGNEDUPDATE 0x0100
 
-#define PLPKS_VAR_LINUX0x01
+#define PLPKS_VAR_LINUX0x02
 #define PLPKS_VAR_COMMON   0x04
 
 struct plpks_var {
-- 
2.31.1



[PATCH v2 3/3] powerpc/pseries: Override lib/arch_vars.c with PowerPC architecture specific version

2022-07-23 Thread Nayna Jain
From: Greg Joyce 

Self Encrypting Drives(SED) make use of POWER LPAR Platform KeyStore for
storing its variables. Thus the block subsystem needs to access
PowerPC specific functions to read/write objects in PLPKS.

Override the default implementations in lib/arch_vars.c file with
PowerPC specific versions.

Signed-off-by: Greg Joyce 
---
 arch/powerpc/platforms/pseries/Makefile   |   1 +
 .../platforms/pseries/plpks_arch_ops.c| 166 ++
 2 files changed, 167 insertions(+)
 create mode 100644 arch/powerpc/platforms/pseries/plpks_arch_ops.c

diff --git a/arch/powerpc/platforms/pseries/Makefile 
b/arch/powerpc/platforms/pseries/Makefile
index 14e143b946a3..3a545422eae5 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_PPC_SPLPAR)  += vphn.o
 obj-$(CONFIG_PPC_SVM)  += svm.o
 obj-$(CONFIG_FA_DUMP)  += rtas-fadump.o
 obj-$(CONFIG_PSERIES_PLPKS) += plpks.o
+obj-$(CONFIG_PSERIES_PLPKS) += plpks_arch_ops.o
 
 obj-$(CONFIG_SUSPEND)  += suspend.o
 obj-$(CONFIG_PPC_VAS)  += vas.o vas-sysfs.o
diff --git a/arch/powerpc/platforms/pseries/plpks_arch_ops.c 
b/arch/powerpc/platforms/pseries/plpks_arch_ops.c
new file mode 100644
index ..48fa19f0c9c5
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpks_arch_ops.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * POWER Platform arch specific code for SED
+ * Copyright (C) 2022 IBM Corporation
+ *
+ * Define operations for generic kernel subsystems to read/write keys from
+ * POWER LPAR Platform KeyStore(PLPKS).
+ *
+ * List of subsystems/usecase using PLPKS:
+ * - Self Encrypting Drives(SED)
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "plpks.h"
+
+/*
+ * variable structure that contains all SED data
+ */
+struct plpks_sed_object_data {
+   u_char version;
+   u_char pad1[7];
+   u_long authority;
+   u_long range;
+   u_int  key_len;
+   u_char key[32];
+};
+
+/*
+ * ext_type values
+ * 00no extension exists
+ * 01-1F common
+ * 20-3F AIX
+ * 40-5F Linux
+ * 60-7F IBMi
+ */
+
+/*
+ * This extension is optional for version 1 sed_object_data
+ */
+struct sed_object_extension {
+   u8 ext_type;
+   u8 rsvd[3];
+   u8 ext_data[64];
+};
+
+#define PKS_SED_OBJECT_DATA_V1  1
+#define PKS_SED_MANGLED_LABEL   "/default/pri"
+#define PLPKS_SED_COMPONENT "sed-opal"
+#define PLPKS_SED_POLICYWORLDREADABLE
+#define PLPKS_SED_OS_COMMON 4
+
+#ifndef CONFIG_BLK_SED_OPAL
+#defineOPAL_AUTH_KEY   ""
+#endif
+
+/*
+ * Read the variable data from PKS given the label
+ */
+int arch_read_variable(enum arch_variable_type type, char *varname,
+  void *varbuf, u_int *varlen)
+{
+   struct plpks_var var;
+   struct plpks_sed_object_data *data;
+   u_int offset = 0;
+   char *buf = (char *)varbuf;
+   int ret;
+
+   var.name = varname;
+   var.namelen = strlen(varname);
+   var.policy = PLPKS_SED_POLICY;
+   var.os = PLPKS_SED_OS_COMMON;
+   var.data = NULL;
+   var.datalen = 0;
+
+   switch (type) {
+   case ARCH_VAR_OPAL_KEY:
+   var.component = PLPKS_SED_COMPONENT;
+   if (strcmp(OPAL_AUTH_KEY, varname) == 0) {
+   var.name = PKS_SED_MANGLED_LABEL;
+   var.namelen = strlen(varname);
+   }
+   offset = offsetof(struct plpks_sed_object_data, key);
+   break;
+   case ARCH_VAR_OTHER:
+   var.component = "";
+   break;
+   }
+
+   ret = plpks_read_os_var();
+   if (ret != 0)
+   return ret;
+
+   if (offset > var.datalen)
+   offset = 0;
+
+   switch (type) {
+   case ARCH_VAR_OPAL_KEY:
+   data = (struct plpks_sed_object_data *)var.data;
+   *varlen = data->key_len;
+   break;
+   case ARCH_VAR_OTHER:
+   *varlen = var.datalen;
+   break;
+   }
+
+   if (var.data) {
+   memcpy(varbuf, var.data + offset, var.datalen - offset);
+   buf[*varlen] = '\0';
+   kfree(var.data);
+   }
+
+   return 0;
+}
+
+/*
+ * Write the variable data to PKS given the label
+ */
+int arch_write_variable(enum arch_variable_type type, char *varname,
+   void *varbuf, u_int varlen)
+{
+   struct plpks_var var;
+   struct plpks_sed_object_data data;
+   struct plpks_var_name vname;
+
+   var.name = varname;
+   var.namelen = strlen(varname);
+   var.policy = PLPKS_SED_POLICY;
+   var.os = PLPKS_SED_OS_COMMON;
+   var.datalen = varlen;
+   var.data = varbuf;
+
+   switch (type) {
+   case ARCH_VAR_OPAL_KEY:
+   

[PATCH v2 2/3] lib: define generic accessor functions for arch specific keystore

2022-07-23 Thread Nayna Jain
From: Greg Joyce 

Generic kernel subsystems may rely on platform specific persistent
KeyStore to store objects containing sensitive key material. In such case,
they need to access architecture specific functions to perform read/write
operations on these variables.

Define the generic variable read/write prototypes to be implemented by
architecture specific versions. The default(weak) implementations of
these prototypes return -EOPNOTSUPP unless overridden by architecture
versions.

Signed-off-by: Greg Joyce 
---
 include/linux/arch_vars.h | 23 +++
 lib/Makefile  |  2 +-
 lib/arch_vars.c   | 25 +
 3 files changed, 49 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/arch_vars.h
 create mode 100644 lib/arch_vars.c

diff --git a/include/linux/arch_vars.h b/include/linux/arch_vars.h
new file mode 100644
index ..9c280ff9432e
--- /dev/null
+++ b/include/linux/arch_vars.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Platform variable opearations.
+ *
+ * Copyright (C) 2022 IBM Corporation
+ *
+ * These are the accessor functions (read/write) for architecture specific
+ * variables. Specific architectures can provide overrides.
+ *
+ */
+
+#include 
+
+enum arch_variable_type {
+   ARCH_VAR_OPAL_KEY  = 0, /* SED Opal Authentication Key */
+   ARCH_VAR_OTHER = 1, /* Other type of variable */
+   ARCH_VAR_MAX   = 1, /* Maximum type value */
+};
+
+int arch_read_variable(enum arch_variable_type type, char *varname,
+  void *varbuf, u_int *varlen);
+int arch_write_variable(enum arch_variable_type type, char *varname,
+   void *varbuf, u_int varlen);
diff --git a/lib/Makefile b/lib/Makefile
index f99bf61f8bbc..b90c4cb0dbbb 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -48,7 +48,7 @@ obj-y += bcd.o sort.o parser.o debug_locks.o random32.o \
 bsearch.o find_bit.o llist.o memweight.o kfifo.o \
 percpu-refcount.o rhashtable.o \
 once.o refcount.o usercopy.o errseq.o bucket_locks.o \
-generic-radix-tree.o
+generic-radix-tree.o arch_vars.o
 obj-$(CONFIG_STRING_SELFTEST) += test_string.o
 obj-y += string_helpers.o
 obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
diff --git a/lib/arch_vars.c b/lib/arch_vars.c
new file mode 100644
index ..e6f16d7d09c1
--- /dev/null
+++ b/lib/arch_vars.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Platform variable operations.
+ *
+ * Copyright (C) 2022 IBM Corporation
+ *
+ * These are the accessor functions (read/write) for architecture specific
+ * variables. Specific architectures can provide overrides.
+ *
+ */
+
+#include 
+#include 
+
+int __weak arch_read_variable(enum arch_variable_type type, char *varname,
+ void *varbuf, u_int *varlen)
+{
+   return -EOPNOTSUPP;
+}
+
+int __weak arch_write_variable(enum arch_variable_type type, char *varname,
+  void *varbuf, u_int varlen)
+{
+   return -EOPNOTSUPP;
+}
-- 
2.27.0



[PATCH v2 1/3] powerpc/pseries: define driver for Platform KeyStore

2022-07-23 Thread Nayna Jain
PowerVM provides an isolated Platform Keystore(PKS) storage allocation
for each LPAR with individually managed access controls to store
sensitive information securely. It provides a new set of hypervisor
calls for Linux kernel to access PKS storage.

Define POWER LPAR Platform KeyStore(PLPKS) driver using H_CALL interface
to access PKS storage.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/hvcall.h   |  11 +
 arch/powerpc/platforms/pseries/Kconfig  |  13 +
 arch/powerpc/platforms/pseries/Makefile |   1 +
 arch/powerpc/platforms/pseries/plpks.c  | 460 
 arch/powerpc/platforms/pseries/plpks.h  |  71 
 5 files changed, 556 insertions(+)
 create mode 100644 arch/powerpc/platforms/pseries/plpks.c
 create mode 100644 arch/powerpc/platforms/pseries/plpks.h

diff --git a/arch/powerpc/include/asm/hvcall.h 
b/arch/powerpc/include/asm/hvcall.h
index d92a20a85395..9f707974af1a 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -79,6 +79,7 @@
 #define H_NOT_ENOUGH_RESOURCES -44
 #define H_R_STATE   -45
 #define H_RESCINDED -46
+#define H_P1   -54
 #define H_P2   -55
 #define H_P3   -56
 #define H_P4   -57
@@ -97,6 +98,8 @@
 #define H_OP_MODE  -73
 #define H_COP_HW   -74
 #define H_STATE-75
+#define H_IN_USE   -77
+#define H_ABORTED  -78
 #define H_UNSUPPORTED_FLAG_START   -256
 #define H_UNSUPPORTED_FLAG_END -511
 #define H_MULTI_THREADS_ACTIVE -9005
@@ -321,6 +324,14 @@
 #define H_SCM_UNBIND_ALL0x3FC
 #define H_SCM_HEALTH0x400
 #define H_SCM_PERFORMANCE_STATS 0x418
+#define H_PKS_GET_CONFIG   0x41C
+#define H_PKS_SET_PASSWORD 0x420
+#define H_PKS_GEN_PASSWORD 0x424
+#define H_PKS_WRITE_OBJECT 0x42C
+#define H_PKS_GEN_KEY  0x430
+#define H_PKS_READ_OBJECT  0x434
+#define H_PKS_REMOVE_OBJECT0x438
+#define H_PKS_CONFIRM_OBJECT_FLUSHED   0x43C
 #define H_RPT_INVALIDATE   0x448
 #define H_SCM_FLUSH0x44C
 #define H_GET_ENERGY_SCALE_INFO0x450
diff --git a/arch/powerpc/platforms/pseries/Kconfig 
b/arch/powerpc/platforms/pseries/Kconfig
index f7fd91d153a4..c4a6d4083a7a 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -142,6 +142,19 @@ config IBMEBUS
help
  Bus device driver for GX bus based adapters.
 
+config PSERIES_PLPKS
+   depends on PPC_PSERIES
+   bool "Support for the Platform Key Storage"
+   help
+ PowerVM provides an isolated Platform Keystore(PKS) storage
+ allocation for each LPAR with individually managed access
+ controls to store sensitive information securely. It can be
+ used to store asymmetric public keys or secrets as required
+ by different usecases. Select this config to enable
+ operating system interface to hypervisor to access this space.
+
+ If unsure, select N.
+
 config PAPR_SCM
depends on PPC_PSERIES && MEMORY_HOTPLUG && LIBNVDIMM
tristate "Support for the PAPR Storage Class Memory interface"
diff --git a/arch/powerpc/platforms/pseries/Makefile 
b/arch/powerpc/platforms/pseries/Makefile
index 7aaff5323544..14e143b946a3 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_PAPR_SCM)+= papr_scm.o
 obj-$(CONFIG_PPC_SPLPAR)   += vphn.o
 obj-$(CONFIG_PPC_SVM)  += svm.o
 obj-$(CONFIG_FA_DUMP)  += rtas-fadump.o
+obj-$(CONFIG_PSERIES_PLPKS) += plpks.o
 
 obj-$(CONFIG_SUSPEND)  += suspend.o
 obj-$(CONFIG_PPC_VAS)  += vas.o vas-sysfs.o
diff --git a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
new file mode 100644
index ..52aaa2894606
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -0,0 +1,460 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * POWER LPAR Platform KeyStore(PLPKS)
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * Provides access to variables stored in Power LPAR Platform KeyStore(PLPKS).
+ */
+
+#define pr_fmt(fmt) "plpks: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "plpks.h"
+
+#define PKS_FW_OWNER0x1
+#define PKS_BOOTLOADER_OWNER 0x2
+#define PKS_OS_OWNER0x3
+
+#define LABEL_VERSION  0
+#define MAX_LABEL_ATTR_SIZE 16
+#define MAX_NAME_SIZE  239
+#define MAX_DATA_SIZE  4000
+
+#define PKS_FLUSH_MAX_TIMEOUT 5000 //msec
+#define PKS_FLUSH_SLEEP  10 //msec
+#define PKS_FLUSH_SLEEP_RANGE 400
+
+static u8 *ospassword;
+static u16 ospasswordlength;
+
+// Retrieved with H_PKS_GET_CONFIG
+static u16 maxpwsize;
+static u16 maxobjsize;
+
+struct plpks_auth {
+   u8 version;
+   u8 consumer;
+   __be64 rsvd0;
+   __be32 r

[PATCH v2 0/3] Provide PowerVM LPAR Platform KeyStore driver for Self Encrypting Drives

2022-07-23 Thread Nayna Jain
PowerVM provides an isolated Platform KeyStore(PKS)[1] storage allocation
for each partition(LPAR) with individually managed access controls to store
sensitive information securely. The Linux Kernel can access this storage by
interfacing with the hypervisor using a new set of hypervisor calls. 

This storage can be used for multiple purposes. The current two usecases
are:

1. Guest Secure Boot on PowerVM[2]
2. Self Encrypting Drives(SED) on PowerVM[3]

Initially, the PowerVM LPAR Platform KeyStore(PLPKS) driver was defined
as part of RFC patches which included the user interface design for guest
secure boot[2]. While this interface is still in progress, the same driver
is also required for Self Encrypting Drives(SED) support. For this reason,
the driver is being split from the patchset[1] and is now separately posted
with SED arch-specific code.

This patchset provides driver for PowerVM LPAR Platform KeyStore and also
arch-specific code for SED to make use of it.

The dependency patch from patch series[3] is moved to this patchset. This
patchset now builds completely of its own.

[1]https://community.ibm.com/community/user/power/blogs/chris-engel1/2020/11/20/powervm-introduces-the-platform-keystore
[2]https://lore.kernel.org/linuxppc-dev/20220622215648.96723-1-na...@linux.ibm.com/
[3]https://lore.kernel.org/keyrings/20220718210156.1535955-1-gjo...@linux.vnet.ibm.com/T/#m8e7b2cbbd26ee1de711bd70967fd0124c85c479f

Changelog:

v2:

* Include feedback from Gregory Joyce, Eric Richter and Murilo Opsfelder Araújo.
* Include suggestions from Michael Ellerman.
* Moved a dependency from generic SED code to this patchset. This patchset now
builds of its own.

Greg Joyce (2):
  lib: define generic accessor functions for arch specific keystore
  powerpc/pseries: Override lib/arch_vars.c with PowerPC architecture
specific version

Nayna Jain (1):
  powerpc/pseries: define driver for Platform KeyStore

 arch/powerpc/include/asm/hvcall.h |  11 +
 arch/powerpc/platforms/pseries/Kconfig|  13 +
 arch/powerpc/platforms/pseries/Makefile   |   2 +
 arch/powerpc/platforms/pseries/plpks.c| 460 ++
 arch/powerpc/platforms/pseries/plpks.h|  71 +++
 .../platforms/pseries/plpks_arch_ops.c| 166 +++
 include/linux/arch_vars.h |  23 +
 lib/Makefile  |   2 +-
 lib/arch_vars.c   |  25 +
 9 files changed, 772 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/platforms/pseries/plpks.c
 create mode 100644 arch/powerpc/platforms/pseries/plpks.h
 create mode 100644 arch/powerpc/platforms/pseries/plpks_arch_ops.c
 create mode 100644 include/linux/arch_vars.h
 create mode 100644 lib/arch_vars.c

-- 
2.27.0


[PATCH 1/2] powerpc/pseries: define driver for Platform KeyStore

2022-07-12 Thread Nayna Jain
PowerVM provides an isolated Platform Keystore(PKS) storage allocation
for each LPAR with individually managed access controls to store
sensitive information securely. It provides a new set of hypervisor
calls for Linux kernel to access PKS storage.

Define PLPKS driver using H_CALL interface to access PKS storage.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/hvcall.h |   9 +
 arch/powerpc/include/asm/plpks.h  |  90 
 arch/powerpc/platforms/pseries/Kconfig|  13 +
 arch/powerpc/platforms/pseries/Makefile   |   2 +
 arch/powerpc/platforms/pseries/plpks/Makefile |   7 +
 arch/powerpc/platforms/pseries/plpks/plpks.c  | 509 ++
 6 files changed, 630 insertions(+)
 create mode 100644 arch/powerpc/include/asm/plpks.h
 create mode 100644 arch/powerpc/platforms/pseries/plpks/Makefile
 create mode 100644 arch/powerpc/platforms/pseries/plpks/plpks.c

diff --git a/arch/powerpc/include/asm/hvcall.h 
b/arch/powerpc/include/asm/hvcall.h
index d92a20a85395..24b661b0717c 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -97,6 +97,7 @@
 #define H_OP_MODE  -73
 #define H_COP_HW   -74
 #define H_STATE-75
+#define H_IN_USE   -77
 #define H_UNSUPPORTED_FLAG_START   -256
 #define H_UNSUPPORTED_FLAG_END -511
 #define H_MULTI_THREADS_ACTIVE -9005
@@ -321,6 +322,14 @@
 #define H_SCM_UNBIND_ALL0x3FC
 #define H_SCM_HEALTH0x400
 #define H_SCM_PERFORMANCE_STATS 0x418
+#define H_PKS_GET_CONFIG   0x41C
+#define H_PKS_SET_PASSWORD 0x420
+#define H_PKS_GEN_PASSWORD 0x424
+#define H_PKS_WRITE_OBJECT 0x42C
+#define H_PKS_GEN_KEY  0x430
+#define H_PKS_READ_OBJECT  0x434
+#define H_PKS_REMOVE_OBJECT0x438
+#define H_PKS_CONFIRM_OBJECT_FLUSHED   0x43C
 #define H_RPT_INVALIDATE   0x448
 #define H_SCM_FLUSH0x44C
 #define H_GET_ENERGY_SCALE_INFO0x450
diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
new file mode 100644
index ..cf60e53e1f15
--- /dev/null
+++ b/arch/powerpc/include/asm/plpks.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * Platform keystore for pseries LPAR(PLPKS).
+ */
+
+#ifndef _PSERIES_PLPKS_H
+#define _PSERIES_PLPKS_H
+
+#include 
+#include 
+
+#define OSSECBOOTAUDIT 0x4000
+#define OSSECBOOTENFORCE 0x2000
+#define WORLDREADABLE 0x0800
+#define SIGNEDUPDATE 0x0100
+
+#define PLPKS_VAR_LINUX0x01
+#define PLPKS_VAR_COMMON   0x04
+
+struct plpks_var {
+   char *component;
+   u8 os;
+   u8 *name;
+   u16 namelen;
+   u32 policy;
+   u16 datalen;
+   u8 *data;
+};
+
+struct plpks_var_name {
+   u16 namelen;
+   u8  *name;
+};
+
+struct plpks_var_name_list {
+   u32 varcount;
+   struct plpks_var_name varlist[];
+};
+
+struct plpks_config {
+   u8 version;
+   u8 flags;
+   u32 rsvd0;
+   u16 maxpwsize;
+   u16 maxobjlabelsize;
+   u16 maxobjsize;
+   u32 totalsize;
+   u32 usedspace;
+   u32 supportedpolicies;
+   u64 rsvd1;
+} __packed;
+
+/**
+ * Successful return from this API  implies PKS is available.
+ * This is used to initialize kernel driver and user interfaces.
+ */
+struct plpks_config *plpks_get_config(void);
+
+/**
+ * Writes the specified var and its data to PKS.
+ * Any caller of PKS driver should present a valid component type for
+ * their variable.
+ */
+int plpks_write_var(struct plpks_var var);
+
+/**
+ * Removes the specified var and its data from PKS.
+ */
+int plpks_remove_var(char *component, u8 varos,
+struct plpks_var_name vname);
+
+/**
+ * Returns the data for the specified os variable.
+ */
+int plpks_read_os_var(struct plpks_var *var);
+
+/**
+ * Returns the data for the specified firmware variable.
+ */
+int plpks_read_fw_var(struct plpks_var *var);
+
+/**
+ * Returns the data for the specified bootloader variable.
+ */
+int plpks_read_bootloader_var(struct plpks_var *var);
+
+#endif
diff --git a/arch/powerpc/platforms/pseries/Kconfig 
b/arch/powerpc/platforms/pseries/Kconfig
index f7fd91d153a4..de6efe5d18c2 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -142,6 +142,19 @@ config IBMEBUS
help
  Bus device driver for GX bus based adapters.
 
+config PSERIES_PLPKS
+   depends on PPC_PSERIES
+   tristate "Support for the Platform Key Storage"
+   help
+ PowerVM provides an isolated Platform Keystore(PKS) storage
+ allocation for each LPAR with individually managed access
+ controls to store sensitive information securely. It can be
+ used to store asymmetric public keys or secrets as required
+ by different usecases. Select this config to enable
+ operating system interface to hypervisor

[PATCH 2/2] powerpc/pseries: kernel interfaces to PLPKS platform driver

2022-07-12 Thread Nayna Jain
From: Greg Joyce 

Add platform specific interfaces arch_read_variable() and
arch_variable() to allow platform agnostic access to platform
variable stores.

Signed-off-by: Greg Joyce 
---
 arch/powerpc/platforms/pseries/plpks/Makefile |   1 +
 .../platforms/pseries/plpks/plpks_arch_ops.c  | 163 ++
 2 files changed, 164 insertions(+)
 create mode 100644 arch/powerpc/platforms/pseries/plpks/plpks_arch_ops.c

diff --git a/arch/powerpc/platforms/pseries/plpks/Makefile 
b/arch/powerpc/platforms/pseries/plpks/Makefile
index e651ace920db..3e9ce6f16575 100644
--- a/arch/powerpc/platforms/pseries/plpks/Makefile
+++ b/arch/powerpc/platforms/pseries/plpks/Makefile
@@ -5,3 +5,4 @@
 #
 
 obj-$(CONFIG_PSERIES_PLPKS)  += plpks.o
+obj-$(CONFIG_PSERIES_PLPKS)  += plpks_arch_ops.o
diff --git a/arch/powerpc/platforms/pseries/plpks/plpks_arch_ops.c 
b/arch/powerpc/platforms/pseries/plpks/plpks_arch_ops.c
new file mode 100644
index ..11cd03da08b7
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpks/plpks_arch_ops.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * POWER platform keystore
+ * Copyright (C) 2022 IBM Corporation
+ *
+ * This pseries platform device driver provides access to
+ * variables stored in platform keystore.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * variable structure that contains all SED data
+ */
+struct plpks_sed_object_data {
+   u_char version;
+   u_char pad1[7];
+   u_long authority;
+   u_long range;
+   u_int  key_len;
+   u_char key[32];
+};
+
+/*
+ * ext_type values
+ * 00no extension exists
+ * 01-1F common
+ * 20-3F AIX
+ * 40-5F Linux
+ * 60-7F IBMi
+ */
+
+/*
+ * This extension is optional for version 1 sed_object_data
+ */
+struct sed_object_extension {
+   u8 ext_type;
+   u8 rsvd[3];
+   u8 ext_data[64];
+};
+
+#define PKS_SED_OBJECT_DATA_V1  1
+#define PKS_SED_MANGLED_LABEL   "/default/pri"
+#define PLPKS_SED_COMPONENT "sed-opal"
+#define PLPKS_SED_POLICYWORLDREADABLE
+#define PLPKS_SED_OS_COMMON 4
+
+#ifndef CONFIG_BLK_SED_OPAL
+#defineOPAL_AUTH_KEY   ""
+#endif
+
+/*
+ * Read the variable data from PKS given the label
+ */
+int arch_read_variable(enum arch_variable_type type, char *varname,
+  void *varbuf, u_int *varlen)
+{
+   struct plpks_var var;
+   struct plpks_sed_object_data *data;
+   u_int offset = 0;
+   char *buf = (char *)varbuf;
+   int ret;
+
+   var.name = varname;
+   var.namelen = strlen(varname);
+   var.policy = PLPKS_SED_POLICY;
+   var.os = PLPKS_SED_OS_COMMON;
+   var.data = NULL;
+   var.datalen = 0;
+
+   switch (type) {
+   case ARCH_VAR_OPAL_KEY:
+   var.component = PLPKS_SED_COMPONENT;
+   if (strcmp(OPAL_AUTH_KEY, varname) == 0) {
+   var.name = PKS_SED_MANGLED_LABEL;
+   var.namelen = strlen(varname);
+   }
+   offset = offsetof(struct plpks_sed_object_data, key);
+   break;
+   case ARCH_VAR_OTHER:
+   var.component = "";
+   break;
+   }
+
+   ret = plpks_read_os_var();
+   if (ret != 0)
+   return ret;
+
+   if (offset > var.datalen)
+   offset = 0;
+
+   switch (type) {
+   case ARCH_VAR_OPAL_KEY:
+   data = (struct plpks_sed_object_data *)var.data;
+   *varlen = data->key_len;
+   break;
+   case ARCH_VAR_OTHER:
+   *varlen = var.datalen;
+   break;
+   }
+
+   if (var.data) {
+   memcpy(varbuf, var.data + offset, var.datalen - offset);
+   buf[*varlen] = '\0';
+   kfree(var.data);
+   }
+
+   return 0;
+}
+
+/*
+ * Write the variable data to PKS given the label
+ */
+int arch_write_variable(enum arch_variable_type type, char *varname,
+   void *varbuf, u_int varlen)
+{
+   struct plpks_var var;
+   struct plpks_sed_object_data data;
+   struct plpks_var_name vname;
+
+   var.name = varname;
+   var.namelen = strlen(varname);
+   var.policy = PLPKS_SED_POLICY;
+   var.os = PLPKS_SED_OS_COMMON;
+   var.datalen = varlen;
+   var.data = varbuf;
+
+   switch (type) {
+   case ARCH_VAR_OPAL_KEY:
+   var.component = PLPKS_SED_COMPONENT;
+   if (strcmp(OPAL_AUTH_KEY, varname) == 0) {
+   var.name = PKS_SED_MANGLED_LABEL;
+   var.namelen = strlen(varname);
+   }
+   var.datalen = sizeof(struct plpks_sed_object_data);
+   var.data = (u8 *)
+
+   /* initialize SED object */
+   data.version = PKS_SED_OBJECT_DATA_V1;
+   data.authority = 

[PATCH 0/2] Provide PowerVM LPAR Platform KeyStore driver for Self Encrypting Drives

2022-07-12 Thread Nayna Jain
PowerVM provides an isolated Platform KeyStore(PKS)[1] storage allocation
for each partition(LPAR) with individually managed access controls to store
sensitive information securely. The Linux Kernel can access this storage by
interfacing with the hypervisor using a new set of hypervisor calls. 

This storage can be used for multiple purposes. The current two usecases
are:

1. Guest Secure Boot on PowerVM[2]
2. Self Encrypting Drives(SED) on PowerVM[3]

Initially, the PowerVM LPAR Platform KeyStore(PLPKS) driver was defined
as part of RFC patches which included the user interface design for guest
secure boot[2]. While this interface is still in progress, the same driver
is also required for Self Encrypting Drives(SED) support. For this reason,
the driver is being split from the patchset[1] and is now separately posted
with SED arch-specific code.

This patchset provides driver for PowerVM LPAR Platform KeyStore and also
arch-specific code for SED to make use of it.

The patch series[3] is pre-requisite to build Patch 2/2. The PLPKS
driver can be built of its own.

[1]https://community.ibm.com/community/user/power/blogs/chris-engel1/2020/11/20/powervm-introduces-the-platform-keystore
[2]https://lore.kernel.org/linuxppc-dev/20220622215648.96723-1-na...@linux.ibm.com/
[3]https://lore.kernel.org/keyrings/20220706023935.875994-1-gjo...@linux.vnet.ibm.com/T/#mc32b51991bf825ec6f90af010998ec7cd2b9624a

Greg Joyce (1):
  powerpc/pseries: kernel interfaces to PLPKS platform driver

Nayna Jain (1):
  powerpc/pseries: define driver for Platform KeyStore

 arch/powerpc/include/asm/hvcall.h |   9 +
 arch/powerpc/include/asm/plpks.h  |  90 
 arch/powerpc/platforms/pseries/Kconfig|  13 +
 arch/powerpc/platforms/pseries/Makefile   |   2 +
 arch/powerpc/platforms/pseries/plpks/Makefile |   8 +
 arch/powerpc/platforms/pseries/plpks/plpks.c  | 509 ++
 .../platforms/pseries/plpks/plpks_arch_ops.c  | 163 ++
 7 files changed, 794 insertions(+)
 create mode 100644 arch/powerpc/include/asm/plpks.h
 create mode 100644 arch/powerpc/platforms/pseries/plpks/Makefile
 create mode 100644 arch/powerpc/platforms/pseries/plpks/plpks.c
 create mode 100644 arch/powerpc/platforms/pseries/plpks/plpks_arch_ops.c

-- 
2.27.0


[RFC PATCH v2 3/3] powerpc/pseries: expose authenticated variables stored in LPAR PKS

2022-06-22 Thread Nayna Jain
PowerVM Guest Secure boot feature need to expose firmware managed
secure variables for user management. These variables store keys for
grub/kernel verification and also corresponding denied list.

Expose these variables to the userpace via fwsecurityfs.

Example:

Example:

# cd /sys/firmware/security/secvars

# pwd
/sys/firmware/security/secvars

# cat /tmp/PK.bin > PK

# ls -l
total 0
-rw-r--r-- 1 root root 2497 Jun 22 08:34 PK

# hexdump -C PK
  00 00 00 00 00 08 00 00  a1 59 c0 a5 e4 94 a7 4a  |.Y.J|
0010  87 b5 ab 15 5c 2b f0 72  3f 03 00 00 00 00 00 00  |\+.r?...|
0020  23 03 00 00 ca 18 1d 1c  01 7d eb 11 9a 71 08 94  |#}...q..|
0030  ef 31 fb e4 30 82 03 0f  30 82 01 f7 a0 03 02 01  |.1..0...0...|
0040  02 02 14 22 ab 18 2f d5  aa dd c5 ba 98 27 60 26  |..."../..'`&|
0050  f1 63 89 54 4c 52 d9 30  0d 06 09 2a 86 48 86 f7  |.c.TLR.0...*.H..|
...

Signed-off-by: Nayna Jain 
---
 arch/powerpc/platforms/pseries/Kconfig|  17 ++
 arch/powerpc/platforms/pseries/plpks/Makefile |   2 +
 .../pseries/plpks/fwsecurityfs_arch.c |  16 ++
 .../platforms/pseries/plpks/internal.h|  18 ++
 .../powerpc/platforms/pseries/plpks/secvars.c | 239 ++
 include/linux/fwsecurityfs.h  |   4 +
 6 files changed, 296 insertions(+)
 create mode 100644 arch/powerpc/platforms/pseries/plpks/fwsecurityfs_arch.c
 create mode 100644 arch/powerpc/platforms/pseries/plpks/internal.h
 create mode 100644 arch/powerpc/platforms/pseries/plpks/secvars.c

diff --git a/arch/powerpc/platforms/pseries/Kconfig 
b/arch/powerpc/platforms/pseries/Kconfig
index 6c1ca487103f..9c52095e20c4 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -152,6 +152,23 @@ config PSERIES_PLPKS
  config to enable operating system interface to hypervisor to
  access this space.
 
+config PSERIES_FWSECURITYFS_ARCH
+   depends on FWSECURITYFS
+   bool "Support fwsecurityfs for pseries"
+   help
+ Enable fwsecuirtyfs arch specific code. This would initialize
+ the firmware security filesystem with initial platform specific
+ structure.
+
+config PSERIES_PLPKS_SECVARS
+   depends on PSERIES_PLPKS
+   select PSERIES_FWSECURITYFS_ARCH
+   tristate "Support for secvars"
+   help
+ This interface exposes authenticated variables stored in the LPAR
+ Platform KeyStore using fwsecurityfs interface.
+ If you are unsure how to use it, say N.
+
 config PAPR_SCM
depends on PPC_PSERIES && MEMORY_HOTPLUG && LIBNVDIMM
tristate "Support for the PAPR Storage Class Memory interface"
diff --git a/arch/powerpc/platforms/pseries/plpks/Makefile 
b/arch/powerpc/platforms/pseries/plpks/Makefile
index e651ace920db..ff3d4b4cd3d7 100644
--- a/arch/powerpc/platforms/pseries/plpks/Makefile
+++ b/arch/powerpc/platforms/pseries/plpks/Makefile
@@ -5,3 +5,5 @@
 #
 
 obj-$(CONFIG_PSERIES_PLPKS)  += plpks.o
+obj-$(CONFIG_PSERIES_FWSECURITYFS_ARCH) += fwsecurityfs_arch.o
+obj-$(CONFIG_PSERIES_PLPKS_SECVARS) += secvars.o
diff --git a/arch/powerpc/platforms/pseries/plpks/fwsecurityfs_arch.c 
b/arch/powerpc/platforms/pseries/plpks/fwsecurityfs_arch.c
new file mode 100644
index ..6ccdfe4000a6
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpks/fwsecurityfs_arch.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * POWER LPAR Platform KeyStore (PLPKS)
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ */
+
+#include 
+
+#include "internal.h"
+
+int arch_fwsecurity_init(void)
+{
+   return plpks_secvars_init();
+}
diff --git a/arch/powerpc/platforms/pseries/plpks/internal.h 
b/arch/powerpc/platforms/pseries/plpks/internal.h
new file mode 100644
index ..6061ffd37677
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpks/internal.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ */
+#ifndef PKS_FWSEC_INTERNAL
+#define PKS_FWSEC_INTERNAL
+
+#ifdef CONFIG_PSERIES_PLPKS_SECVARS
+int plpks_secvars_init(void);
+#else
+int plpks_secvars_init(void)
+{
+   return 0;
+}
+#endif
+#endif
diff --git a/arch/powerpc/platforms/pseries/plpks/secvars.c 
b/arch/powerpc/platforms/pseries/plpks/secvars.c
new file mode 100644
index ..8852cb8f2f3c
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/plpks/secvars.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * POWER LPAR Platform KeyStore (PLPKS)
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "internal.h"
+
+static struct dentry *secvar_dir;
+
+static const char * const names[] = {
+   "PK",
+  

[RFC PATCH v2 2/3] fs: define a firmware security filesystem named fwsecurityfs

2022-06-22 Thread Nayna Jain
securityfs is meant for linux security subsystems to expose policies/logs
or any other information. However, there are various firmware security
features which expose their variables for user management via kernel.
There is currently no single place to expose these variables. Different
platforms use sysfs/platform specific filesystem(efivarfs)/securityfs
interface as find appropriate. Thus, there is a gap in kernel interfaces
to expose variables for security features.

Define a firmware security filesystem (fwsecurityfs) to be used for
exposing variables managed by firmware and to be used by firmware
enabled security features. These variables are platform specific.
Filesystem provides platforms to implement their own underlying
semantics by defining own inode and file operations.

Similar to securityfs, the firmware security filesystem is recommended
to be exposed on a well known mount point /sys/firmware/security.
Platforms can define their own directory or file structure under this path.

Example:

# mount -t fwsecurityfs fwsecurityfs /sys/firmware/security

# cd /sys/firmware/security/

Signed-off-by: Nayna Jain 
---
 fs/Kconfig   |   1 +
 fs/Makefile  |   1 +
 fs/fwsecurityfs/Kconfig  |  14 +++
 fs/fwsecurityfs/Makefile |  10 +++
 fs/fwsecurityfs/inode.c  | 159 +++
 fs/fwsecurityfs/internal.h   |  13 +++
 fs/fwsecurityfs/super.c  | 154 +
 include/linux/fwsecurityfs.h |  29 +++
 include/uapi/linux/magic.h   |   1 +
 9 files changed, 382 insertions(+)
 create mode 100644 fs/fwsecurityfs/Kconfig
 create mode 100644 fs/fwsecurityfs/Makefile
 create mode 100644 fs/fwsecurityfs/inode.c
 create mode 100644 fs/fwsecurityfs/internal.h
 create mode 100644 fs/fwsecurityfs/super.c
 create mode 100644 include/linux/fwsecurityfs.h

diff --git a/fs/Kconfig b/fs/Kconfig
index 5976eb33535f..19ea28143428 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -276,6 +276,7 @@ config ARCH_HAS_GIGANTIC_PAGE
 
 source "fs/configfs/Kconfig"
 source "fs/efivarfs/Kconfig"
+source "fs/fwsecurityfs/Kconfig"
 
 endmenu
 
diff --git a/fs/Makefile b/fs/Makefile
index 208a74e0b00e..5792cd0443cb 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -137,6 +137,7 @@ obj-$(CONFIG_F2FS_FS)   += f2fs/
 obj-$(CONFIG_CEPH_FS)  += ceph/
 obj-$(CONFIG_PSTORE)   += pstore/
 obj-$(CONFIG_EFIVAR_FS)+= efivarfs/
+obj-$(CONFIG_FWSECURITYFS) += fwsecurityfs/
 obj-$(CONFIG_EROFS_FS) += erofs/
 obj-$(CONFIG_VBOXSF_FS)+= vboxsf/
 obj-$(CONFIG_ZONEFS_FS)+= zonefs/
diff --git a/fs/fwsecurityfs/Kconfig b/fs/fwsecurityfs/Kconfig
new file mode 100644
index ..f1665511eeb9
--- /dev/null
+++ b/fs/fwsecurityfs/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 IBM Corporation
+# Author: Nayna Jain 
+#
+
+config FWSECURITYFS
+   bool "Enable the fwsecurityfs filesystem"
+   help
+ This will build the fwsecurityfs file system which is recommended
+ to be mounted on /sys/firmware/security. This can be used by
+ platforms to expose their variables which are managed by firmware.
+
+ If you are unsure how to answer this question, answer N.
diff --git a/fs/fwsecurityfs/Makefile b/fs/fwsecurityfs/Makefile
new file mode 100644
index ..b9931d180178
--- /dev/null
+++ b/fs/fwsecurityfs/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 IBM Corporation
+# Author: Nayna Jain 
+#
+# Makefile for the firmware security filesystem
+
+obj-$(CONFIG_FWSECURITYFS) += fwsecurityfs.o
+
+fwsecurityfs-objs  := inode.o super.o
diff --git a/fs/fwsecurityfs/inode.c b/fs/fwsecurityfs/inode.c
new file mode 100644
index ..5d06dc0de059
--- /dev/null
+++ b/fs/fwsecurityfs/inode.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "internal.h"
+
+int fwsecurityfs_remove_file(struct dentry *dentry)
+{
+   drop_nlink(d_inode(dentry));
+   dput(dentry);
+   return 0;
+};
+EXPORT_SYMBOL_GPL(fwsecurityfs_remove_file);
+
+int fwsecurityfs_create_file(const char *name, umode_t mode,
+   u16 filesize, struct dentry *parent,
+   struct dentry *dentry,
+   const struct file_operations *fops)
+{
+   struct inode *inode;
+   int error;
+   struct inode *dir;
+
+   if (!parent)
+   return -EINVAL;
+
+   dir = d_inode(parent);
+   pr_debug("securityfs: creating file '%s'\n", name)

[RFC PATCH v2 0/3] powerpc/pseries: add support for local secure storage called Platform KeyStore(PKS)

2022-06-22 Thread Nayna Jain
PowerVM provides an isolated Platform KeyStore(PKS)[1] storage allocation
for each partition(LPAR) with individually managed access controls to store
sensitive information securely. Linux Kernel can access this storage by
interfacing with hypervisor using a new set of hypervisor calls. 

PowerVM guest secure boot feature intend to use Platform KeyStore for
the purpose of storing public keys. Secure boot requires public keys to
be able to verify the grub and boot kernel. To allow authenticated
 manipulation of keys, it supports variables to store key authorities
- PK/KEK. Other variables are used to store code signing keys - db/grubdb.
It also supports denied list to disallow booting even if signed with
valid key. This is done via denied list database - dbx or sbat. These
variables would be stored in PKS, and are managed and controlled by
firmware.

The purpose of this patchset is to add userspace interface to manage
these variables.

For v1[2] version, we received following feedback
"Ok, this is like the 3rd or 4th different platform-specific proposal for
this type of functionality.  I think we need to give up on
platform-specific user/kernel apis on this (random sysfs/securityfs
files scattered around the tree), and come up with a standard place for
all of this."

Currently, OpenPOWER exposes variables via sysfs, while EFI platforms
have used sysfs and then moved to their own efivarfs filesystem.
Recently, coco feature is using securityfs to expose their
secrets. All of these environments are different both syntactically and
semantically.

securityfs is meant for linux security subsystems to expose policies/logs
or any other information, and do not interact with firmware for managing
these variables. However, there are various firmware security
features which expose their variables for user management via kernel as
discussed above. There is currently no single place to expose these
variables. Different platforms use sysfs/platform specific
filesystem(efivarfs)/securityfs interface as find appropriate. This has
resulted in interfaces scattered around the tree.

This resulted in demand of a need for a common single place for new
platform interfaces to expose their variables for firmware security
features. This would simplify the interface for users of these platforms.
This patchset proposes firmware security filesystem(fwsecurityfs). Any
platform can expose the variables which are required by firmware security
features via this interface. Going forward, this would give a common place
for exposing variables managed by firmware while still allowing platforms
to implement their own underlying semantics.

This design consists of two parts:
1. firmware security filesystem(fwsecurityfs) that provides platforms with
APIs to create their own underlying directory and file structure. It is
recommended to establish a well known mount point:
i.e. /sys/firmware/security/

2. platform specific implementation for these variables which implements
underlying semantics. Platforms can expose their variables as files
allowing read/write/add/delete operations by defining their own inode and
file operations.

This patchset defines:
1. pseries driver to access LPAR Platform Key Store(PLPKS)
2. firmware security filesystem named fwsecurityfs
3. Interface to expose secure variables stored in LPAR PKS via fwsecurityfs

[1] 
https://community.ibm.com/community/user/power/blogs/chris-engel1/2020/11/20/powervm-introduces-the-platform-keystore
[2] 
https://lore.kernel.org/linuxppc-dev/20220122005637.28199-1-na...@linux.ibm.com/

Changelog:

v1:

* Defined unified interface(firmware security filesystem) for all platforms
to expose their variables used for security features. 
* Expose secvars using firmware security fileystem.
* Renamed PKS driver to PLPKS to avoid naming conflict as mentioned by
Dave Hanson.

Nayna Jain (3):
  powerpc/pseries: define driver for Platform KeyStore
  fs: define a firmware security filesystem named fwsecurityfs
  powerpc/pseries: expose authenticated variables stored in LPAR PKS

 arch/powerpc/include/asm/hvcall.h |  12 +-
 arch/powerpc/include/asm/plpks.h  |  92 
 arch/powerpc/platforms/pseries/Kconfig|  27 +
 arch/powerpc/platforms/pseries/Makefile   |   2 +
 arch/powerpc/platforms/pseries/plpks/Makefile |   9 +
 .../pseries/plpks/fwsecurityfs_arch.c |  16 +
 .../platforms/pseries/plpks/internal.h|  18 +
 arch/powerpc/platforms/pseries/plpks/plpks.c  | 517 ++
 .../powerpc/platforms/pseries/plpks/secvars.c | 239 
 fs/Kconfig|   1 +
 fs/Makefile   |   1 +
 fs/fwsecurityfs/Kconfig   |  14 +
 fs/fwsecurityfs/Makefile  |  10 +
 fs/fwsecurityfs/inode.c   | 159 ++
 fs/fwsecurityfs/internal.h|  13 +
 fs/fwsecurityfs/super.c   | 154 ++
 inc

[RFC PATCH v2 1/3] powerpc/pseries: define driver for Platform KeyStore

2022-06-22 Thread Nayna Jain
PowerVM provides an isolated Platform Keystore(PKS) storage allocation
for each LPAR with individually managed access controls to store
sensitive information securely. It provides a new set of hypervisor
calls for Linux kernel to access PKS storage.

Define PLPKS driver using H_CALL interface to access PKS storage.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/hvcall.h |  12 +-
 arch/powerpc/include/asm/plpks.h  |  92 
 arch/powerpc/platforms/pseries/Kconfig|  10 +
 arch/powerpc/platforms/pseries/Makefile   |   2 +
 arch/powerpc/platforms/pseries/plpks/Makefile |   7 +
 arch/powerpc/platforms/pseries/plpks/plpks.c  | 517 ++
 6 files changed, 639 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/include/asm/plpks.h
 create mode 100644 arch/powerpc/platforms/pseries/plpks/Makefile
 create mode 100644 arch/powerpc/platforms/pseries/plpks/plpks.c

diff --git a/arch/powerpc/include/asm/hvcall.h 
b/arch/powerpc/include/asm/hvcall.h
index d92a20a85395..1da429235632 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -97,6 +97,7 @@
 #define H_OP_MODE  -73
 #define H_COP_HW   -74
 #define H_STATE-75
+#define H_IN_USE   -77
 #define H_UNSUPPORTED_FLAG_START   -256
 #define H_UNSUPPORTED_FLAG_END -511
 #define H_MULTI_THREADS_ACTIVE -9005
@@ -321,10 +322,19 @@
 #define H_SCM_UNBIND_ALL0x3FC
 #define H_SCM_HEALTH0x400
 #define H_SCM_PERFORMANCE_STATS 0x418
+#define H_PKS_GET_CONFIG   0x41C
+#define H_PKS_SET_PASSWORD 0x420
+#define H_PKS_GEN_PASSWORD 0x424
+#define H_PKS_WRITE_OBJECT 0x42C
+#define H_PKS_GEN_KEY  0x430
+#define H_PKS_READ_OBJECT  0x434
+#define H_PKS_REMOVE_OBJECT0x438
+#define H_PKS_CONFIRM_OBJECT_FLUSHED   0x43C
 #define H_RPT_INVALIDATE   0x448
 #define H_SCM_FLUSH0x44C
 #define H_GET_ENERGY_SCALE_INFO0x450
-#define MAX_HCALL_OPCODE   H_GET_ENERGY_SCALE_INFO
+#define H_PKS_SIGNED_UPDATE0x454
+#define MAX_HCALL_OPCODE   H_PKS_SIGNED_UPDATE
 
 /* Scope args for H_SCM_UNBIND_ALL */
 #define H_UNBIND_SCOPE_ALL (0x1)
diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
new file mode 100644
index ..c3b544bdbcb6
--- /dev/null
+++ b/arch/powerpc/include/asm/plpks.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * Platform keystore for pseries LPAR(PLPKS).
+ */
+
+#ifndef _PSERIES_PLPKS_H
+#define _PSERIES_PLPKS_H
+
+
+#include 
+#include 
+
+
+#define OSSECBOOTAUDIT 0x4000
+#define OSSECBOOTENFORCE 0x2000
+#define WORLDREADABLE 0x0800
+#define SIGNEDUPDATE 0x0100
+
+struct plpks_var {
+   char *component;
+   u8 *name;
+   u16 namelen;
+   u32 policy;
+   u16 datalen;
+   u8 *data;
+};
+
+struct plpks_var_name {
+   u16 namelen;
+   u8  *name;
+};
+
+struct plpks_var_name_list {
+   u32 varcount;
+   struct plpks_var_name varlist[];
+};
+
+struct plpks_config {
+   u8 version;
+   u8 flags;
+   u32 rsvd0;
+   u16 maxpwsize;
+   u16 maxobjlabelsize;
+   u16 maxobjsize;
+   u32 totalsize;
+   u32 usedspace;
+   u32 supportedpolicies;
+   u64 rsvd1;
+} __packed;
+
+/**
+ * Successful return from this API  implies PKS is available.
+ * This is used to initialize kernel driver and user interfaces.
+ */
+extern struct plpks_config *plpks_get_config(void);
+
+/**
+ * Updates the authenticated variable. It expects NULL as the component.
+ */
+extern int plpks_signed_update_var(struct plpks_var var);
+
+/**
+ * Writes the specified var and its data to PKS.
+ * Any caller of PKS driver should present a valid component type for
+ * their variable.
+ */
+extern int plpks_write_var(struct plpks_var var);
+
+/**
+ * Removes the specified var and its data from PKS.
+ */
+extern int plpks_remove_var(char *component, struct plpks_var_name vname);
+
+/**
+ * Returns the data for the specified os variable.
+ */
+extern int plpks_read_os_var(struct plpks_var *var);
+
+/**
+ * Returns the data for the specified firmware variable.
+ */
+extern int plpks_read_fw_var(struct plpks_var *var);
+
+/**
+ * Returns the data for the specified bootloader variable.
+ */
+extern int plpks_read_bootloader_var(struct plpks_var *var);
+
+#endif
diff --git a/arch/powerpc/platforms/pseries/Kconfig 
b/arch/powerpc/platforms/pseries/Kconfig
index f7fd91d153a4..6c1ca487103f 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -142,6 +142,16 @@ config IBMEBUS
help
  Bus device driver for GX bus based adapters.
 
+config PSERIES_PLPKS
+   depends on PPC_PSERIES
+   tristate "Support for the Platform Key Storage"
+   help
+ PowerVM provides an isolated Platform Keystore(PKS) storage
+ allocatio

[RFC PATCH 2/2] pseries: define sysfs interface to expose PKS variables

2022-01-21 Thread Nayna Jain
PowerVM guest secure boot intend to use Platform Keystore(PKS) for the
purpose of storing public keys to verify digital signature.

Define sysfs interface to expose PKS variables to userspace to allow
read/write/add/delete operations. Each variable is shown as a read/write
attribute file. The size of the file represents the size of the current
content of the variable.

create_var and delete_var attribute files are always present which allow
users to create/delete variables. These are write only attributes.The
design has tried to be compliant with sysfs semantic to represent single
value per attribute. Thus, rather than mapping a complete data structure
representation to create_var, it only accepts a single formatted string
to create an empty variable.

The sysfs interface is designed such as to expose PKS configuration
properties, operating system variables and firmware variables.
Current version exposes configuration and operating system variables.
The support for exposing firmware variables will be added in the future
version.

Example of pksvar sysfs interface:

# cd /sys/firmware/pksvar/
# ls
config  os

# cd config

# ls -ltrh
total 0
-r--r--r-- 1 root root 64K Jan 21 17:55 version
-r--r--r-- 1 root root 64K Jan 21 17:55 used_space
-r--r--r-- 1 root root 64K Jan 21 17:55 total_size
-r--r--r-- 1 root root 64K Jan 21 17:55 supported_policies
-r--r--r-- 1 root root 64K Jan 21 17:55 max_object_size
-r--r--r-- 1 root root 64K Jan 21 17:55 max_object_label_size
-r--r--r-- 1 root root 64K Jan 21 17:55 flags

# cd os

# ls -ltrh
total 0
-rw--- 1 root root 104 Jan 21 17:56 var4
-rw--- 1 root root 104 Jan 21 17:56 var3
-rw--- 1 root root 831 Jan 21 17:56 GLOBAL_PK
-rw--- 1 root root 831 Jan 21 17:56 GLOBAL_KEK
-rw--- 1 root root  76 Jan 21 17:56 GLOBAL_dbx
-rw--- 1 root root 831 Jan 21 17:56 GLOBAL_db
--w--- 1 root root 64K Jan 21 17:56 delete_var
--w--- 1 root root 64K Jan 21 17:56 create_var

1. Read variable

# hexdump -C GLOBAL_db
  00 00 00 00 a1 59 c0 a5  e4 94 a7 4a 87 b5 ab 15  |.Y.J|
0010  5c 2b f0 72 3f 03 00 00  00 00 00 00 23 03 00 00  |\+.r?...#...|

0330  02 a8 e8 ed 0f 20 60 3f  40 04 7c a8 91 21 37 eb  |. `?@.|..!7.|
0340  f3 f1 4e  |..N|
0343

2. Write variable

cat /tmp/data.bin > 

3. Create variable

# echo "var1" > create_var
# ls -ltrh
total 0
-rw--- 1 root root 104 Jan 21 17:56 var4
-rw--- 1 root root 104 Jan 21 17:56 var3
-rw--- 1 root root 831 Jan 21 17:56 GLOBAL_PK
-rw--- 1 root root 831 Jan 21 17:56 GLOBAL_KEK
-rw--- 1 root root  76 Jan 21 17:56 GLOBAL_dbx
-rw--- 1 root root 831 Jan 21 17:56 GLOBAL_db
--w--- 1 root root 64K Jan 21 17:56 delete_var
--w--- 1 root root 64K Jan 21 17:57 create_var
-rw--- 1 root root   0 Jan 21 17:57 var1.tmp

Current design creates a zero size temporary variable. This implies
it is not yet persisted to PKS. Only once data is written to newly
created temporary variable and if it is successfully stored in the
PKS, that the variable is permanent. The temporary variable will get
removed on reboot. The code currently doesn't remove .tmp suffix
immediately when persisted. The future version will fix this.

To avoid the additional .tmp semantic, alternative option is to consider
any zero size variable as temporary variable. This option is under
evaluation. This would avoid any runtime sysfs magic to replace .tmp
variable with real variable.

Also, the formatted string to pass to create_var will have following
format in the future version:
:

4. Delete variable
# echo "var3" > delete_var
# ls -ltrh
total 0
-rw--- 1 root root 104 Jan 21 17:56 var4
-rw--- 1 root root 831 Jan 21 17:56 GLOBAL_PK
-rw--- 1 root root 831 Jan 21 17:56 GLOBAL_KEK
-rw--- 1 root root  76 Jan 21 17:56 GLOBAL_dbx
-rw--- 1 root root 831 Jan 21 17:56 GLOBAL_db
--w--- 1 root root 64K Jan 21 17:57 create_var
-rw--- 1 root root   0 Jan 21 17:57 var1.tmp
--w--- 1 root root 64K Jan 21 17:58 delete_var

The var3 file is removed at runtime, if variable is successfully
removed from the PKS storage.

NOTE: We are evaluating two design for userspace interface: using the
sysfs or defining a new filesystem based. Any feedback on this sysfs based
approach would be highly appreciated. We have tried to follow one value
per attribute semantic. If that or any other semantics aren't followed
properly, please let us know.

Signed-off-by: Nayna Jain 
---
 Documentation/ABI/testing/sysfs-pksvar|  77 
 arch/powerpc/platforms/pseries/Kconfig|   7 +
 arch/powerpc/platforms/pseries/Makefile   |   1 +
 arch/powerpc/platforms/pseries/pksvar-sysfs.c | 356 ++
 4 files changed, 441 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-pksvar
 create mode 100644 arch/powerpc/platforms/pseries/pksvar-sysfs.c

diff --git a/Documentation/ABI/testing/sysfs-pksvar

[RFC PATCH 1/2] pseries: define driver for Platform Keystore

2022-01-21 Thread Nayna Jain
PowerVM provides an isolated Platform Keystore(PKS) storage allocation
for each partition with individually managed access controls to store
sensitive information securely. It provides a new set of hypervisor
calls for Linux kernel to access PKS storage.

Define PKS driver using H_CALL interface to access PKS storage.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/hvcall.h   |  13 +-
 arch/powerpc/include/asm/pks.h  |  84 
 arch/powerpc/platforms/pseries/Kconfig  |  10 +
 arch/powerpc/platforms/pseries/Makefile |   1 +
 arch/powerpc/platforms/pseries/pks.c| 494 
 5 files changed, 601 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/include/asm/pks.h
 create mode 100644 arch/powerpc/platforms/pseries/pks.c

diff --git a/arch/powerpc/include/asm/hvcall.h 
b/arch/powerpc/include/asm/hvcall.h
index 9bcf345cb208..08108dcf8677 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -97,6 +97,7 @@
 #define H_OP_MODE  -73
 #define H_COP_HW   -74
 #define H_STATE-75
+#define H_IN_USE   -77
 #define H_UNSUPPORTED_FLAG_START   -256
 #define H_UNSUPPORTED_FLAG_END -511
 #define H_MULTI_THREADS_ACTIVE -9005
@@ -321,9 +322,19 @@
 #define H_SCM_UNBIND_ALL0x3FC
 #define H_SCM_HEALTH0x400
 #define H_SCM_PERFORMANCE_STATS 0x418
+#define H_PKS_GET_CONFIG   0x41C
+#define H_PKS_SET_PASSWORD 0x420
+#define H_PKS_GEN_PASSWORD 0x424
+#define H_PKS_GET_OBJECT_LABELS 0x428
+#define H_PKS_WRITE_OBJECT 0x42C
+#define H_PKS_GEN_KEY  0x430
+#define H_PKS_READ_OBJECT  0x434
+#define H_PKS_REMOVE_OBJECT0x438
+#define H_PKS_CONFIRM_OBJECT_FLUSHED   0x43C
 #define H_RPT_INVALIDATE   0x448
 #define H_SCM_FLUSH0x44C
-#define MAX_HCALL_OPCODE   H_SCM_FLUSH
+#define H_PKS_SB_SIGNED_UPDATE 0x454
+#define MAX_HCALL_OPCODE   H_PKS_SB_SIGNED_UPDATE
 
 /* Scope args for H_SCM_UNBIND_ALL */
 #define H_UNBIND_SCOPE_ALL (0x1)
diff --git a/arch/powerpc/include/asm/pks.h b/arch/powerpc/include/asm/pks.h
new file mode 100644
index ..ef6f541d75d3
--- /dev/null
+++ b/arch/powerpc/include/asm/pks.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain
+ *
+ * Platform keystore for pseries.
+ */
+#ifndef _PSERIES_PKS_H
+#define _PSERIES_PKS_H
+
+
+#include 
+#include 
+
+struct pks_var {
+   char *prefix;
+   u8 *name;
+   u16 namelen;
+   u32 policy;
+   u16 datalen;
+   u8 *data;
+};
+
+struct pks_var_name {
+   u16 namelen;
+   u8  *name;
+};
+
+struct pks_var_name_list {
+   u32 varcount;
+   struct pks_var_name *varlist;
+};
+
+struct pks_config {
+   u8 version;
+   u8 flags;
+   u32 rsvd0;
+   u16 maxpwsize;
+   u16 maxobjlabelsize;
+   u16 maxobjsize;
+   u32 totalsize;
+   u32 usedspace;
+   u32 supportedpolicies;
+   u64 rsvd1;
+} __packed;
+
+/**
+ * Successful return from this API  implies PKS is available.
+ * This is used to initialize kernel driver and user interfaces.
+ */
+extern struct pks_config *pks_get_config(void);
+
+/**
+ * Returns all the var names for this prefix.
+ * This only returns name list. If the caller needs data, it has to 
specifically
+ * call read for the required var name.
+ */
+int pks_get_var_ids_for_type(char *prefix, struct pks_var_name_list *list);
+
+/**
+ * Writes the specified var and its data to PKS.
+ * Any caller of PKS driver should present a valid prefix type for their
+ * variable. This is an exception only for signed variables exposed via
+ * sysfs which do not have any prefixes.
+ * The prefix should always start with '/'. For eg. '/sysfs'.
+ */
+extern int pks_write_var(struct pks_var var);
+
+/**
+ * Writes the specified signed var and its data to PKS.
+ */
+extern int pks_update_signed_var(struct pks_var var);
+
+/**
+ * Removes the specified var and its data from PKS.
+ */
+extern int pks_remove_var(char *prefix, struct pks_var_name vname);
+
+/**
+ * Returns the data for the specified variable.
+ */
+extern int pks_read_var(struct pks_var *var);
+
+#endif
diff --git a/arch/powerpc/platforms/pseries/Kconfig 
b/arch/powerpc/platforms/pseries/Kconfig
index 2e57391e0778..32d0df84e611 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -147,6 +147,16 @@ config IBMEBUS
help
  Bus device driver for GX bus based adapters.
 
+config PSERIES_PKS
+   depends on PPC_PSERIES
+   tristate "Support for the Platform Key Storage"
+   help
+ PowerVM provides an isolated Platform Keystore(PKS) storage
+ allocation for each partition with individually managed
+ access controls to store sensitive information securely. Select
+ this config to enable operating system interface to hypervisor to
+ access this space.
+
 confi

[RFC PATCH 0/2] powerpc/pseries: add support for local secure storage called Platform Keystore(PKS)

2022-01-21 Thread Nayna Jain
PowerVM provides an isolated Platform Keystore(PKS) storage allocation
for each partition with individually managed access controls to store
sensitive information securely. Linux Kernel can access this storage by
interfacing with hypervisor using a new set of hypervisor calls. 

PowerVM guest secure boot intend to use Platform Keystore for the
purpose of storing public keys. Secure boot requires public keys to
be able to verify the grub and boot kernel. To allow authenticated
 manipulation of keys, it supports variables to store key authorities
- PK/KEK and code signing keys - db. It also supports denied list to
disallow booting even if signed with valid key. This is done via
denied list database - dbx or sbat. These variables would be stored in
PKS, and are managed and controlled by firmware.

The purpose of this patchset is to add support for users to
read/write/add/delete variables required for secure boot on PowerVM.

Nayna Jain (2):
  pseries: define driver for Platform Keystore
  pseries: define sysfs interface to expose PKS variables

 Documentation/ABI/testing/sysfs-pksvar|  77 +++
 arch/powerpc/include/asm/hvcall.h |  13 +-
 arch/powerpc/include/asm/pks.h|  84 +++
 arch/powerpc/platforms/pseries/Kconfig|  17 +
 arch/powerpc/platforms/pseries/Makefile   |   2 +
 arch/powerpc/platforms/pseries/pks.c  | 494 ++
 arch/powerpc/platforms/pseries/pksvar-sysfs.c | 356 +
 7 files changed, 1042 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ABI/testing/sysfs-pksvar
 create mode 100644 arch/powerpc/include/asm/pks.h
 create mode 100644 arch/powerpc/platforms/pseries/pks.c
 create mode 100644 arch/powerpc/platforms/pseries/pksvar-sysfs.c

-- 
2.27.0


[PATCH v3] powerpc/pseries: detect secure and trusted boot state of the system.

2020-07-15 Thread Nayna Jain
The device-tree property to check secure and trusted boot state is
different for guests(pseries) compared to baremetal(powernv).

This patch updates the existing is_ppc_secureboot_enabled() and
is_ppc_trustedboot_enabled() functions to add support for pseries.

The secureboot and trustedboot state are exposed via device-tree property:
/proc/device-tree/ibm,secure-boot and /proc/device-tree/ibm,trusted-boot

The values of ibm,secure-boot under pseries are interpreted as:

0 - Disabled
1 - Enabled in Log-only mode. This patch interprets this value as
disabled, since audit mode is currently not supported for Linux.
2 - Enabled and enforced.
3-9 - Enabled and enforcing; requirements are at the discretion of the
operating system.

The values of ibm,trusted-boot under pseries are interpreted as:
0 - Disabled
1 - Enabled

Signed-off-by: Nayna Jain 
Reviewed-by: Daniel Axtens 
---
v3:
* fixed double check. Thanks Daniel for noticing it.
* updated patch description.

v2:
* included Michael Ellerman's feedback.
* added Daniel Axtens's Reviewed-by.

 arch/powerpc/kernel/secure_boot.c | 19 +--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/secure_boot.c 
b/arch/powerpc/kernel/secure_boot.c
index 4b982324d368..118bcb5f79c4 100644
--- a/arch/powerpc/kernel/secure_boot.c
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct device_node *get_ppc_fw_sb_node(void)
 {
@@ -23,12 +24,19 @@ bool is_ppc_secureboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   u32 secureboot;
 
node = get_ppc_fw_sb_node();
enabled = of_property_read_bool(node, "os-secureboot-enforcing");
-
of_node_put(node);
 
+   if (enabled)
+   goto out;
+
+   if (!of_property_read_u32(of_root, "ibm,secure-boot", ))
+   enabled = (secureboot > 1);
+
+out:
pr_info("Secure boot mode %s\n", enabled ? "enabled" : "disabled");
 
return enabled;
@@ -38,12 +46,19 @@ bool is_ppc_trustedboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   u32 trustedboot;
 
node = get_ppc_fw_sb_node();
enabled = of_property_read_bool(node, "trusted-enabled");
-
of_node_put(node);
 
+   if (enabled)
+   goto out;
+
+   if (!of_property_read_u32(of_root, "ibm,trusted-boot", ))
+   enabled = (trustedboot > 0);
+
+out:
pr_info("Trusted boot mode %s\n", enabled ? "enabled" : "disabled");
 
return enabled;
-- 
2.26.2



[PATCH v2] powerpc/pseries: detect secure and trusted boot state of the system.

2020-07-10 Thread Nayna Jain
The device-tree property to check secure and trusted boot state is
different for guests(pseries) compared to baremetal(powernv).

This patch updates the existing is_ppc_secureboot_enabled() and
is_ppc_trustedboot_enabled() function to add support for pseries.

Signed-off-by: Nayna Jain 
Reviewed-by: Daniel Axtens 
---
v2:
* included Michael Ellerman's feedback.
* added Daniel Axtens's Reviewed-by.

 arch/powerpc/kernel/secure_boot.c | 23 +--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/secure_boot.c 
b/arch/powerpc/kernel/secure_boot.c
index 4b982324d368..efb325cbd42f 100644
--- a/arch/powerpc/kernel/secure_boot.c
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct device_node *get_ppc_fw_sb_node(void)
 {
@@ -23,12 +24,21 @@ bool is_ppc_secureboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   u32 secureboot;
 
node = get_ppc_fw_sb_node();
enabled = of_property_read_bool(node, "os-secureboot-enforcing");
-
of_node_put(node);
 
+   if (enabled)
+   goto out;
+
+   if (!of_property_read_u32(of_root, "ibm,secure-boot", )) {
+   if (secureboot)
+   enabled = (secureboot > 1) ? true : false;
+   }
+
+out:
pr_info("Secure boot mode %s\n", enabled ? "enabled" : "disabled");
 
return enabled;
@@ -38,12 +48,21 @@ bool is_ppc_trustedboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   u32 trustedboot;
 
node = get_ppc_fw_sb_node();
enabled = of_property_read_bool(node, "trusted-enabled");
-
of_node_put(node);
 
+   if (enabled)
+   goto out;
+
+   if (!of_property_read_u32(of_root, "ibm,trusted-boot", )) {
+   if (trustedboot)
+   enabled = (trustedboot > 0) ? true : false;
+   }
+
+out:
pr_info("Trusted boot mode %s\n", enabled ? "enabled" : "disabled");
 
return enabled;
-- 
2.26.2



[PATCH] powerpc/pseries: detect secure and trusted boot state of the system.

2020-07-04 Thread Nayna Jain
The device-tree property to check secure and trusted boot state is
different for guests(pseries) compared to baremetal(powernv).

This patch updates the existing is_ppc_secureboot_enabled() and
is_ppc_trustedboot_enabled() function to add support for pseries.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/kernel/secure_boot.c | 31 +--
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/secure_boot.c 
b/arch/powerpc/kernel/secure_boot.c
index 4b982324d368..43fc6607c7a5 100644
--- a/arch/powerpc/kernel/secure_boot.c
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct device_node *get_ppc_fw_sb_node(void)
 {
@@ -23,11 +24,20 @@ bool is_ppc_secureboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   const u32 *secureboot;
 
-   node = get_ppc_fw_sb_node();
-   enabled = of_property_read_bool(node, "os-secureboot-enforcing");
+   if (machine_is(powernv)) {
+   node = get_ppc_fw_sb_node();
+   enabled =
+   of_property_read_bool(node, "os-secureboot-enforcing");
+   of_node_put(node);
+   }
 
-   of_node_put(node);
+   if (machine_is(pseries)) {
+   secureboot = of_get_property(of_root, "ibm,secure-boot", NULL);
+   if (secureboot)
+   enabled = (*secureboot > 1) ? true : false;
+   }
 
pr_info("Secure boot mode %s\n", enabled ? "enabled" : "disabled");
 
@@ -38,11 +48,20 @@ bool is_ppc_trustedboot_enabled(void)
 {
struct device_node *node;
bool enabled = false;
+   const u32 *trustedboot;
 
-   node = get_ppc_fw_sb_node();
-   enabled = of_property_read_bool(node, "trusted-enabled");
+   if (machine_is(powernv)) {
+   node = get_ppc_fw_sb_node();
+   enabled = of_property_read_bool(node, "trusted-enabled");
+   of_node_put(node);
+   }
 
-   of_node_put(node);
+   if (machine_is(pseries)) {
+   trustedboot =
+   of_get_property(of_root, "ibm,trusted-boot", NULL);
+   if (trustedboot)
+   enabled = (*trustedboot > 0) ? true : false;
+   }
 
pr_info("Trusted boot mode %s\n", enabled ? "enabled" : "disabled");
 
-- 
2.18.1



[PATCH v2] powerpc/ima: fix secure boot rules in ima arch policy

2020-05-01 Thread Nayna Jain
To prevent verifying the kernel module appended signature twice
(finit_module), once by the module_sig_check() and again by IMA, powerpc
secure boot rules define an IMA architecture specific policy rule
only if CONFIG_MODULE_SIG_FORCE is not enabled. This, unfortunately, does
not take into account the ability of enabling "sig_enforce" on the boot
command line (module.sig_enforce=1).

Including the IMA module appraise rule results in failing the finit_module
syscall, unless the module signing public key is loaded onto the IMA
keyring.

This patch fixes secure boot policy rules to be based on CONFIG_MODULE_SIG
instead.

Fixes: 4238fad366a6 ("powerpc/ima: Add support to initialize ima policy rules")
Signed-off-by: Nayna Jain 
---
v2:
* Fixes the patch description to specify the problem more clearly as asked 
by Michael Ellerman.

 arch/powerpc/kernel/ima_arch.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index e34116255ced..957abd592075 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -19,12 +19,12 @@ bool arch_ima_get_secureboot(void)
  * to be stored as an xattr or as an appended signature.
  *
  * To avoid duplicate signature verification as much as possible, the IMA
- * policy rule for module appraisal is added only if CONFIG_MODULE_SIG_FORCE
+ * policy rule for module appraisal is added only if CONFIG_MODULE_SIG
  * is not enabled.
  */
 static const char *const secure_rules[] = {
"appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
-#ifndef CONFIG_MODULE_SIG_FORCE
+#ifndef CONFIG_MODULE_SIG
"appraise func=MODULE_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #endif
NULL
@@ -50,7 +50,7 @@ static const char *const secure_and_trusted_rules[] = {
"measure func=KEXEC_KERNEL_CHECK template=ima-modsig",
"measure func=MODULE_CHECK template=ima-modsig",
"appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
-#ifndef CONFIG_MODULE_SIG_FORCE
+#ifndef CONFIG_MODULE_SIG
"appraise func=MODULE_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #endif
NULL
-- 
2.18.1



[PATCH] powerpc/ima: fix secure boot rules in ima arch policy

2020-04-10 Thread Nayna Jain
To prevent verifying the kernel module appended signature twice
(finit_module), once by the module_sig_check() and again by IMA, powerpc
IMA secure boot rules define an IMA architecture specific policy rule
only if CONFIG_MODULE_SIG_FORCE is not enabled. This, unfortunately, does
not take into account the ability of enabling "sig_enforce" on the boot
command line (module.sig_enforce=1).

This patch fixes secure boot policy rules to be based on CONFIG_MODULE_SIG
instead.

Fixes: 4238fad366a6 ("powerpc/ima: Add support to initialize ima policy rules")
Signed-off-by: Nayna Jain 
---
 arch/powerpc/kernel/ima_arch.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index e34116255ced..957abd592075 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -19,12 +19,12 @@ bool arch_ima_get_secureboot(void)
  * to be stored as an xattr or as an appended signature.
  *
  * To avoid duplicate signature verification as much as possible, the IMA
- * policy rule for module appraisal is added only if CONFIG_MODULE_SIG_FORCE
+ * policy rule for module appraisal is added only if CONFIG_MODULE_SIG
  * is not enabled.
  */
 static const char *const secure_rules[] = {
"appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
-#ifndef CONFIG_MODULE_SIG_FORCE
+#ifndef CONFIG_MODULE_SIG
"appraise func=MODULE_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #endif
NULL
@@ -50,7 +50,7 @@ static const char *const secure_and_trusted_rules[] = {
"measure func=KEXEC_KERNEL_CHECK template=ima-modsig",
"measure func=MODULE_CHECK template=ima-modsig",
"appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
-#ifndef CONFIG_MODULE_SIG_FORCE
+#ifndef CONFIG_MODULE_SIG
"appraise func=MODULE_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #endif
NULL
-- 
2.25.1



[PATCH v3] ima: add a new CONFIG for loading arch-specific policies

2020-03-08 Thread Nayna Jain
From: Nayna Jain 

Every time a new architecture defines the IMA architecture specific
functions - arch_ima_get_secureboot() and arch_ima_get_policy(), the IMA
include file needs to be updated. To avoid this "noise", this patch
defines a new IMA Kconfig IMA_SECURE_AND_OR_TRUSTED_BOOT option, allowing
the different architectures to select it.

Suggested-by: Linus Torvalds 
Signed-off-by: Nayna Jain 
Acked-by: Ard Biesheuvel 
Cc: Ard Biesheuvel 
Cc: Philipp Rudo 
Cc: Michael Ellerman 
---
v3:
* Removes CONFIG_IMA dependency. Thanks Ard.
* Updated the patch with improvements suggested by Michael. It now uses
"imply" instead of "select". Thanks Michael.
* Replaced the CONFIG_IMA in x86 and s390 with new config, else it was
resulting in redefinition when the IMA_SECURE_AND_OR_TRUSTED_BOOT
is not enabled. Thanks to Mimi for identifying the problem.
* Removed "#ifdef EFI" check in the arch/x86/Makefile for compiling
ima_arch.c file.
* Ard, Thanks for your Acked-by. I have changed the arch/x86/Makefile in
this version. Can you please review again and confirm ?
* Rudo, Thanks for your review. I have changed arch/s390/Makefile as well.
Can you also please review again ?

v2:
* Fixed the issue identified by Mimi. Thanks Mimi, Ard, Heiko and Michael for
discussing the fix.

 arch/powerpc/Kconfig   | 1 +
 arch/s390/Kconfig  | 1 +
 arch/s390/kernel/Makefile  | 2 +-
 arch/x86/Kconfig   | 1 +
 arch/x86/kernel/Makefile   | 4 +---
 include/linux/ima.h| 3 +--
 security/integrity/ima/Kconfig | 7 +++
 7 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 497b7d0b2d7e..5b9f1cba2a44 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -979,6 +979,7 @@ config PPC_SECURE_BOOT
bool
depends on PPC_POWERNV
depends on IMA_ARCH_POLICY
+   imply IMA_SECURE_AND_OR_TRUSTED_BOOT
help
  Systems with firmware secure boot enabled need to define security
  policies to extend secure boot to the OS. This config allows a user
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 8abe77536d9d..59c216af6264 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -195,6 +195,7 @@ config S390
select ARCH_HAS_FORCE_DMA_UNENCRYPTED
select SWIOTLB
select GENERIC_ALLOCATOR
+   imply IMA_SECURE_AND_OR_TRUSTED_BOOT
 
 
 config SCHED_OMIT_FRAME_POINTER
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 2b1203cf7be6..578a6fa82ea4 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -70,7 +70,7 @@ obj-$(CONFIG_JUMP_LABEL)  += jump_label.o
 obj-$(CONFIG_KEXEC_FILE)   += machine_kexec_file.o kexec_image.o
 obj-$(CONFIG_KEXEC_FILE)   += kexec_elf.o
 
-obj-$(CONFIG_IMA)  += ima_arch.o
+obj-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT)   += ima_arch.o
 
 obj-$(CONFIG_PERF_EVENTS)  += perf_event.o perf_cpum_cf_common.o
 obj-$(CONFIG_PERF_EVENTS)  += perf_cpum_cf.o perf_cpum_sf.o
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index beea77046f9b..dcf5b1729f7c 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -230,6 +230,7 @@ config X86
select VIRT_TO_BUS
select X86_FEATURE_NAMESif PROC_FS
select PROC_PID_ARCH_STATUS if PROC_FS
+   imply IMA_SECURE_AND_OR_TRUSTED_BOOTif EFI
 
 config INSTRUCTION_DECODER
def_bool y
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 9b294c13809a..cfef37a27def 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -154,6 +154,4 @@ ifeq ($(CONFIG_X86_64),y)
obj-y   += vsmp_64.o
 endif
 
-ifdef CONFIG_EFI
-obj-$(CONFIG_IMA)  += ima_arch.o
-endif
+obj-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT)   += ima_arch.o
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 1659217e9b60..aefe758f4466 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -30,8 +30,7 @@ extern void ima_kexec_cmdline(const void *buf, int size);
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
 
-#if (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390) \
-   || defined(CONFIG_PPC_SECURE_BOOT)
+#ifdef CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
 extern bool arch_ima_get_secureboot(void);
 extern const char * const *arch_get_ima_policy(void);
 #else
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 3f3ee4e2eb0d..edde88dbe576 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -327,3 +327,10 @@ config IMA_QUEUE_EARLY_BOOT_KEYS
depends on IMA_MEASURE_ASYMMETRIC_KEYS
depends on SYSTEM_TRUSTED_KEYRING
default y
+
+config IMA_SECURE_AND_OR_TRUSTED_BOOT
+   bool
+   depends on IMA_ARCH_POLICY
+   help
+  This option is selected by architectures

[PATCH v3] ima: add a new CONFIG for loading arch-specific policies

2020-03-06 Thread Nayna Jain
Every time a new architecture defines the IMA architecture specific
functions - arch_ima_get_secureboot() and arch_ima_get_policy(), the IMA
include file needs to be updated. To avoid this "noise", this patch
defines a new IMA Kconfig IMA_SECURE_AND_OR_TRUSTED_BOOT option, allowing
the different architectures to select it.

Suggested-by: Linus Torvalds 
Signed-off-by: Nayna Jain 
Cc: Ard Biesheuvel 
Cc: Philipp Rudo 
Cc: Michael Ellerman 
---
v3:
* Updated and tested the patch with improvements suggested by Michael.
It now uses "imply" instead of "select". Thanks Michael.
* Have missed replacing the CONFIG_IMA in x86 and s390 with new config,
that was resulting in redefinition when the IMA_SECURE_AND_OR_TRUSTED_BOOT
is not enabled. Thanks to Mimi for recognizing the problem.

v2:
* Fixed the issue identified by Mimi. Thanks Mimi, Ard, Heiko and Michael for
discussing the fix.

 arch/powerpc/Kconfig   | 1 +
 arch/s390/Kconfig  | 1 +
 arch/s390/kernel/Makefile  | 2 +-
 arch/x86/Kconfig   | 1 +
 arch/x86/kernel/Makefile   | 2 +-
 include/linux/ima.h| 3 +--
 security/integrity/ima/Kconfig | 8 
 7 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 497b7d0b2d7e..a5cfde432983 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -979,6 +979,7 @@ config PPC_SECURE_BOOT
bool
depends on PPC_POWERNV
depends on IMA_ARCH_POLICY
+   select IMA_SECURE_AND_OR_TRUSTED_BOOT
help
  Systems with firmware secure boot enabled need to define security
  policies to extend secure boot to the OS. This config allows a user
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 8abe77536d9d..4a502fbcb800 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -195,6 +195,7 @@ config S390
select ARCH_HAS_FORCE_DMA_UNENCRYPTED
select SWIOTLB
select GENERIC_ALLOCATOR
+   select IMA_SECURE_AND_OR_TRUSTED_BOOT if IMA_ARCH_POLICY
 
 
 config SCHED_OMIT_FRAME_POINTER
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 2b1203cf7be6..578a6fa82ea4 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -70,7 +70,7 @@ obj-$(CONFIG_JUMP_LABEL)  += jump_label.o
 obj-$(CONFIG_KEXEC_FILE)   += machine_kexec_file.o kexec_image.o
 obj-$(CONFIG_KEXEC_FILE)   += kexec_elf.o
 
-obj-$(CONFIG_IMA)  += ima_arch.o
+obj-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT)   += ima_arch.o
 
 obj-$(CONFIG_PERF_EVENTS)  += perf_event.o perf_cpum_cf_common.o
 obj-$(CONFIG_PERF_EVENTS)  += perf_cpum_cf.o perf_cpum_sf.o
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index beea77046f9b..7f5bfaf0cbd2 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -230,6 +230,7 @@ config X86
select VIRT_TO_BUS
select X86_FEATURE_NAMESif PROC_FS
select PROC_PID_ARCH_STATUS if PROC_FS
+   select IMA_SECURE_AND_OR_TRUSTED_BOOT   if EFI && IMA_ARCH_POLICY
 
 config INSTRUCTION_DECODER
def_bool y
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 9b294c13809a..7f131ceba136 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -155,5 +155,5 @@ ifeq ($(CONFIG_X86_64),y)
 endif
 
 ifdef CONFIG_EFI
-obj-$(CONFIG_IMA)  += ima_arch.o
+obj-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT)   += ima_arch.o
 endif
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 1659217e9b60..aefe758f4466 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -30,8 +30,7 @@ extern void ima_kexec_cmdline(const void *buf, int size);
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
 
-#if (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390) \
-   || defined(CONFIG_PPC_SECURE_BOOT)
+#ifdef CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
 extern bool arch_ima_get_secureboot(void);
 extern const char * const *arch_get_ima_policy(void);
 #else
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 3f3ee4e2eb0d..2baaf196c6d8 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -327,3 +327,11 @@ config IMA_QUEUE_EARLY_BOOT_KEYS
depends on IMA_MEASURE_ASYMMETRIC_KEYS
depends on SYSTEM_TRUSTED_KEYRING
default y
+
+config IMA_SECURE_AND_OR_TRUSTED_BOOT
+   bool
+   depends on IMA_ARCH_POLICY
+   default n
+   help
+  This option is selected by architectures to enable secure and/or
+  trusted boot based on IMA runtime policies.
-- 
2.18.1



[PATCH v2] ima: add a new CONFIG for loading arch-specific policies

2020-03-03 Thread Nayna Jain
Every time a new architecture defines the IMA architecture specific
functions - arch_ima_get_secureboot() and arch_ima_get_policy(), the IMA
include file needs to be updated. To avoid this "noise", this patch
defines a new IMA Kconfig IMA_SECURE_AND_OR_TRUSTED_BOOT option, allowing
the different architectures to select it.

Suggested-by: Linus Torvalds 
Signed-off-by: Nayna Jain 
Cc: Ard Biesheuvel 
Cc: Philipp Rudo 
Cc: Michael Ellerman 
---
v2:
* Fixed the issue identified by Mimi. Thanks Mimi, Ard, Heiko and Michael for
discussing the fix.

 arch/powerpc/Kconfig   | 1 +
 arch/s390/Kconfig  | 1 +
 arch/x86/Kconfig   | 1 +
 include/linux/ima.h| 3 +--
 security/integrity/ima/Kconfig | 9 +
 5 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 497b7d0b2d7e..a5cfde432983 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -979,6 +979,7 @@ config PPC_SECURE_BOOT
bool
depends on PPC_POWERNV
depends on IMA_ARCH_POLICY
+   select IMA_SECURE_AND_OR_TRUSTED_BOOT
help
  Systems with firmware secure boot enabled need to define security
  policies to extend secure boot to the OS. This config allows a user
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 8abe77536d9d..4a502fbcb800 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -195,6 +195,7 @@ config S390
select ARCH_HAS_FORCE_DMA_UNENCRYPTED
select SWIOTLB
select GENERIC_ALLOCATOR
+   select IMA_SECURE_AND_OR_TRUSTED_BOOT if IMA_ARCH_POLICY
 
 
 config SCHED_OMIT_FRAME_POINTER
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index beea77046f9b..7f5bfaf0cbd2 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -230,6 +230,7 @@ config X86
select VIRT_TO_BUS
select X86_FEATURE_NAMESif PROC_FS
select PROC_PID_ARCH_STATUS if PROC_FS
+   select IMA_SECURE_AND_OR_TRUSTED_BOOT   if EFI && IMA_ARCH_POLICY
 
 config INSTRUCTION_DECODER
def_bool y
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 1659217e9b60..aefe758f4466 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -30,8 +30,7 @@ extern void ima_kexec_cmdline(const void *buf, int size);
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
 
-#if (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390) \
-   || defined(CONFIG_PPC_SECURE_BOOT)
+#ifdef CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
 extern bool arch_ima_get_secureboot(void);
 extern const char * const *arch_get_ima_policy(void);
 #else
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 3f3ee4e2eb0d..d17972aa413a 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -327,3 +327,12 @@ config IMA_QUEUE_EARLY_BOOT_KEYS
depends on IMA_MEASURE_ASYMMETRIC_KEYS
depends on SYSTEM_TRUSTED_KEYRING
default y
+
+config IMA_SECURE_AND_OR_TRUSTED_BOOT
+   bool
+   depends on IMA
+   depends on IMA_ARCH_POLICY
+   default n
+   help
+  This option is selected by architectures to enable secure and/or
+  trusted boot based on IMA runtime policies.
-- 
2.13.6



[PATCH] ima: add a new CONFIG for loading arch-specific policies

2020-02-26 Thread Nayna Jain
Every time a new architecture defines the IMA architecture specific
functions - arch_ima_get_secureboot() and arch_ima_get_policy(), the IMA
include file needs to be updated. To avoid this "noise", this patch
defines a new IMA Kconfig IMA_SECURE_AND_OR_TRUSTED_BOOT option, allowing
the different architectures to select it.

Suggested-by: Linus Torvalds 
Signed-off-by: Nayna Jain 
Cc: Ard Biesheuvel 
Cc: Martin Schwidefsky 
Cc: Philipp Rudo 
Cc: Michael Ellerman 
---
 arch/powerpc/Kconfig   | 2 +-
 arch/s390/Kconfig  | 1 +
 arch/x86/Kconfig   | 1 +
 include/linux/ima.h| 3 +--
 security/integrity/ima/Kconfig | 9 +
 5 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 497b7d0b2d7e..b8ce1b995633 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -246,6 +246,7 @@ config PPC
select SYSCTL_EXCEPTION_TRACE
select THREAD_INFO_IN_TASK
select VIRT_TO_BUS  if !PPC64
+   select IMA_SECURE_AND_OR_TRUSTED_BOOT   if PPC_SECURE_BOOT
#
# Please keep this list sorted alphabetically.
#
@@ -978,7 +979,6 @@ config PPC_SECURE_BOOT
prompt "Enable secure boot support"
bool
depends on PPC_POWERNV
-   depends on IMA_ARCH_POLICY
help
  Systems with firmware secure boot enabled need to define security
  policies to extend secure boot to the OS. This config allows a user
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 8abe77536d9d..90ff3633ade6 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -195,6 +195,7 @@ config S390
select ARCH_HAS_FORCE_DMA_UNENCRYPTED
select SWIOTLB
select GENERIC_ALLOCATOR
+   select IMA_SECURE_AND_OR_TRUSTED_BOOT
 
 
 config SCHED_OMIT_FRAME_POINTER
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index beea77046f9b..cafa66313fe2 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -230,6 +230,7 @@ config X86
select VIRT_TO_BUS
select X86_FEATURE_NAMESif PROC_FS
select PROC_PID_ARCH_STATUS if PROC_FS
+   select IMA_SECURE_AND_OR_TRUSTED_BOOT   if EFI
 
 config INSTRUCTION_DECODER
def_bool y
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 1659217e9b60..aefe758f4466 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -30,8 +30,7 @@ extern void ima_kexec_cmdline(const void *buf, int size);
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
 
-#if (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390) \
-   || defined(CONFIG_PPC_SECURE_BOOT)
+#ifdef CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
 extern bool arch_ima_get_secureboot(void);
 extern const char * const *arch_get_ima_policy(void);
 #else
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 3f3ee4e2eb0d..d17972aa413a 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -327,3 +327,12 @@ config IMA_QUEUE_EARLY_BOOT_KEYS
depends on IMA_MEASURE_ASYMMETRIC_KEYS
depends on SYSTEM_TRUSTED_KEYRING
default y
+
+config IMA_SECURE_AND_OR_TRUSTED_BOOT
+   bool
+   depends on IMA
+   depends on IMA_ARCH_POLICY
+   default n
+   help
+  This option is selected by architectures to enable secure and/or
+  trusted boot based on IMA runtime policies.
-- 
2.18.1



[PATCH v9 4/4] powerpc: load firmware trusted keys/hashes into kernel keyring

2019-11-10 Thread Nayna Jain
The keys used to verify the Host OS kernel are managed by firmware as
secure variables. This patch loads the verification keys into the .platform
keyring and revocation hashes into .blacklist keyring. This enables
verification and loading of the kernels signed by the boot time keys which
are trusted by firmware.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Signed-off-by: Eric Richter 
---
 security/integrity/Kconfig   |  9 +++
 security/integrity/Makefile  |  4 +-
 security/integrity/platform_certs/load_powerpc.c | 99 
 3 files changed, 111 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/platform_certs/load_powerpc.c

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 0bae6adb63a9..71f0177e8716 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -72,6 +72,15 @@ config LOAD_IPL_KEYS
depends on S390
def_bool y
 
+config LOAD_PPC_KEYS
+   bool "Enable loading of platform and blacklisted keys for POWER"
+   depends on INTEGRITY_PLATFORM_KEYRING
+   depends on PPC_SECURE_BOOT
+   default y
+   help
+ Enable loading of keys to the .platform keyring and blacklisted
+ hashes to the .blacklist keyring for powerpc based platforms.
+
 config INTEGRITY_AUDIT
bool "Enables integrity auditing support "
depends on AUDIT
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 351c9662994b..7ee39d66cf16 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -14,6 +14,8 @@ integrity-$(CONFIG_LOAD_UEFI_KEYS) += 
platform_certs/efi_parser.o \
  platform_certs/load_uefi.o \
  platform_certs/keyring_handler.o
 integrity-$(CONFIG_LOAD_IPL_KEYS) += platform_certs/load_ipl_s390.o
-
+integrity-$(CONFIG_LOAD_PPC_KEYS) += platform_certs/efi_parser.o \
+ platform_certs/load_powerpc.o \
+ platform_certs/keyring_handler.o
 obj-$(CONFIG_IMA)  += ima/
 obj-$(CONFIG_EVM)  += evm/
diff --git a/security/integrity/platform_certs/load_powerpc.c 
b/security/integrity/platform_certs/load_powerpc.c
new file mode 100644
index ..9b2596e838ac
--- /dev/null
+++ b/security/integrity/platform_certs/load_powerpc.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ *
+ *  - loads keys and hashes stored and controlled by the firmware.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "keyring_handler.h"
+
+/*
+ * Get a certificate list blob from the named secure variable.
+ */
+static __init void *get_cert_list(u8 *key, unsigned long keylen, uint64_t 
*size)
+{
+   int rc;
+   void *db;
+
+   rc = secvar_ops->get(key, keylen, NULL, size);
+   if (rc) {
+   pr_err("Couldn't get size: %d\n", rc);
+   return NULL;
+   }
+
+   db = kmalloc(*size, GFP_KERNEL);
+   if (!db)
+   return NULL;
+
+   rc = secvar_ops->get(key, keylen, db, size);
+   if (rc) {
+   kfree(db);
+   pr_err("Error reading %s var: %d\n", key, rc);
+   return NULL;
+   }
+
+   return db;
+}
+
+/*
+ * Load the certs contained in the keys databases into the platform trusted
+ * keyring and the blacklisted X.509 cert SHA256 hashes into the blacklist
+ * keyring.
+ */
+static int __init load_powerpc_certs(void)
+{
+   void *db = NULL, *dbx = NULL;
+   uint64_t dbsize = 0, dbxsize = 0;
+   int rc = 0;
+   struct device_node *node;
+
+   if (!secvar_ops)
+   return -ENODEV;
+
+   /* The following only applies for the edk2-compat backend.
+* Return early if it is not set.
+*/
+
+   node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");
+   rc = of_property_match_string(node, "format", "ibm,edk2-compat-v1");
+   if (rc)
+   return -ENODEV;
+
+   /* Get db, and dbx.  They might not exist, so it isn't
+* an error if we can't get them.
+*/
+   db = get_cert_list("db", 3, );
+   if (!db) {
+   pr_err("Couldn't get db list from firmware\n");
+   } else {
+   rc = parse_efi_signature_list("powerpc:db", db, dbsize,
+ get_handler_for_db);
+   if (rc)
+   pr_err("Couldn't parse db signatures: %d\n", rc);
+   kfree(db);
+   }
+
+   dbx = get_cert_list("dbx", 4,  );
+   if (!dbx) {
+   pr_i

[PATCH v9 3/4] x86/efi: move common keyring handler functions to new file

2019-11-10 Thread Nayna Jain
The handlers to add the keys to the .platform keyring and blacklisted
hashes to the .blacklist keyring is common for both the uefi and powerpc
mechanisms of loading the keys/hashes from the firmware.

This patch moves the common code from load_uefi.c to keyring_handler.c

Signed-off-by: Nayna Jain 
Acked-by: Mimi Zohar 
Signed-off-by: Eric Richter 
---
 security/integrity/Makefile|  3 +-
 .../integrity/platform_certs/keyring_handler.c | 80 ++
 .../integrity/platform_certs/keyring_handler.h | 32 +
 security/integrity/platform_certs/load_uefi.c  | 67 +-
 4 files changed, 115 insertions(+), 67 deletions(-)
 create mode 100644 security/integrity/platform_certs/keyring_handler.c
 create mode 100644 security/integrity/platform_certs/keyring_handler.h

diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 35e6ca773734..351c9662994b 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -11,7 +11,8 @@ integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
 integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o
 integrity-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/efi_parser.o \
-   platform_certs/load_uefi.o
+ platform_certs/load_uefi.o \
+ platform_certs/keyring_handler.o
 integrity-$(CONFIG_LOAD_IPL_KEYS) += platform_certs/load_ipl_s390.o
 
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/platform_certs/keyring_handler.c 
b/security/integrity/platform_certs/keyring_handler.c
new file mode 100644
index ..c5ba695c10e3
--- /dev/null
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../integrity.h"
+
+static efi_guid_t efi_cert_x509_guid __initdata = EFI_CERT_X509_GUID;
+static efi_guid_t efi_cert_x509_sha256_guid __initdata =
+   EFI_CERT_X509_SHA256_GUID;
+static efi_guid_t efi_cert_sha256_guid __initdata = EFI_CERT_SHA256_GUID;
+
+/*
+ * Blacklist a hash.
+ */
+static __init void uefi_blacklist_hash(const char *source, const void *data,
+  size_t len, const char *type,
+  size_t type_len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(type_len + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, type, type_len);
+   p += type_len;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfree(hash);
+}
+
+/*
+ * Blacklist an X509 TBS hash.
+ */
+static __init void uefi_blacklist_x509_tbs(const char *source,
+  const void *data, size_t len)
+{
+   uefi_blacklist_hash(source, data, len, "tbs:", 4);
+}
+
+/*
+ * Blacklist the hash of an executable.
+ */
+static __init void uefi_blacklist_binary(const char *source,
+const void *data, size_t len)
+{
+   uefi_blacklist_hash(source, data, len, "bin:", 4);
+}
+
+/*
+ * Return the appropriate handler for particular signature list types found in
+ * the UEFI db and MokListRT tables.
+ */
+__init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
+   return add_to_platform_keyring;
+   return 0;
+}
+
+/*
+ * Return the appropriate handler for particular signature list types found in
+ * the UEFI dbx and MokListXRT tables.
+ */
+__init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_sha256_guid) == 0)
+   return uefi_blacklist_x509_tbs;
+   if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0)
+   return uefi_blacklist_binary;
+   return 0;
+}
diff --git a/security/integrity/platform_certs/keyring_handler.h 
b/security/integrity/platform_certs/keyring_handler.h
new file mode 100644
index ..2462bfa08fe3
--- /dev/null
+++ b/security/integrity/platform_certs/keyring_handler.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef PLATFORM_CERTS_INTERNAL_H
+#define PLATFORM_CERTS_INTERNAL_H
+
+#include 
+
+void blacklist_hash(const char *source, const void *data,
+   size_t len, const char *type,
+   size_t type_len);
+
+/*
+ * Blacklist an X509 TBS hash.
+ */
+void blacklist_x509_tbs(const char *source, const void *data, size_t len);
+
+/*
+ * Blacklist the hash of an executable.
+ */
+void blacklist_binary(const char *source, const void *data, size_t len);
+
+/*
+ * Return the handler for p

[PATCH v9 2/4] powerpc: expose secure variables to userspace via sysfs

2019-11-10 Thread Nayna Jain
PowerNV secure variables, which store the keys used for OS kernel
verification, are managed by the firmware. These secure variables need to
be accessed by the userspace for addition/deletion of the certificates.

This patch adds the sysfs interface to expose secure variables for PowerNV
secureboot. The users shall use this interface for manipulating
the keys stored in the secure variables.

Signed-off-by: Nayna Jain 
Reviewed-by: Greg Kroah-Hartman 
Signed-off-by: Eric Richter 
---
 Documentation/ABI/testing/sysfs-secvar |  46 ++
 arch/powerpc/Kconfig   |  11 ++
 arch/powerpc/kernel/Makefile   |   1 +
 arch/powerpc/kernel/secvar-sysfs.c | 248 +
 4 files changed, 306 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-secvar
 create mode 100644 arch/powerpc/kernel/secvar-sysfs.c

diff --git a/Documentation/ABI/testing/sysfs-secvar 
b/Documentation/ABI/testing/sysfs-secvar
new file mode 100644
index ..feebb8c57294
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-secvar
@@ -0,0 +1,46 @@
+What:  /sys/firmware/secvar
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   This directory is created if the POWER firmware supports OS
+   secureboot, thereby secure variables. It exposes interface
+   for reading/writing the secure variables
+
+What:  /sys/firmware/secvar/vars
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   This directory lists all the secure variables that are supported
+   by the firmware.
+
+What:  /sys/firmware/secvar/format
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   A string indicating which backend is in use by the firmware.
+   This determines the format of the variable and the accepted
+   format of variable updates.
+
+What:  /sys/firmware/secvar/vars/
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   Each secure variable is represented as a directory named as
+   . The variable name is unique and is in ASCII
+   representation. The data and size can be determined by reading
+   their respective attribute files.
+
+What:  /sys/firmware/secvar/vars//size
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   An integer representation of the size of the content of the
+   variable. In other words, it represents the size of the data.
+
+What:  /sys/firmware/secvar/vars//data
+Date:  August 2019
+Contact:   Nayna Jain h
+Description:   A read-only file containing the value of the variable. The size
+   of the file represents the maximum size of the variable data.
+
+What:  /sys/firmware/secvar/vars//update
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   A write-only file that is used to submit the new value for the
+   variable. The size of the file represents the maximum size of
+   the variable data that can be written.
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c795039bdc73..cabc091f3fe1 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -945,6 +945,17 @@ config PPC_SECURE_BOOT
  to enable OS secure boot on systems that have firmware support for
  it. If in doubt say N.
 
+config PPC_SECVAR_SYSFS
+   bool "Enable sysfs interface for POWER secure variables"
+   default y
+   depends on PPC_SECURE_BOOT
+   depends on SYSFS
+   help
+ POWER secure variables are managed and controlled by firmware.
+ These variables are exposed to userspace via sysfs to enable
+ read/write operations on these variables. Say Y if you have
+ secure boot enabled and want to expose variables to userspace.
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 3cf26427334f..b216e9f316ee 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -162,6 +162,7 @@ obj-y   += ucall.o
 endif
 
 obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o ima_arch.o secvar-ops.o
+obj-$(CONFIG_PPC_SECVAR_SYSFS) += secvar-sysfs.o
 
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
diff --git a/arch/powerpc/kernel/secvar-sysfs.c 
b/arch/powerpc/kernel/secvar-sysfs.c
new file mode 100644
index ..a0a78aba2083
--- /dev/null
+++ b/arch/powerpc/kernel/secvar-sysfs.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 IBM Corporation 
+ *
+ * This code exposes secure variables to user via sysfs
+ */
+
+#define pr_fmt(fmt) "secvar-sysfs: "fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define NAME_MAX_SIZE 1024
+
+static struct kobject *secvar_kobj;
+static struct kset *secvar

[PATCH v9 1/4] powerpc/powernv: Add OPAL API interface to access secure variable

2019-11-10 Thread Nayna Jain
The X.509 certificates trusted by the platform and required to secure boot
the OS kernel are wrapped in secure variables, which are controlled by
OPAL.

This patch adds firmware/kernel interface to read and write OPAL secure
variables based on the unique key.

This support can be enabled using CONFIG_OPAL_SECVAR.

Signed-off-by: Claudio Carvalho 
Signed-off-by: Nayna Jain 
Signed-off-by: Eric Richter 
---
 arch/powerpc/include/asm/opal-api.h  |   5 +-
 arch/powerpc/include/asm/opal.h  |   7 ++
 arch/powerpc/include/asm/secvar.h|  35 +++
 arch/powerpc/kernel/Makefile |   2 +-
 arch/powerpc/kernel/secvar-ops.c |  16 +++
 arch/powerpc/platforms/powernv/Makefile  |   2 +-
 arch/powerpc/platforms/powernv/opal-call.c   |   3 +
 arch/powerpc/platforms/powernv/opal-secvar.c | 140 +++
 arch/powerpc/platforms/powernv/opal.c|   3 +
 9 files changed, 210 insertions(+), 3 deletions(-)
 create mode 100644 arch/powerpc/include/asm/secvar.h
 create mode 100644 arch/powerpc/kernel/secvar-ops.c
 create mode 100644 arch/powerpc/platforms/powernv/opal-secvar.c

diff --git a/arch/powerpc/include/asm/opal-api.h 
b/arch/powerpc/include/asm/opal-api.h
index 378e3997845a..c1f25a760eb1 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -211,7 +211,10 @@
 #define OPAL_MPIPL_UPDATE  173
 #define OPAL_MPIPL_REGISTER_TAG174
 #define OPAL_MPIPL_QUERY_TAG   175
-#define OPAL_LAST  175
+#define OPAL_SECVAR_GET176
+#define OPAL_SECVAR_GET_NEXT   177
+#define OPAL_SECVAR_ENQUEUE_UPDATE 178
+#define OPAL_LAST  178
 
 #define QUIESCE_HOLD   1 /* Spin all calls at entry */
 #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index a0cf8fba4d12..9986ac34b8e2 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -298,6 +298,13 @@ int opal_sensor_group_clear(u32 group_hndl, int token);
 int opal_sensor_group_enable(u32 group_hndl, int token, bool enable);
 int opal_nx_coproc_init(uint32_t chip_id, uint32_t ct);
 
+int opal_secvar_get(const char *key, uint64_t key_len, u8 *data,
+   uint64_t *data_size);
+int opal_secvar_get_next(const char *key, uint64_t *key_len,
+uint64_t key_buf_size);
+int opal_secvar_enqueue_update(const char *key, uint64_t key_len, u8 *data,
+  uint64_t data_size);
+
 s64 opal_mpipl_update(enum opal_mpipl_ops op, u64 src, u64 dest, u64 size);
 s64 opal_mpipl_register_tag(enum opal_mpipl_tags tag, u64 addr);
 s64 opal_mpipl_query_tag(enum opal_mpipl_tags tag, u64 *addr);
diff --git a/arch/powerpc/include/asm/secvar.h 
b/arch/powerpc/include/asm/secvar.h
new file mode 100644
index ..4cc35b58b986
--- /dev/null
+++ b/arch/powerpc/include/asm/secvar.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ *
+ * PowerPC secure variable operations.
+ */
+#ifndef SECVAR_OPS_H
+#define SECVAR_OPS_H
+
+#include 
+#include 
+
+extern const struct secvar_operations *secvar_ops;
+
+struct secvar_operations {
+   int (*get)(const char *key, uint64_t key_len, u8 *data,
+  uint64_t *data_size);
+   int (*get_next)(const char *key, uint64_t *key_len,
+   uint64_t keybufsize);
+   int (*set)(const char *key, uint64_t key_len, u8 *data,
+  uint64_t data_size);
+};
+
+#ifdef CONFIG_PPC_SECURE_BOOT
+
+extern void set_secvar_ops(const struct secvar_operations *ops);
+
+#else
+
+static inline void set_secvar_ops(const struct secvar_operations *ops) { }
+
+#endif
+
+#endif
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index e8eb2955b7d5..3cf26427334f 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -161,7 +161,7 @@ ifneq ($(CONFIG_PPC_POWERNV)$(CONFIG_PPC_SVM),)
 obj-y  += ucall.o
 endif
 
-obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o ima_arch.o
+obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o ima_arch.o secvar-ops.o
 
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
diff --git a/arch/powerpc/kernel/secvar-ops.c b/arch/powerpc/kernel/secvar-ops.c
new file mode 100644
index ..4cfa7dbd8850
--- /dev/null
+++ b/arch/powerpc/kernel/secvar-ops.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ *
+ * This file initializes secvar operations for PowerPC Secureboot
+ */
+
+#include 
+
+const struct secvar_operations *secvar_ops;
+
+void set_secvar_ops(const st

[PATCH v9 0/4] powerpc: expose secure variables to the kernel and userspace

2019-11-10 Thread Nayna Jain
dbacks:
  * fixes Patch 1/2
   * moves OPAL API wrappers after opal_nx_proc_init(), fixed the
   naming, types and removed extern.
   * fixes spaces
   * renames get_variable() to get(), get_next_variable() to get_next()
   and set_variable() to set()
   * removed get_secvar_ops() and defined secvar_ops as global
   * fixes consts and statics
   * removes generic secvar_init() and defined platform specific
   opal_secar_init()
   * updates opal_secvar_supported() to check for secvar support even
   before checking the OPAL APIs support and also fixed the error codes.
   * addes function that converts OPAL return codes to linux errno
   * moves secvar check support in the opal_secvar_init() and defined its
   prototype in opal.h
  * fixes Patch 2/2
   * fixes static/const
   * defines macro for max name size
   * replaces OPAL error codes with linux errno and also updated error
   handling
   * moves secvar support check before creating sysfs kobjects in 
   secvar_sysfs_init()
   * fixes spaces  

v2:
* removes complete efi-sms from the sysfs implementation and is simplified
* includes Greg's and Oliver's feedbacks:
 * adds sysfs documentation
 * moves sysfs code to arch/powerpc
 * other code related feedbacks.
* adds two new patches to load keys to .platform and .blacklist keyring.
These patches are added to this series as they are also dependent on
OPAL APIs.

Nayna Jain (4):
  powerpc/powernv: Add OPAL API interface to access secure variable
  powerpc: expose secure variables to userspace via sysfs
  x86/efi: move common keyring handler functions to new file
  powerpc: load firmware trusted keys/hashes into kernel keyring

 Documentation/ABI/testing/sysfs-secvar |  46 
 arch/powerpc/Kconfig   |  11 +
 arch/powerpc/include/asm/opal-api.h|   5 +-
 arch/powerpc/include/asm/opal.h|   7 +
 arch/powerpc/include/asm/secvar.h  |  35 +++
 arch/powerpc/kernel/Makefile   |   3 +-
 arch/powerpc/kernel/secvar-ops.c   |  16 ++
 arch/powerpc/kernel/secvar-sysfs.c | 248 +
 arch/powerpc/platforms/powernv/Makefile|   2 +-
 arch/powerpc/platforms/powernv/opal-call.c |   3 +
 arch/powerpc/platforms/powernv/opal-secvar.c   | 140 
 arch/powerpc/platforms/powernv/opal.c  |   3 +
 security/integrity/Kconfig |   9 +
 security/integrity/Makefile|   7 +-
 .../integrity/platform_certs/keyring_handler.c |  80 +++
 .../integrity/platform_certs/keyring_handler.h |  32 +++
 security/integrity/platform_certs/load_powerpc.c   |  99 
 security/integrity/platform_certs/load_uefi.c  |  67 +-
 18 files changed, 742 insertions(+), 71 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-secvar
 create mode 100644 arch/powerpc/include/asm/secvar.h
 create mode 100644 arch/powerpc/kernel/secvar-ops.c
 create mode 100644 arch/powerpc/kernel/secvar-sysfs.c
 create mode 100644 arch/powerpc/platforms/powernv/opal-secvar.c
 create mode 100644 security/integrity/platform_certs/keyring_handler.c
 create mode 100644 security/integrity/platform_certs/keyring_handler.h
 create mode 100644 security/integrity/platform_certs/load_powerpc.c

-- 
2.13.6



[PATCH v8 4/4] powerpc: load firmware trusted keys/hashes into kernel keyring

2019-11-09 Thread Nayna Jain
The keys used to verify the Host OS kernel are managed by firmware as
secure variables. This patch loads the verification keys into the .platform
keyring and revocation hashes into .blacklist keyring. This enables
verification and loading of the kernels signed by the boot time keys which
are trusted by firmware.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Signed-off-by: Eric Richter 
---
 security/integrity/Kconfig|  9 ++
 security/integrity/Makefile   |  4 +-
 .../integrity/platform_certs/load_powerpc.c   | 98 +++
 3 files changed, 110 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/platform_certs/load_powerpc.c

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 0bae6adb63a9..71f0177e8716 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -72,6 +72,15 @@ config LOAD_IPL_KEYS
depends on S390
def_bool y
 
+config LOAD_PPC_KEYS
+   bool "Enable loading of platform and blacklisted keys for POWER"
+   depends on INTEGRITY_PLATFORM_KEYRING
+   depends on PPC_SECURE_BOOT
+   default y
+   help
+ Enable loading of keys to the .platform keyring and blacklisted
+ hashes to the .blacklist keyring for powerpc based platforms.
+
 config INTEGRITY_AUDIT
bool "Enables integrity auditing support "
depends on AUDIT
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 351c9662994b..7ee39d66cf16 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -14,6 +14,8 @@ integrity-$(CONFIG_LOAD_UEFI_KEYS) += 
platform_certs/efi_parser.o \
  platform_certs/load_uefi.o \
  platform_certs/keyring_handler.o
 integrity-$(CONFIG_LOAD_IPL_KEYS) += platform_certs/load_ipl_s390.o
-
+integrity-$(CONFIG_LOAD_PPC_KEYS) += platform_certs/efi_parser.o \
+ platform_certs/load_powerpc.o \
+ platform_certs/keyring_handler.o
 obj-$(CONFIG_IMA)  += ima/
 obj-$(CONFIG_EVM)  += evm/
diff --git a/security/integrity/platform_certs/load_powerpc.c 
b/security/integrity/platform_certs/load_powerpc.c
new file mode 100644
index ..99ddc2ed59e6
--- /dev/null
+++ b/security/integrity/platform_certs/load_powerpc.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ *
+ *  - loads keys and hashes stored and controlled by the firmware.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "keyring_handler.h"
+
+/*
+ * Get a certificate list blob from the named secure variable.
+ */
+static __init void *get_cert_list(u8 *key, unsigned long keylen, uint64_t 
*size)
+{
+   int rc;
+   void *db;
+
+   rc = secvar_ops->get(key, keylen, NULL, size);
+   if (rc) {
+   pr_err("Couldn't get size: %d\n", rc);
+   return NULL;
+   }
+
+   db = kmalloc(*size, GFP_KERNEL);
+   if (!db)
+   return NULL;
+
+   rc = secvar_ops->get(key, keylen, db, size);
+   if (rc) {
+   kfree(db);
+   pr_err("Error reading %s var: %d\n", key, rc);
+   return NULL;
+   }
+
+   return db;
+}
+
+/*
+ * Load the certs contained in the keys databases into the platform trusted
+ * keyring and the blacklisted X.509 cert SHA256 hashes into the blacklist
+ * keyring.
+ */
+static int __init load_powerpc_certs(void)
+{
+   void *db = NULL, *dbx = NULL;
+   uint64_t dbsize = 0, dbxsize = 0;
+   int rc = 0;
+   struct device_node *node;
+
+   if (!secvar_ops)
+   return -ENODEV;
+
+   /* The following only applies for the edk2-compat backend.
+* Return early if it is not set.
+*/
+
+   node = of_find_compatible_node(NULL, NULL, "ibm,edk2-compat-v1");
+   if (!node)
+   return -ENODEV;
+
+   /* Get db, and dbx.  They might not exist, so it isn't
+* an error if we can't get them.
+*/
+   db = get_cert_list("db", 3, );
+   if (!db) {
+   pr_err("Couldn't get db list from firmware\n");
+   } else {
+   rc = parse_efi_signature_list("powerpc:db", db, dbsize,
+ get_handler_for_db);
+   if (rc)
+   pr_err("Couldn't parse db signatures: %d\n", rc);
+   kfree(db);
+   }
+
+   dbx = get_cert_list("dbx", 4,  );
+   if (!dbx) {
+   pr_info("Couldn't get dbx list from firmware\n");
+   } else {
+   rc = parse_efi_signature_list("powerpc:dbx", dbx, dbxsize,
+ 

[PATCH v8 3/4] x86/efi: move common keyring handler functions to new file

2019-11-09 Thread Nayna Jain
The handlers to add the keys to the .platform keyring and blacklisted
hashes to the .blacklist keyring is common for both the uefi and powerpc
mechanisms of loading the keys/hashes from the firmware.

This patch moves the common code from load_uefi.c to keyring_handler.c

Signed-off-by: Nayna Jain 
Acked-by: Mimi Zohar 
Signed-off-by: Eric Richter 
---
 security/integrity/Makefile   |  3 +-
 .../platform_certs/keyring_handler.c  | 80 +++
 .../platform_certs/keyring_handler.h  | 32 
 security/integrity/platform_certs/load_uefi.c | 67 +---
 4 files changed, 115 insertions(+), 67 deletions(-)
 create mode 100644 security/integrity/platform_certs/keyring_handler.c
 create mode 100644 security/integrity/platform_certs/keyring_handler.h

diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 35e6ca773734..351c9662994b 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -11,7 +11,8 @@ integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
 integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o
 integrity-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/efi_parser.o \
-   platform_certs/load_uefi.o
+ platform_certs/load_uefi.o \
+ platform_certs/keyring_handler.o
 integrity-$(CONFIG_LOAD_IPL_KEYS) += platform_certs/load_ipl_s390.o
 
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/platform_certs/keyring_handler.c 
b/security/integrity/platform_certs/keyring_handler.c
new file mode 100644
index ..c5ba695c10e3
--- /dev/null
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../integrity.h"
+
+static efi_guid_t efi_cert_x509_guid __initdata = EFI_CERT_X509_GUID;
+static efi_guid_t efi_cert_x509_sha256_guid __initdata =
+   EFI_CERT_X509_SHA256_GUID;
+static efi_guid_t efi_cert_sha256_guid __initdata = EFI_CERT_SHA256_GUID;
+
+/*
+ * Blacklist a hash.
+ */
+static __init void uefi_blacklist_hash(const char *source, const void *data,
+  size_t len, const char *type,
+  size_t type_len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(type_len + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, type, type_len);
+   p += type_len;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfree(hash);
+}
+
+/*
+ * Blacklist an X509 TBS hash.
+ */
+static __init void uefi_blacklist_x509_tbs(const char *source,
+  const void *data, size_t len)
+{
+   uefi_blacklist_hash(source, data, len, "tbs:", 4);
+}
+
+/*
+ * Blacklist the hash of an executable.
+ */
+static __init void uefi_blacklist_binary(const char *source,
+const void *data, size_t len)
+{
+   uefi_blacklist_hash(source, data, len, "bin:", 4);
+}
+
+/*
+ * Return the appropriate handler for particular signature list types found in
+ * the UEFI db and MokListRT tables.
+ */
+__init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
+   return add_to_platform_keyring;
+   return 0;
+}
+
+/*
+ * Return the appropriate handler for particular signature list types found in
+ * the UEFI dbx and MokListXRT tables.
+ */
+__init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_sha256_guid) == 0)
+   return uefi_blacklist_x509_tbs;
+   if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0)
+   return uefi_blacklist_binary;
+   return 0;
+}
diff --git a/security/integrity/platform_certs/keyring_handler.h 
b/security/integrity/platform_certs/keyring_handler.h
new file mode 100644
index ..2462bfa08fe3
--- /dev/null
+++ b/security/integrity/platform_certs/keyring_handler.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef PLATFORM_CERTS_INTERNAL_H
+#define PLATFORM_CERTS_INTERNAL_H
+
+#include 
+
+void blacklist_hash(const char *source, const void *data,
+   size_t len, const char *type,
+   size_t type_len);
+
+/*
+ * Blacklist an X509 TBS hash.
+ */
+void blacklist_x509_tbs(const char *source, const void *data, size_t len);
+
+/*
+ * Blacklist the hash of an executable.
+ */
+void blacklist_binary(const char *source, const void *data, size_t len);
+
+/*
+ * Return the handler for particular signat

[PATCH v8 2/4] powerpc: expose secure variables to userspace via sysfs

2019-11-09 Thread Nayna Jain
PowerNV secure variables, which store the keys used for OS kernel
verification, are managed by the firmware. These secure variables need to
be accessed by the userspace for addition/deletion of the certificates.

This patch adds the sysfs interface to expose secure variables for PowerNV
secureboot. The users shall use this interface for manipulating
the keys stored in the secure variables.

Signed-off-by: Nayna Jain 
Reviewed-by: Greg Kroah-Hartman 
Signed-off-by: Eric Richter 
---
 Documentation/ABI/testing/sysfs-secvar |  46 +
 arch/powerpc/Kconfig   |  11 ++
 arch/powerpc/kernel/Makefile   |   1 +
 arch/powerpc/kernel/secvar-sysfs.c | 248 +
 4 files changed, 306 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-secvar
 create mode 100644 arch/powerpc/kernel/secvar-sysfs.c

diff --git a/Documentation/ABI/testing/sysfs-secvar 
b/Documentation/ABI/testing/sysfs-secvar
new file mode 100644
index ..911b89cc6957
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-secvar
@@ -0,0 +1,46 @@
+What:  /sys/firmware/secvar
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   This directory is created if the POWER firmware supports OS
+   secureboot, thereby secure variables. It exposes interface
+   for reading/writing the secure variables
+
+What:  /sys/firmware/secvar/vars
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   This directory lists all the secure variables that are supported
+   by the firmware.
+
+What:  /sys/firmware/secvar/backend
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   A string indicating which backend is in use by the firmware.
+   This determines the format of the variable and the accepted
+   format of variable updates.
+
+What:  /sys/firmware/secvar/vars/
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   Each secure variable is represented as a directory named as
+   . The variable name is unique and is in ASCII
+   representation. The data and size can be determined by reading
+   their respective attribute files.
+
+What:  /sys/firmware/secvar/vars//size
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   An integer representation of the size of the content of the
+   variable. In other words, it represents the size of the data.
+
+What:  /sys/firmware/secvar/vars//data
+Date:  August 2019
+Contact:   Nayna Jain h
+Description:   A read-only file containing the value of the variable. The size
+   of the file represents the maximum size of the variable data.
+
+What:  /sys/firmware/secvar/vars//update
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   A write-only file that is used to submit the new value for the
+   variable. The size of the file represents the maximum size of
+   the variable data that can be written.
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c795039bdc73..cabc091f3fe1 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -945,6 +945,17 @@ config PPC_SECURE_BOOT
  to enable OS secure boot on systems that have firmware support for
  it. If in doubt say N.
 
+config PPC_SECVAR_SYSFS
+   bool "Enable sysfs interface for POWER secure variables"
+   default y
+   depends on PPC_SECURE_BOOT
+   depends on SYSFS
+   help
+ POWER secure variables are managed and controlled by firmware.
+ These variables are exposed to userspace via sysfs to enable
+ read/write operations on these variables. Say Y if you have
+ secure boot enabled and want to expose variables to userspace.
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 3cf26427334f..b216e9f316ee 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -162,6 +162,7 @@ obj-y   += ucall.o
 endif
 
 obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o ima_arch.o secvar-ops.o
+obj-$(CONFIG_PPC_SECVAR_SYSFS) += secvar-sysfs.o
 
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
diff --git a/arch/powerpc/kernel/secvar-sysfs.c 
b/arch/powerpc/kernel/secvar-sysfs.c
new file mode 100644
index ..39345edbdecc
--- /dev/null
+++ b/arch/powerpc/kernel/secvar-sysfs.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 IBM Corporation 
+ *
+ * This code exposes secure variables to user via sysfs
+ */
+
+#define pr_fmt(fmt) "secvar-sysfs: "fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define NAME_MAX_SIZE 1024
+
+static struct kobject *secvar_kobj;
+static struct kset *secvar_kset;
+
+sta

[PATCH v8 1/4] powerpc/powernv: Add OPAL API interface to access secure variable

2019-11-09 Thread Nayna Jain
The X.509 certificates trusted by the platform and required to secure boot
the OS kernel are wrapped in secure variables, which are controlled by
OPAL.

This patch adds firmware/kernel interface to read and write OPAL secure
variables based on the unique key.

This support can be enabled using CONFIG_OPAL_SECVAR.

Signed-off-by: Claudio Carvalho 
Signed-off-by: Nayna Jain 
Signed-off-by: Eric Richter 
---
 arch/powerpc/include/asm/opal-api.h  |   5 +-
 arch/powerpc/include/asm/opal.h  |   7 +
 arch/powerpc/include/asm/secvar.h|  35 +
 arch/powerpc/kernel/Makefile |   2 +-
 arch/powerpc/kernel/secvar-ops.c |  16 +++
 arch/powerpc/platforms/powernv/Makefile  |   2 +-
 arch/powerpc/platforms/powernv/opal-call.c   |   3 +
 arch/powerpc/platforms/powernv/opal-secvar.c | 140 +++
 arch/powerpc/platforms/powernv/opal.c|   3 +
 9 files changed, 210 insertions(+), 3 deletions(-)
 create mode 100644 arch/powerpc/include/asm/secvar.h
 create mode 100644 arch/powerpc/kernel/secvar-ops.c
 create mode 100644 arch/powerpc/platforms/powernv/opal-secvar.c

diff --git a/arch/powerpc/include/asm/opal-api.h 
b/arch/powerpc/include/asm/opal-api.h
index 378e3997845a..c1f25a760eb1 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -211,7 +211,10 @@
 #define OPAL_MPIPL_UPDATE  173
 #define OPAL_MPIPL_REGISTER_TAG174
 #define OPAL_MPIPL_QUERY_TAG   175
-#define OPAL_LAST  175
+#define OPAL_SECVAR_GET176
+#define OPAL_SECVAR_GET_NEXT   177
+#define OPAL_SECVAR_ENQUEUE_UPDATE 178
+#define OPAL_LAST  178
 
 #define QUIESCE_HOLD   1 /* Spin all calls at entry */
 #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index a0cf8fba4d12..9986ac34b8e2 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -298,6 +298,13 @@ int opal_sensor_group_clear(u32 group_hndl, int token);
 int opal_sensor_group_enable(u32 group_hndl, int token, bool enable);
 int opal_nx_coproc_init(uint32_t chip_id, uint32_t ct);
 
+int opal_secvar_get(const char *key, uint64_t key_len, u8 *data,
+   uint64_t *data_size);
+int opal_secvar_get_next(const char *key, uint64_t *key_len,
+uint64_t key_buf_size);
+int opal_secvar_enqueue_update(const char *key, uint64_t key_len, u8 *data,
+  uint64_t data_size);
+
 s64 opal_mpipl_update(enum opal_mpipl_ops op, u64 src, u64 dest, u64 size);
 s64 opal_mpipl_register_tag(enum opal_mpipl_tags tag, u64 addr);
 s64 opal_mpipl_query_tag(enum opal_mpipl_tags tag, u64 *addr);
diff --git a/arch/powerpc/include/asm/secvar.h 
b/arch/powerpc/include/asm/secvar.h
new file mode 100644
index ..4cc35b58b986
--- /dev/null
+++ b/arch/powerpc/include/asm/secvar.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ *
+ * PowerPC secure variable operations.
+ */
+#ifndef SECVAR_OPS_H
+#define SECVAR_OPS_H
+
+#include 
+#include 
+
+extern const struct secvar_operations *secvar_ops;
+
+struct secvar_operations {
+   int (*get)(const char *key, uint64_t key_len, u8 *data,
+  uint64_t *data_size);
+   int (*get_next)(const char *key, uint64_t *key_len,
+   uint64_t keybufsize);
+   int (*set)(const char *key, uint64_t key_len, u8 *data,
+  uint64_t data_size);
+};
+
+#ifdef CONFIG_PPC_SECURE_BOOT
+
+extern void set_secvar_ops(const struct secvar_operations *ops);
+
+#else
+
+static inline void set_secvar_ops(const struct secvar_operations *ops) { }
+
+#endif
+
+#endif
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index e8eb2955b7d5..3cf26427334f 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -161,7 +161,7 @@ ifneq ($(CONFIG_PPC_POWERNV)$(CONFIG_PPC_SVM),)
 obj-y  += ucall.o
 endif
 
-obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o ima_arch.o
+obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o ima_arch.o secvar-ops.o
 
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
diff --git a/arch/powerpc/kernel/secvar-ops.c b/arch/powerpc/kernel/secvar-ops.c
new file mode 100644
index ..4cfa7dbd8850
--- /dev/null
+++ b/arch/powerpc/kernel/secvar-ops.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ *
+ * This file initializes secvar operations for PowerPC Secureboot
+ */
+
+#include 
+
+const struct secvar_operations *secvar_ops;
+
+void set_secvar_ops(const struct secvar_operations 

[PATCH v8 0/4] powerpc: expose secure variables to the kernel and userspace

2019-11-09 Thread Nayna Jain
atics
   * removes generic secvar_init() and defined platform specific
   opal_secar_init()
   * updates opal_secvar_supported() to check for secvar support even
   before checking the OPAL APIs support and also fixed the error codes.
   * addes function that converts OPAL return codes to linux errno
   * moves secvar check support in the opal_secvar_init() and defined its
   prototype in opal.h
  * fixes Patch 2/2
   * fixes static/const
   * defines macro for max name size
   * replaces OPAL error codes with linux errno and also updated error
   handling
   * moves secvar support check before creating sysfs kobjects in 
   secvar_sysfs_init()
   * fixes spaces  

v2:
* removes complete efi-sms from the sysfs implementation and is simplified
* includes Greg's and Oliver's feedbacks:
 * adds sysfs documentation
 * moves sysfs code to arch/powerpc
 * other code related feedbacks.
* adds two new patches to load keys to .platform and .blacklist keyring.
These patches are added to this series as they are also dependent on
OPAL APIs.

Nayna Jain (4):
  powerpc/powernv: Add OPAL API interface to access secure variable
  powerpc: expose secure variables to userspace via sysfs
  x86/efi: move common keyring handler functions to new file
  powerpc: load firmware trusted keys/hashes into kernel keyring

 Documentation/ABI/testing/sysfs-secvar|  46 
 arch/powerpc/Kconfig  |  11 +
 arch/powerpc/include/asm/opal-api.h   |   5 +-
 arch/powerpc/include/asm/opal.h   |   7 +
 arch/powerpc/include/asm/secvar.h |  35 +++
 arch/powerpc/kernel/Makefile  |   3 +-
 arch/powerpc/kernel/secvar-ops.c  |  16 ++
 arch/powerpc/kernel/secvar-sysfs.c| 248 ++
 arch/powerpc/platforms/powernv/Makefile   |   2 +-
 arch/powerpc/platforms/powernv/opal-call.c|   3 +
 arch/powerpc/platforms/powernv/opal-secvar.c  | 140 ++
 arch/powerpc/platforms/powernv/opal.c |   3 +
 security/integrity/Kconfig|   9 +
 security/integrity/Makefile   |   7 +-
 .../platform_certs/keyring_handler.c  |  80 ++
 .../platform_certs/keyring_handler.h  |  32 +++
 .../integrity/platform_certs/load_powerpc.c   |  98 +++
 security/integrity/platform_certs/load_uefi.c |  67 +
 18 files changed, 741 insertions(+), 71 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-secvar
 create mode 100644 arch/powerpc/include/asm/secvar.h
 create mode 100644 arch/powerpc/kernel/secvar-ops.c
 create mode 100644 arch/powerpc/kernel/secvar-sysfs.c
 create mode 100644 arch/powerpc/platforms/powernv/opal-secvar.c
 create mode 100644 security/integrity/platform_certs/keyring_handler.c
 create mode 100644 security/integrity/platform_certs/keyring_handler.h
 create mode 100644 security/integrity/platform_certs/load_powerpc.c

-- 
2.20.1



Re: [PATCH v9 7/8] ima: check against blacklisted hashes for files with modsig

2019-10-25 Thread Nayna Jain



On 10/24/19 12:48 PM, Lakshmi Ramasubramanian wrote:

On 10/23/2019 8:47 PM, Nayna Jain wrote:


+/*
+ * ima_check_blacklist - determine if the binary is blacklisted.
+ *
+ * Add the hash of the blacklisted binary to the measurement list, 
based

+ * on policy.
+ *
+ * Returns -EPERM if the hash is blacklisted.
+ */
+int ima_check_blacklist(struct integrity_iint_cache *iint,
+    const struct modsig *modsig, int pcr)
+{
+    enum hash_algo hash_algo;
+    const u8 *digest = NULL;
+    u32 digestsize = 0;
+    int rc = 0;
+
+    if (!(iint->flags & IMA_CHECK_BLACKLIST))
+    return 0;
+
+    if (iint->flags & IMA_MODSIG_ALLOWED && modsig) {
+    ima_get_modsig_digest(modsig, _algo, , 
);

+
+    rc = is_binary_blacklisted(digest, digestsize);
+    if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
+    process_buffer_measurement(digest, digestsize,
+   "blacklisted-hash", NONE,
+   pcr);
+    }


The enum value "NONE" is being passed to process_buffer_measurement to 
indicate that the check for required action based on ima policy is 
already done by ima_check_blacklist. Not sure, but this can cause 
confusion in the future when someone updates process_buffer_measurement.



As I explained in the response to other patch, the purpose is to 
indicate that it is an auxiliary measurement record. By passing func as 
NONE, it implies there is no explicit policy to be queried for the 
template as it is an additional record for an existing policy and is to 
use ima-buf template.


What type of confusion do you mean ?

Thanks & Regards,

 - Nayna



Re: [PATCH v9 5/8] ima: make process_buffer_measurement() generic

2019-10-25 Thread Nayna Jain



On 10/24/19 10:20 AM, Lakshmi Ramasubramanian wrote:

On 10/23/19 8:47 PM, Nayna Jain wrote:

Hi Nayna,


+void process_buffer_measurement(const void *buf, int size,
+    const char *eventname, enum ima_hooks func,
+    int pcr)
  {
  int ret = 0;
  struct ima_template_entry *entry = NULL;



+    if (func) {
+    security_task_getsecid(current, );
+    action = ima_get_action(NULL, current_cred(), secid, 0, func,
+    , );
+    if (!(action & IMA_MEASURE))
+    return;
+    }


In your change set process_buffer_measurement is called with NONE for 
the parameter func. So ima_get_action (the above if block) will not be 
executed.


Wouldn't it better to update ima_get_action (and related functions) to 
handle the ima policy (func param)?



The idea is to use ima-buf template for the auxiliary measurement 
record. The auxiliary measurement record is an additional record to the 
one already created based on the existing policy. When func is passed as 
NONE, it represents it is an additional record. I am not sure what you 
mean by updating ima_get_action, it is already handling the ima policy.


Thanks & Regards,

    - Nayna



Re: [PATCH v9 2/8] powerpc/ima: add support to initialize ima policy rules

2019-10-25 Thread Nayna Jain



On 10/24/19 12:35 PM, Lakshmi Ramasubramanian wrote:

On 10/23/2019 8:47 PM, Nayna Jain wrote:


+/*
+ * The "secure_rules" are enabled only on "secureboot" enabled systems.
+ * These rules verify the file signatures against known good values.
+ * The "appraise_type=imasig|modsig" option allows the known good 
signature

+ * to be stored as an xattr or as an appended signature.
+ *
+ * To avoid duplicate signature verification as much as possible, 
the IMA
+ * policy rule for module appraisal is added only if 
CONFIG_MODULE_SIG_FORCE

+ * is not enabled.
+ */
+static const char *const secure_rules[] = {
+    "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig",
+#ifndef CONFIG_MODULE_SIG_FORCE
+    "appraise func=MODULE_CHECK appraise_type=imasig|modsig",
+#endif
+    NULL
+};


Is there any way to not use conditional compilation in the above array 
definition? Maybe define different functions to get "secure_rules" for 
when CONFIG_MODULE_SIG_FORCE is defined and when it is not defined.


How will you decide which function to be called ?

Thanks & Regards,

    - Nayna



Re: [PATCH v9 1/8] powerpc: detect the secure boot mode of the system

2019-10-25 Thread Nayna Jain



On 10/24/19 12:26 PM, Lakshmi Ramasubramanian wrote:

On 10/23/2019 8:47 PM, Nayna Jain wrote:

This patch defines a function to detect the secure boot state of a
PowerNV system.



+bool is_ppc_secureboot_enabled(void)
+{
+    struct device_node *node;
+    bool enabled = false;
+
+    node = of_find_compatible_node(NULL, NULL, "ibm,secvar-v1");
+    if (!of_device_is_available(node)) {
+    pr_err("Cannot find secure variable node in device tree; 
failing to secure state\n");

+    goto out;


Related to "goto out;" above:

Would of_find_compatible_node return NULL if the given node is not found?

If of_device_is_available returns false (say, because node is NULL or 
it does not find the specified node) would it be correct to call 
of_node_put?


of_node_put() handles NULL.

Thanks & Regards,

 - Nayna



Re: [PATCH v9 3/8] powerpc: detect the trusted boot state of the system

2019-10-25 Thread Nayna Jain



On 10/24/19 12:38 PM, Lakshmi Ramasubramanian wrote:

On 10/23/2019 8:47 PM, Nayna Jain wrote:


+bool is_ppc_trustedboot_enabled(void)
+{
+    struct device_node *node;
+    bool enabled = false;
+
+    node = get_ppc_fw_sb_node();
+    enabled = of_property_read_bool(node, "trusted-enabled");


Can get_ppc_fw_sb_node return NULL?
Would of_property_read_bool handle the case when node is NULL?


Yes.

Thanks & Regards,

 - Nayna



[PATCH v5 4/4] powerpc: load firmware trusted keys/hashes into kernel keyring

2019-10-24 Thread Nayna Jain
The keys used to verify the Host OS kernel are managed by firmware as
secure variables. This patch loads the verification keys into the .platform
keyring and revocation hashes into .blacklist keyring. This enables
verification and loading of the kernels signed by the boot time keys which
are trusted by firmware.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
---
 arch/powerpc/Kconfig  |  1 +
 security/integrity/Kconfig|  8 ++
 security/integrity/Makefile   |  4 +-
 .../integrity/platform_certs/load_powerpc.c   | 86 +++
 4 files changed, 98 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/platform_certs/load_powerpc.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 949e747bc8c2..5d860ed6c901 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -939,6 +939,7 @@ config PPC_SECURE_BOOT
bool
depends on PPC_POWERNV
depends on IMA_ARCH_POLICY
+   select LOAD_PPC_KEYS
help
  Systems with firmware secure boot enabled need to define security
  policies to extend secure boot to the OS. This config allows a user
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 0bae6adb63a9..26abee23e4e3 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -72,6 +72,14 @@ config LOAD_IPL_KEYS
depends on S390
def_bool y
 
+config LOAD_PPC_KEYS
+   bool "Enable loading of platform and blacklisted keys for POWER"
+   depends on INTEGRITY_PLATFORM_KEYRING
+   depends on PPC_SECURE_BOOT
+   help
+ Enable loading of keys to the .platform keyring and blacklisted
+ hashes to the .blacklist keyring for powerpc based platforms.
+
 config INTEGRITY_AUDIT
bool "Enables integrity auditing support "
depends on AUDIT
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 351c9662994b..7ee39d66cf16 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -14,6 +14,8 @@ integrity-$(CONFIG_LOAD_UEFI_KEYS) += 
platform_certs/efi_parser.o \
  platform_certs/load_uefi.o \
  platform_certs/keyring_handler.o
 integrity-$(CONFIG_LOAD_IPL_KEYS) += platform_certs/load_ipl_s390.o
-
+integrity-$(CONFIG_LOAD_PPC_KEYS) += platform_certs/efi_parser.o \
+ platform_certs/load_powerpc.o \
+ platform_certs/keyring_handler.o
 obj-$(CONFIG_IMA)  += ima/
 obj-$(CONFIG_EVM)  += evm/
diff --git a/security/integrity/platform_certs/load_powerpc.c 
b/security/integrity/platform_certs/load_powerpc.c
new file mode 100644
index ..83d99cde5376
--- /dev/null
+++ b/security/integrity/platform_certs/load_powerpc.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ *
+ *  - loads keys and hashes stored and controlled by the firmware.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "keyring_handler.h"
+
+/*
+ * Get a certificate list blob from the named secure variable.
+ */
+static __init void *get_cert_list(u8 *key, unsigned long keylen, uint64_t 
*size)
+{
+   int rc;
+   void *db;
+
+   rc = secvar_ops->get(key, keylen, NULL, size);
+   if (rc) {
+   pr_err("Couldn't get size: %d\n", rc);
+   return NULL;
+   }
+
+   db = kmalloc(*size, GFP_KERNEL);
+   if (!db)
+   return NULL;
+
+   rc = secvar_ops->get(key, keylen, db, size);
+   if (rc) {
+   kfree(db);
+   pr_err("Error reading db var: %d\n", rc);
+   return NULL;
+   }
+
+   return db;
+}
+
+/*
+ * Load the certs contained in the keys databases into the platform trusted
+ * keyring and the blacklisted X.509 cert SHA256 hashes into the blacklist
+ * keyring.
+ */
+static int __init load_powerpc_certs(void)
+{
+   void *db = NULL, *dbx = NULL;
+   uint64_t dbsize = 0, dbxsize = 0;
+   int rc = 0;
+
+   if (!secvar_ops)
+   return -ENODEV;
+
+   /* Get db, and dbx.  They might not exist, so it isn't
+* an error if we can't get them.
+*/
+   db = get_cert_list("db", 3, );
+   if (!db) {
+   pr_err("Couldn't get db list from firmware\n");
+   } else {
+   rc = parse_efi_signature_list("powerpc:db", db, dbsize,
+ get_handler_for_db);
+   if (rc)
+   pr_err("Couldn't parse db signatures: %d\n", rc);
+   kfree(db);
+   }
+
+   dbx = get_cert_list("dbx", 3,  );
+   if (!db

[PATCH v5 3/4] x86/efi: move common keyring handler functions to new file

2019-10-24 Thread Nayna Jain
The handlers to add the keys to the .platform keyring and blacklisted
hashes to the .blacklist keyring is common for both the uefi and powerpc
mechanisms of loading the keys/hashes from the firmware.

This patch moves the common code from load_uefi.c to keyring_handler.c

Signed-off-by: Nayna Jain 
Acked-by: Mimi Zohar 
---
 security/integrity/Makefile   |  3 +-
 .../platform_certs/keyring_handler.c  | 80 +++
 .../platform_certs/keyring_handler.h  | 32 
 security/integrity/platform_certs/load_uefi.c | 67 +---
 4 files changed, 115 insertions(+), 67 deletions(-)
 create mode 100644 security/integrity/platform_certs/keyring_handler.c
 create mode 100644 security/integrity/platform_certs/keyring_handler.h

diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 35e6ca773734..351c9662994b 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -11,7 +11,8 @@ integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
 integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o
 integrity-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/efi_parser.o \
-   platform_certs/load_uefi.o
+ platform_certs/load_uefi.o \
+ platform_certs/keyring_handler.o
 integrity-$(CONFIG_LOAD_IPL_KEYS) += platform_certs/load_ipl_s390.o
 
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/platform_certs/keyring_handler.c 
b/security/integrity/platform_certs/keyring_handler.c
new file mode 100644
index ..c5ba695c10e3
--- /dev/null
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../integrity.h"
+
+static efi_guid_t efi_cert_x509_guid __initdata = EFI_CERT_X509_GUID;
+static efi_guid_t efi_cert_x509_sha256_guid __initdata =
+   EFI_CERT_X509_SHA256_GUID;
+static efi_guid_t efi_cert_sha256_guid __initdata = EFI_CERT_SHA256_GUID;
+
+/*
+ * Blacklist a hash.
+ */
+static __init void uefi_blacklist_hash(const char *source, const void *data,
+  size_t len, const char *type,
+  size_t type_len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(type_len + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, type, type_len);
+   p += type_len;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfree(hash);
+}
+
+/*
+ * Blacklist an X509 TBS hash.
+ */
+static __init void uefi_blacklist_x509_tbs(const char *source,
+  const void *data, size_t len)
+{
+   uefi_blacklist_hash(source, data, len, "tbs:", 4);
+}
+
+/*
+ * Blacklist the hash of an executable.
+ */
+static __init void uefi_blacklist_binary(const char *source,
+const void *data, size_t len)
+{
+   uefi_blacklist_hash(source, data, len, "bin:", 4);
+}
+
+/*
+ * Return the appropriate handler for particular signature list types found in
+ * the UEFI db and MokListRT tables.
+ */
+__init efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
+   return add_to_platform_keyring;
+   return 0;
+}
+
+/*
+ * Return the appropriate handler for particular signature list types found in
+ * the UEFI dbx and MokListXRT tables.
+ */
+__init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_sha256_guid) == 0)
+   return uefi_blacklist_x509_tbs;
+   if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0)
+   return uefi_blacklist_binary;
+   return 0;
+}
diff --git a/security/integrity/platform_certs/keyring_handler.h 
b/security/integrity/platform_certs/keyring_handler.h
new file mode 100644
index ..2462bfa08fe3
--- /dev/null
+++ b/security/integrity/platform_certs/keyring_handler.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef PLATFORM_CERTS_INTERNAL_H
+#define PLATFORM_CERTS_INTERNAL_H
+
+#include 
+
+void blacklist_hash(const char *source, const void *data,
+   size_t len, const char *type,
+   size_t type_len);
+
+/*
+ * Blacklist an X509 TBS hash.
+ */
+void blacklist_x509_tbs(const char *source, const void *data, size_t len);
+
+/*
+ * Blacklist the hash of an executable.
+ */
+void blacklist_binary(const char *source, const void *data, size_t len);
+
+/*
+ * Return the handler for particular signature list types found in the d

[PATCH v5 2/4] powerpc: expose secure variables to userspace via sysfs

2019-10-24 Thread Nayna Jain
PowerNV secure variables, which store the keys used for OS kernel
verification, are managed by the firmware. These secure variables need to
be accessed by the userspace for addition/deletion of the certificates.

This patch adds the sysfs interface to expose secure variables for PowerNV
secureboot. The users shall use this interface for manipulating
the keys stored in the secure variables.

Signed-off-by: Nayna Jain 
Reviewed-by: Greg Kroah-Hartman 
---
 Documentation/ABI/testing/sysfs-secvar |  39 +
 arch/powerpc/Kconfig   |  11 ++
 arch/powerpc/kernel/Makefile   |   1 +
 arch/powerpc/kernel/secvar-sysfs.c | 228 +
 4 files changed, 279 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-secvar
 create mode 100644 arch/powerpc/kernel/secvar-sysfs.c

diff --git a/Documentation/ABI/testing/sysfs-secvar 
b/Documentation/ABI/testing/sysfs-secvar
new file mode 100644
index ..bc0bedf2b662
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-secvar
@@ -0,0 +1,39 @@
+What:  /sys/firmware/secvar
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   This directory is created if the POWER firmware supports OS
+   secureboot, thereby secure variables. It exposes interface
+   for reading/writing the secure variables
+
+What:  /sys/firmware/secvar/vars
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   This directory lists all the secure variables that are supported
+   by the firmware.
+
+What:  /sys/firmware/secvar/vars/
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   Each secure variable is represented as a directory named as
+   . The variable name is unique and is in ASCII
+   representation. The data and size can be determined by reading
+   their respective attribute files.
+
+What:  /sys/firmware/secvar/vars//size
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   An integer representation of the size of the content of the
+   variable. In other words, it represents the size of the data.
+
+What:  /sys/firmware/secvar/vars//data
+Date:  August 2019
+Contact:   Nayna Jain h
+Description:   A read-only file containing the value of the variable. The size
+   of the file represents the maximum size of the variable data.
+
+What:  /sys/firmware/secvar/vars//update
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:   A write-only file that is used to submit the new value for the
+   variable. The size of the file represents the maximum size of
+   the variable data that can be written.
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c795039bdc73..949e747bc8c2 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -945,6 +945,17 @@ config PPC_SECURE_BOOT
  to enable OS secure boot on systems that have firmware support for
  it. If in doubt say N.
 
+config PPC_SECVAR_SYSFS
+   tristate "Enable sysfs interface for POWER secure variables"
+   default y
+   depends on PPC_SECURE_BOOT
+   depends on SYSFS
+   help
+ POWER secure variables are managed and controlled by firmware.
+ These variables are exposed to userspace via sysfs to enable
+ read/write operations on these variables. Say Y if you have
+ secure boot enabled and want to expose variables to userspace.
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 3cf26427334f..b216e9f316ee 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -162,6 +162,7 @@ obj-y   += ucall.o
 endif
 
 obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o ima_arch.o secvar-ops.o
+obj-$(CONFIG_PPC_SECVAR_SYSFS) += secvar-sysfs.o
 
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
diff --git a/arch/powerpc/kernel/secvar-sysfs.c 
b/arch/powerpc/kernel/secvar-sysfs.c
new file mode 100644
index ..f0c4950649e0
--- /dev/null
+++ b/arch/powerpc/kernel/secvar-sysfs.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 IBM Corporation 
+ *
+ * This code exposes secure variables to user via sysfs
+ */
+
+#define pr_fmt(fmt) "secvar-sysfs: "fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define NAME_MAX_SIZE 1024
+
+static struct kobject *secvar_kobj;
+static struct kset *secvar_kset;
+
+static ssize_t size_show(struct kobject *kobj, struct kobj_attribute *attr,
+char *buf)
+{
+   uint64_t dsize;
+   int rc;
+
+   rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, NULL, );
+   if (rc) {
+   pr_err("Error retrieving variable size

[PATCH v5 1/4] powerpc/powernv: Add OPAL API interface to access secure variable

2019-10-24 Thread Nayna Jain
The X.509 certificates trusted by the platform and required to secure boot
the OS kernel are wrapped in secure variables, which are controlled by
OPAL.

This patch adds firmware/kernel interface to read and write OPAL secure
variables based on the unique key.

This support can be enabled using CONFIG_OPAL_SECVAR.

Signed-off-by: Claudio Carvalho 
Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/opal-api.h  |   5 +-
 arch/powerpc/include/asm/opal.h  |   7 +
 arch/powerpc/include/asm/secvar.h|  35 +
 arch/powerpc/kernel/Makefile |   2 +-
 arch/powerpc/kernel/secvar-ops.c |  16 +++
 arch/powerpc/platforms/powernv/Makefile  |   2 +-
 arch/powerpc/platforms/powernv/opal-call.c   |   3 +
 arch/powerpc/platforms/powernv/opal-secvar.c | 140 +++
 arch/powerpc/platforms/powernv/opal.c|   3 +
 9 files changed, 210 insertions(+), 3 deletions(-)
 create mode 100644 arch/powerpc/include/asm/secvar.h
 create mode 100644 arch/powerpc/kernel/secvar-ops.c
 create mode 100644 arch/powerpc/platforms/powernv/opal-secvar.c

diff --git a/arch/powerpc/include/asm/opal-api.h 
b/arch/powerpc/include/asm/opal-api.h
index 378e3997845a..c1f25a760eb1 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -211,7 +211,10 @@
 #define OPAL_MPIPL_UPDATE  173
 #define OPAL_MPIPL_REGISTER_TAG174
 #define OPAL_MPIPL_QUERY_TAG   175
-#define OPAL_LAST  175
+#define OPAL_SECVAR_GET176
+#define OPAL_SECVAR_GET_NEXT   177
+#define OPAL_SECVAR_ENQUEUE_UPDATE 178
+#define OPAL_LAST  178
 
 #define QUIESCE_HOLD   1 /* Spin all calls at entry */
 #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index a0cf8fba4d12..9986ac34b8e2 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -298,6 +298,13 @@ int opal_sensor_group_clear(u32 group_hndl, int token);
 int opal_sensor_group_enable(u32 group_hndl, int token, bool enable);
 int opal_nx_coproc_init(uint32_t chip_id, uint32_t ct);
 
+int opal_secvar_get(const char *key, uint64_t key_len, u8 *data,
+   uint64_t *data_size);
+int opal_secvar_get_next(const char *key, uint64_t *key_len,
+uint64_t key_buf_size);
+int opal_secvar_enqueue_update(const char *key, uint64_t key_len, u8 *data,
+  uint64_t data_size);
+
 s64 opal_mpipl_update(enum opal_mpipl_ops op, u64 src, u64 dest, u64 size);
 s64 opal_mpipl_register_tag(enum opal_mpipl_tags tag, u64 addr);
 s64 opal_mpipl_query_tag(enum opal_mpipl_tags tag, u64 *addr);
diff --git a/arch/powerpc/include/asm/secvar.h 
b/arch/powerpc/include/asm/secvar.h
new file mode 100644
index ..4cc35b58b986
--- /dev/null
+++ b/arch/powerpc/include/asm/secvar.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ *
+ * PowerPC secure variable operations.
+ */
+#ifndef SECVAR_OPS_H
+#define SECVAR_OPS_H
+
+#include 
+#include 
+
+extern const struct secvar_operations *secvar_ops;
+
+struct secvar_operations {
+   int (*get)(const char *key, uint64_t key_len, u8 *data,
+  uint64_t *data_size);
+   int (*get_next)(const char *key, uint64_t *key_len,
+   uint64_t keybufsize);
+   int (*set)(const char *key, uint64_t key_len, u8 *data,
+  uint64_t data_size);
+};
+
+#ifdef CONFIG_PPC_SECURE_BOOT
+
+extern void set_secvar_ops(const struct secvar_operations *ops);
+
+#else
+
+static inline void set_secvar_ops(const struct secvar_operations *ops) { }
+
+#endif
+
+#endif
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index e8eb2955b7d5..3cf26427334f 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -161,7 +161,7 @@ ifneq ($(CONFIG_PPC_POWERNV)$(CONFIG_PPC_SVM),)
 obj-y  += ucall.o
 endif
 
-obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o ima_arch.o
+obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o ima_arch.o secvar-ops.o
 
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
diff --git a/arch/powerpc/kernel/secvar-ops.c b/arch/powerpc/kernel/secvar-ops.c
new file mode 100644
index ..4cfa7dbd8850
--- /dev/null
+++ b/arch/powerpc/kernel/secvar-ops.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ *
+ * This file initializes secvar operations for PowerPC Secureboot
+ */
+
+#include 
+
+const struct secvar_operations *secvar_ops;
+
+void set_secvar_ops(const struct secvar_operations *ops)
+{
+   secvar_ops =

[PATCH v5 0/4] powerpc: expose secure variables to the kernel and userspace

2019-10-24 Thread Nayna Jain
In order to verify the OS kernel on PowerNV systems, secure boot requires
X.509 certificates trusted by the platform. These are stored in secure
variables controlled by OPAL, called OPAL secure variables. In order to
enable users to manage the keys, the secure variables need to be exposed
to userspace.

OPAL provides the runtime services for the kernel to be able to access the
secure variables[1]. This patchset defines the kernel interface for the
OPAL APIs. These APIs are used by the hooks, which load these variables
to the keyring and expose them to the userspace for reading/writing.

The previous version[2] of the patchset added support only for the sysfs
interface. This patch adds two more patches that involves loading of
the firmware trusted keys to the kernel keyring.

Overall, this patchset adds the following support:

* expose secure variables to the kernel via OPAL Runtime API interface
* expose secure variables to the userspace via kernel sysfs interface
* load kernel verification and revocation keys to .platform and
.blacklist keyring respectively.

The secure variables can be read/written using simple linux utilities
cat/hexdump.

For example:
Path to the secure variables is:
/sys/firmware/secvar/vars

Each secure variable is listed as directory. 
$ ls -l
total 0
drwxr-xr-x. 2 root root 0 Aug 20 21:20 db
drwxr-xr-x. 2 root root 0 Aug 20 21:20 KEK
drwxr-xr-x. 2 root root 0 Aug 20 21:20 PK

The attributes of each of the secure variables are(for example: PK):
[db]$ ls -l
total 0
-r--r--r--. 1 root root  4096 Oct  1 15:10 data
-r--r--r--. 1 root root 65536 Oct  1 15:10 size
--w---. 1 root root  4096 Oct  1 15:12 update

The "data" is used to read the existing variable value using hexdump. The
data is stored in ESL format.
The "update" is used to write a new value using cat. The update is
to be submitted as AUTH file.

[1] Depends on skiboot OPAL API changes which removes metadata from
the API. https://lists.ozlabs.org/pipermail/skiboot/2019-September/015203.html.
[2] https://lkml.org/lkml/2019/6/13/1644

Changelog:
v5:
* rebased to v5.4-rc3
* includes Oliver's feedbacks
  * changed OPAL API as platform driver
  * sysfs are made default enabled and dependent on PPC_SECURE_BOOT
  * fixed code specific changes in both OPAL API and sysfs
  * reading size of the "data" and "update" file from device-tree.  
  * fixed sysfs documentation to also reflect the data and update file
  size interpretation
  * This patchset is no more dependent on ima-arch/blacklist patchset

v4:
* rebased to v5.4-rc1 
* uses __BIN_ATTR_WO macro to create binary attribute as suggested by
  Greg
* removed email id from the file header
* renamed argument keysize to keybufsize in get_next() function
* updated default binary file sizes to 0, as firmware handles checking
against the maximum size
* fixed minor formatting issues in Patch 4/4
* added Greg's and Mimi's Reviewed-by and Ack-by

v3:
* includes Greg's feedbacks:
 * fixes in Patch 2/4
   * updates the Documentation.
   * fixes code feedbacks
* adds SYSFS Kconfig dependency for SECVAR_SYSFS
* fixes mixed tabs and spaces
* removes "name" attribute for each of the variable name based
directories
* fixes using __ATTR_RO() and __BIN_ATTR_RO() and statics and const
* fixes the racing issue by using kobj_type default groups. Also,
fixes the kobject leakage.
* removes extra print messages
  * updates patch description for Patch 3/4
  * removes file name from Patch 4/4 file header comment and removed
  def_bool y from the LOAD_PPC_KEYS Kconfig

* includes Oliver's feedbacks:
  * fixes Patch 1/2
   * moves OPAL API wrappers after opal_nx_proc_init(), fixed the
   naming, types and removed extern.
   * fixes spaces
   * renames get_variable() to get(), get_next_variable() to get_next()
   and set_variable() to set()
   * removed get_secvar_ops() and defined secvar_ops as global
   * fixes consts and statics
   * removes generic secvar_init() and defined platform specific
   opal_secar_init()
   * updates opal_secvar_supported() to check for secvar support even
   before checking the OPAL APIs support and also fixed the error codes.
   * addes function that converts OPAL return codes to linux errno
   * moves secvar check support in the opal_secvar_init() and defined its
   prototype in opal.h
  * fixes Patch 2/2
   * fixes static/const
   * defines macro for max name size
   * replaces OPAL error codes with linux errno and also updated error
   handling
   * moves secvar support check before creating sysfs kobjects in 
   secvar_sysfs_init()
   * fixes spaces  

v2:
* removes complete efi-sms from the sysfs implementation and is simplified
* includes Greg's and Oliver's feedbacks:
 * adds sysfs documentation
 * moves sysfs code to arch/powerpc
 * other code related feedbacks.
* adds two new patches to load keys to .platform and .blacklist keyring.
These patches are added to this series as th

[PATCH v9 8/8] powerpc/ima: update ima arch policy to check for blacklist

2019-10-23 Thread Nayna Jain
This patch updates the arch-specific policies for PowerNV system to make
sure that the binary hash is not blacklisted.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
---
 arch/powerpc/kernel/ima_arch.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index 0ef5956c9753..b9de0fb45bb9 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -23,9 +23,9 @@ bool arch_ima_get_secureboot(void)
  * is not enabled.
  */
 static const char *const secure_rules[] = {
-   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig",
+   "appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #ifndef CONFIG_MODULE_SIG_FORCE
-   "appraise func=MODULE_CHECK appraise_type=imasig|modsig",
+   "appraise func=MODULE_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #endif
NULL
 };
@@ -49,9 +49,9 @@ static const char *const trusted_rules[] = {
 static const char *const secure_and_trusted_rules[] = {
"measure func=KEXEC_KERNEL_CHECK template=ima-modsig",
"measure func=MODULE_CHECK template=ima-modsig",
-   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig",
+   "appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #ifndef CONFIG_MODULE_SIG_FORCE
-   "appraise func=MODULE_CHECK appraise_type=imasig|modsig",
+   "appraise func=MODULE_CHECK appraise_flag=check_blacklist 
appraise_type=imasig|modsig",
 #endif
NULL
 };
-- 
2.20.1



[PATCH v9 7/8] ima: check against blacklisted hashes for files with modsig

2019-10-23 Thread Nayna Jain
Asymmetric private keys are used to sign multiple files. The kernel
currently support checking against blacklisted keys. However, if the
public key is blacklisted, any file signed by the blacklisted key will
automatically fail signature verification. We might not want to blacklist
all the files signed by a particular key, but just a single file.
Blacklisting the public key is not fine enough granularity.

This patch adds support for checking against the blacklisted hash of the
file based on the IMA policy. The blacklisted hash is the file hash
without the appended signature. Defined is a new policy option
"appraise_flag=check_blacklist".

In addition to the blacklisted binary hashes stored in the firmware "dbx"
variable, the Linux kernel may be configured to load blacklisted binary
hashes onto the .blacklist keyring as well.  The following example shows
how to blacklist a kernel module.

$ sha256sum kernel/kheaders.ko
77fa889b35a05338ec52e51591c1b89d4c8d1c99a21251d7c22b1a8642a6bad3  kern
el/kheaders.ko

$ grep BLACKLIST .config
# CONFIG_IMA_BLACKLIST_KEYRING is not set
CONFIG_SYSTEM_BLACKLIST_KEYRING=y
CONFIG_SYSTEM_BLACKLIST_HASH_LIST="blacklist-hash-list"

$ cat certs/blacklist-hash-list
"bin:77fa889b35a05338ec52e51591c1b89d4c8d1c99a21251d7c22b1a8642a6bad3"

Update the IMA custom measurement and appraisal policy rules
(/etc/ima-policy):

measure func=MODULE_CHECK template=ima-modsig
appraise func=MODULE_CHECK appraise_flag=check_blacklist
appraise_type=imasig|modsig

After building, installing, and rebooting the kernel:

# keyctl show %keyring:.blacklist | grep 77fa889b35a05
 545660333 ---lswrv  0 0   \_ blacklist:
bin:77fa889b35a05338ec52e51591c1b89d4c8d1c99a21251d7c22b1a8642a6bad3

# cat /sys/kernel/security/ima/policy | grep MODULE_CHECK
measure func=MODULE_CHECK template=ima-modsig
appraise func=MODULE_CHECK appraise_flag=check_blacklist
appraise_type=imasig|modsig

# modprobe kheaders
modprobe: ERROR: could not insert 'kheaders': Permission denied

# cat /sys/kernel/security/ima/ascii_runtime_measurements
10 0c9834db5a0182c1fb0cdc5d3adcf11a11fd83dd ima-sig
sha256:3bc6ed4f0b4d6e31bc1dbc9ef844605abc7afdc6d81a57d77a1ec9407997c40
2 /usr/lib/modules/5.4.0-rc3+/kernel/kernel/kheaders.ko

10 82aad2bcc3fa8ed94762356b5c14838f3bcfa6a0 ima-modsig
sha256:3bc6ed4f0b4d6e31bc1dbc9ef844605abc7afdc6d81a57d77a1ec9407997c40
2 /usr/lib/modules/5.4.0rc3+/kernel/kernel/kheaders.ko  sha256:77fa889b3
5a05338ec52e51591c1b89d4c8d1c99a21251d7c22b1a8642a6bad3
3082029a06092a864886f70d010702a082028b30820287020101310d300b0609608648
016503040201300b06092a864886f70d01070131820264

10 25b72217cc1152b44b134ce2cd68f12dfb71acb3 ima-buf
sha256:8b58427fedcf8f4b20bc8dc007f2e232bf7285d7b93a66476321f9c2a3aa132
b blacklisted-hash
77fa889b35a05338ec52e51591c1b89d4c8d1c99a21251d7c22b1a8642a6bad3

Signed-off-by: Nayna Jain 
---
 Documentation/ABI/testing/ima_policy  |  4 
 security/integrity/ima/ima.h  |  8 +++
 security/integrity/ima/ima_appraise.c | 33 +++
 security/integrity/ima/ima_main.c | 12 ++
 security/integrity/ima/ima_policy.c   | 12 --
 security/integrity/integrity.h|  1 +
 6 files changed, 64 insertions(+), 6 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy 
b/Documentation/ABI/testing/ima_policy
index 29ebe9afdac4..29aaedf33246 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -25,6 +25,7 @@ Description:
lsm:[[subj_user=] [subj_role=] [subj_type=]
 [obj_user=] [obj_role=] [obj_type=]]
option: [[appraise_type=]] [template=] [permit_directio]
+   [appraise_flag=]
base:   func:= 
[BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK]
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
@@ -38,6 +39,9 @@ Description:
fowner:= decimal value
lsm:are LSM specific
option: appraise_type:= [imasig] [imasig|modsig]
+   appraise_flag:= [check_blacklist]
+   Currently, blacklist check is only for files signed 
with appended
+   signature.
template:= name of a defined IMA template type
(eg, ima-ng). Only valid when action is "measure".
pcr:= decimal value
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index a65772ffa427..df4ca482fb53 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -256,6 +256,8 @@ int ima_policy_show(struct seq_file *m, void *v);
 #define IMA_APPRAISE_KEXEC 0x40
 
 #ifdef CONFIG_IMA_APPRAISE
+int ima_check_blacklist(struct integrity_iint_cache *iint,
+

[PATCH v9 6/8] certs: add wrapper function to check blacklisted binary hash

2019-10-23 Thread Nayna Jain
The -EKEYREJECTED error returned by existing is_hash_blacklisted() is
misleading when called for checking against blacklisted hash of a
binary.

This patch adds a wrapper function is_binary_blacklisted() to return
-EPERM error if binary is blacklisted.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
---
 certs/blacklist.c | 9 +
 include/keys/system_keyring.h | 6 ++
 2 files changed, 15 insertions(+)

diff --git a/certs/blacklist.c b/certs/blacklist.c
index ec00bf337eb6..6514f9ebc943 100644
--- a/certs/blacklist.c
+++ b/certs/blacklist.c
@@ -135,6 +135,15 @@ int is_hash_blacklisted(const u8 *hash, size_t hash_len, 
const char *type)
 }
 EXPORT_SYMBOL_GPL(is_hash_blacklisted);
 
+int is_binary_blacklisted(const u8 *hash, size_t hash_len)
+{
+   if (is_hash_blacklisted(hash, hash_len, "bin") == -EKEYREJECTED)
+   return -EPERM;
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(is_binary_blacklisted);
+
 /*
  * Initialise the blacklist
  */
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index c1a96fdf598b..fb8b07daa9d1 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -35,12 +35,18 @@ extern int restrict_link_by_builtin_and_secondary_trusted(
 extern int mark_hash_blacklisted(const char *hash);
 extern int is_hash_blacklisted(const u8 *hash, size_t hash_len,
   const char *type);
+extern int is_binary_blacklisted(const u8 *hash, size_t hash_len);
 #else
 static inline int is_hash_blacklisted(const u8 *hash, size_t hash_len,
  const char *type)
 {
return 0;
 }
+
+static inline int is_binary_blacklisted(const u8 *hash, size_t hash_len)
+{
+   return 0;
+}
 #endif
 
 #ifdef CONFIG_IMA_BLACKLIST_KEYRING
-- 
2.20.1



[PATCH v9 5/8] ima: make process_buffer_measurement() generic

2019-10-23 Thread Nayna Jain
process_buffer_measurement() is limited to measuring the kexec boot
command line. This patch makes process_buffer_measurement() more
generic, allowing it to measure other types of buffer data (e.g.
blacklisted binary hashes or key hashes).

process_buffer_measurement() may be called directly from an IMA
hook or as an auxiliary measurement record. In both cases the buffer
measurement is based on policy. This patch modifies the function to
conditionally retrieve the policy defined PCR and template for the IMA
hook case.

Signed-off-by: Nayna Jain 
---
 security/integrity/ima/ima.h  |  3 ++
 security/integrity/ima/ima_main.c | 51 ---
 2 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 3689081aaf38..a65772ffa427 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -217,6 +217,9 @@ void ima_store_measurement(struct integrity_iint_cache 
*iint, struct file *file,
   struct evm_ima_xattr_data *xattr_value,
   int xattr_len, const struct modsig *modsig, int pcr,
   struct ima_template_desc *template_desc);
+void process_buffer_measurement(const void *buf, int size,
+   const char *eventname, enum ima_hooks func,
+   int pcr);
 void ima_audit_measurement(struct integrity_iint_cache *iint,
   const unsigned char *filename);
 int ima_alloc_init_template(struct ima_event_data *event_data,
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index 60027c643ecd..fe0b704ffdeb 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -626,14 +626,14 @@ int ima_load_data(enum kernel_load_data_id id)
  * @buf: pointer to the buffer that needs to be added to the log.
  * @size: size of buffer(in bytes).
  * @eventname: event name to be used for the buffer entry.
- * @cred: a pointer to a credentials structure for user validation.
- * @secid: the secid of the task to be validated.
+ * @func: IMA hook
+ * @pcr: pcr to extend the measurement
  *
  * Based on policy, the buffer is measured into the ima log.
  */
-static void process_buffer_measurement(const void *buf, int size,
-  const char *eventname,
-  const struct cred *cred, u32 secid)
+void process_buffer_measurement(const void *buf, int size,
+   const char *eventname, enum ima_hooks func,
+   int pcr)
 {
int ret = 0;
struct ima_template_entry *entry = NULL;
@@ -642,19 +642,38 @@ static void process_buffer_measurement(const void *buf, 
int size,
.filename = eventname,
.buf = buf,
.buf_len = size};
-   struct ima_template_desc *template_desc = NULL;
+   struct ima_template_desc *template = NULL;
struct {
struct ima_digest_data hdr;
char digest[IMA_MAX_DIGEST_SIZE];
} hash = {};
int violation = 0;
-   int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
int action = 0;
+   u32 secid;
 
-   action = ima_get_action(NULL, cred, secid, 0, KEXEC_CMDLINE, ,
-   _desc);
-   if (!(action & IMA_MEASURE))
-   return;
+   if (func) {
+   security_task_getsecid(current, );
+   action = ima_get_action(NULL, current_cred(), secid, 0, func,
+   , );
+   if (!(action & IMA_MEASURE))
+   return;
+   }
+
+   if (!pcr)
+   pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+
+   if (!template) {
+   template = lookup_template_desc("ima-buf");
+   ret = template_desc_init_fields(template->fmt,
+   &(template->fields),
+   &(template->num_fields));
+   if (ret < 0) {
+   pr_err("template %s init failed, result: %d\n",
+  (strlen(template->name) ?
+   template->name : template->fmt), ret);
+   return;
+   }
+   }
 
iint.ima_hash = 
iint.ima_hash->algo = ima_hash_algo;
@@ -664,7 +683,7 @@ static void process_buffer_measurement(const void *buf, int 
size,
if (ret < 0)
goto out;
 
-   ret = ima_alloc_init_template(_data, , template_desc);
+   ret = ima_alloc_init_template(_data, , template);
if (ret < 0)
goto out;
 
@@ -686,13 +705,9 @@ static void process_buffer_measurement(const void *buf,

[PATCH v9 4/8] powerpc/ima: define trusted boot policy

2019-10-23 Thread Nayna Jain
This patch defines an arch-specific trusted boot only policy and a
combined secure and trusted boot policy.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/kernel/ima_arch.c | 33 -
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index d88913dc0da7..0ef5956c9753 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -30,6 +30,32 @@ static const char *const secure_rules[] = {
NULL
 };
 
+/*
+ * The "trusted_rules" are enabled only on "trustedboot" enabled systems.
+ * These rules add the kexec kernel image and kernel modules file hashes to
+ * the IMA measurement list.
+ */
+static const char *const trusted_rules[] = {
+   "measure func=KEXEC_KERNEL_CHECK",
+   "measure func=MODULE_CHECK",
+   NULL
+};
+
+/*
+ * The "secure_and_trusted_rules" contains rules for both the secure boot and
+ * trusted boot. The "template=ima-modsig" option includes the appended
+ * signature, when available, in the IMA measurement list.
+ */
+static const char *const secure_and_trusted_rules[] = {
+   "measure func=KEXEC_KERNEL_CHECK template=ima-modsig",
+   "measure func=MODULE_CHECK template=ima-modsig",
+   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig",
+#ifndef CONFIG_MODULE_SIG_FORCE
+   "appraise func=MODULE_CHECK appraise_type=imasig|modsig",
+#endif
+   NULL
+};
+
 /*
  * Returns the relevant IMA arch-specific policies based on the system secure
  * boot state.
@@ -37,7 +63,12 @@ static const char *const secure_rules[] = {
 const char *const *arch_get_ima_policy(void)
 {
if (is_ppc_secureboot_enabled())
-   return secure_rules;
+   if (is_ppc_trustedboot_enabled())
+   return secure_and_trusted_rules;
+   else
+   return secure_rules;
+   else if (is_ppc_trustedboot_enabled())
+   return trusted_rules;
 
return NULL;
 }
-- 
2.20.1



[PATCH v9 3/8] powerpc: detect the trusted boot state of the system

2019-10-23 Thread Nayna Jain
While secure boot permits only properly verified signed kernels to be
booted, trusted boot calculates the file hash of the kernel image and
stores the measurement prior to boot, that can be subsequently compared
against good known values via attestation services.

This patch reads the trusted boot state of a PowerNV system. The state
is used to conditionally enable additional measurement rules in the IMA
arch-specific policies.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/secure_boot.h |  6 ++
 arch/powerpc/kernel/secure_boot.c  | 26 ++
 2 files changed, 32 insertions(+)

diff --git a/arch/powerpc/include/asm/secure_boot.h 
b/arch/powerpc/include/asm/secure_boot.h
index 07d0fe0ca81f..a2ff556916c6 100644
--- a/arch/powerpc/include/asm/secure_boot.h
+++ b/arch/powerpc/include/asm/secure_boot.h
@@ -11,6 +11,7 @@
 #ifdef CONFIG_PPC_SECURE_BOOT
 
 bool is_ppc_secureboot_enabled(void);
+bool is_ppc_trustedboot_enabled(void);
 
 #else
 
@@ -19,5 +20,10 @@ static inline bool is_ppc_secureboot_enabled(void)
return false;
 }
 
+static inline bool is_ppc_trustedboot_enabled(void)
+{
+   return false;
+}
+
 #endif
 #endif
diff --git a/arch/powerpc/kernel/secure_boot.c 
b/arch/powerpc/kernel/secure_boot.c
index 63dc82c50862..a6a5f17ede03 100644
--- a/arch/powerpc/kernel/secure_boot.c
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -7,6 +7,17 @@
 #include 
 #include 
 
+static struct device_node *get_ppc_fw_sb_node(void)
+{
+   static const struct of_device_id ids[] = {
+   { .compatible = "ibm,secureboot-v1", },
+   { .compatible = "ibm,secureboot-v2", },
+   {},
+   };
+
+   return of_find_matching_node(NULL, ids);
+}
+
 bool is_ppc_secureboot_enabled(void)
 {
struct device_node *node;
@@ -30,3 +41,18 @@ bool is_ppc_secureboot_enabled(void)
pr_info("Secure boot mode %s\n", enabled ? "enabled" : "disabled");
return enabled;
 }
+
+bool is_ppc_trustedboot_enabled(void)
+{
+   struct device_node *node;
+   bool enabled = false;
+
+   node = get_ppc_fw_sb_node();
+   enabled = of_property_read_bool(node, "trusted-enabled");
+
+   of_node_put(node);
+
+   pr_info("Trusted boot mode %s\n", enabled ? "enabled" : "disabled");
+
+   return enabled;
+}
-- 
2.20.1



[PATCH v9 2/8] powerpc/ima: add support to initialize ima policy rules

2019-10-23 Thread Nayna Jain
PowerNV system use a Linux-based bootloader, which relies on the IMA
subsystem to enforce different secure boot modes. Since the verification
policy may differ based on the secure boot mode of the system, the
policies must be defined at runtime.

This patch implements arch-specific support to define IMA policy
rules based on the runtime secure boot mode of the system.

This patch provides arch-specific IMA policies if PPC_SECURE_BOOT
config is enabled.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/Kconfig   |  1 +
 arch/powerpc/kernel/Makefile   |  2 +-
 arch/powerpc/kernel/ima_arch.c | 43 ++
 include/linux/ima.h|  3 ++-
 4 files changed, 47 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/kernel/ima_arch.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 56ea0019b616..c795039bdc73 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -938,6 +938,7 @@ config PPC_SECURE_BOOT
prompt "Enable secure boot support"
bool
depends on PPC_POWERNV
+   depends on IMA_ARCH_POLICY
help
  Systems with firmware secure boot enabled need to define security
  policies to extend secure boot to the OS. This config allows a user
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index e2a54fa240ac..e8eb2955b7d5 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -161,7 +161,7 @@ ifneq ($(CONFIG_PPC_POWERNV)$(CONFIG_PPC_SVM),)
 obj-y  += ucall.o
 endif
 
-obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o
+obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o ima_arch.o
 
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
new file mode 100644
index ..d88913dc0da7
--- /dev/null
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ */
+
+#include 
+#include 
+
+bool arch_ima_get_secureboot(void)
+{
+   return is_ppc_secureboot_enabled();
+}
+
+/*
+ * The "secure_rules" are enabled only on "secureboot" enabled systems.
+ * These rules verify the file signatures against known good values.
+ * The "appraise_type=imasig|modsig" option allows the known good signature
+ * to be stored as an xattr or as an appended signature.
+ *
+ * To avoid duplicate signature verification as much as possible, the IMA
+ * policy rule for module appraisal is added only if CONFIG_MODULE_SIG_FORCE
+ * is not enabled.
+ */
+static const char *const secure_rules[] = {
+   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig",
+#ifndef CONFIG_MODULE_SIG_FORCE
+   "appraise func=MODULE_CHECK appraise_type=imasig|modsig",
+#endif
+   NULL
+};
+
+/*
+ * Returns the relevant IMA arch-specific policies based on the system secure
+ * boot state.
+ */
+const char *const *arch_get_ima_policy(void)
+{
+   if (is_ppc_secureboot_enabled())
+   return secure_rules;
+
+   return NULL;
+}
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 1c37f17f7203..6d904754d858 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -29,7 +29,8 @@ extern void ima_kexec_cmdline(const void *buf, int size);
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
 
-#if (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390)
+#if (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390) \
+   || defined(CONFIG_PPC_SECURE_BOOT)
 extern bool arch_ima_get_secureboot(void);
 extern const char * const *arch_get_ima_policy(void);
 #else
-- 
2.20.1



[PATCH v9 1/8] powerpc: detect the secure boot mode of the system

2019-10-23 Thread Nayna Jain
This patch defines a function to detect the secure boot state of a
PowerNV system.

The PPC_SECURE_BOOT config represents the base enablement of secure boot
for powerpc.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/Kconfig   | 10 
 arch/powerpc/include/asm/secure_boot.h | 23 ++
 arch/powerpc/kernel/Makefile   |  2 ++
 arch/powerpc/kernel/secure_boot.c  | 32 ++
 4 files changed, 67 insertions(+)
 create mode 100644 arch/powerpc/include/asm/secure_boot.h
 create mode 100644 arch/powerpc/kernel/secure_boot.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 3e56c9c2f16e..56ea0019b616 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -934,6 +934,16 @@ config PPC_MEM_KEYS
 
  If unsure, say y.
 
+config PPC_SECURE_BOOT
+   prompt "Enable secure boot support"
+   bool
+   depends on PPC_POWERNV
+   help
+ Systems with firmware secure boot enabled need to define security
+ policies to extend secure boot to the OS. This config allows a user
+ to enable OS secure boot on systems that have firmware support for
+ it. If in doubt say N.
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/include/asm/secure_boot.h 
b/arch/powerpc/include/asm/secure_boot.h
new file mode 100644
index ..07d0fe0ca81f
--- /dev/null
+++ b/arch/powerpc/include/asm/secure_boot.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Secure boot definitions
+ *
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ */
+#ifndef _ASM_POWER_SECURE_BOOT_H
+#define _ASM_POWER_SECURE_BOOT_H
+
+#ifdef CONFIG_PPC_SECURE_BOOT
+
+bool is_ppc_secureboot_enabled(void);
+
+#else
+
+static inline bool is_ppc_secureboot_enabled(void)
+{
+   return false;
+}
+
+#endif
+#endif
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index a7ca8fe62368..e2a54fa240ac 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -161,6 +161,8 @@ ifneq ($(CONFIG_PPC_POWERNV)$(CONFIG_PPC_SVM),)
 obj-y  += ucall.o
 endif
 
+obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o
+
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
 KCOV_INSTRUMENT_prom_init.o := n
diff --git a/arch/powerpc/kernel/secure_boot.c 
b/arch/powerpc/kernel/secure_boot.c
new file mode 100644
index ..63dc82c50862
--- /dev/null
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ */
+#include 
+#include 
+#include 
+
+bool is_ppc_secureboot_enabled(void)
+{
+   struct device_node *node;
+   bool enabled = false;
+
+   node = of_find_compatible_node(NULL, NULL, "ibm,secvar-v1");
+   if (!of_device_is_available(node)) {
+   pr_err("Cannot find secure variable node in device tree; 
failing to secure state\n");
+   goto out;
+   }
+
+   /*
+* secureboot is enabled if os-secure-enforcing property exists,
+* else disabled.
+*/
+   enabled = of_property_read_bool(node, "os-secure-enforcing");
+
+out:
+   of_node_put(node);
+
+   pr_info("Secure boot mode %s\n", enabled ? "enabled" : "disabled");
+   return enabled;
+}
-- 
2.20.1



[PATCH v9 0/8] powerpc: Enabling IMA arch specific secure boot policies

2019-10-23 Thread Nayna Jain
This patchset extends the previous version[1] by adding support for
checking against a blacklist of binary hashes.

The IMA subsystem supports custom, built-in, arch-specific policies to
define the files to be measured and appraised. These policies are honored
based on priority, where arch-specific policy is the highest and custom
is the lowest.

PowerNV system uses a Linux-based bootloader to kexec the OS. The
bootloader kernel relies on IMA for signature verification of the OS
kernel before doing the kexec. This patchset adds support for powerpc
arch-specific IMA policies that are conditionally defined based on a
system's secure boot and trusted boot states. The OS secure boot and
trusted boot states are determined via device-tree properties.

The verification needs to be performed only for binaries that are not
blacklisted. The kernel currently only checks against the blacklist of
keys. However, doing so results in blacklisting all the binaries that
are signed by the same key. In order to prevent just one particular
binary from being loaded, it must be checked against a blacklist of
binary hashes. This patchset also adds support to IMA for checking
against a hash blacklist for files. signed by appended signature.

[1] http://patchwork.ozlabs.org/cover/1149262/ 

Changelog:

v9:
* Includes feedbacks from Michael
  * fix the missing of_node_put()
* Includes Mimi's feedbacks
  * fix the policy show() function to display check_blacklist
  * fix the other comment related and patch description
  * add the example of blacklist in the Patch 7/8
Note: Patch 7/8 is giving errors when checkpatch.pl is run because
of the format of showing measurement record as part of the example. I am
not very sure if that can be fixed as we need to represent the
measurements as is.

v8:
* Updates the Patch Description as per Michael's and Mimi's feedback
* Includes feedbacks from Michael for the device tree and policies
  * removes the arch-policy hack by defining three arrays.
  * fixes related to device-tree calls 
  * other code specific feedbacks
* Includes feedbacks from Mimi on the blacklist
  * generic blacklist function is modified than previous version
  * other coding fixes

v7:
* Removes patch related to dt-bindings as per input from Rob Herring. 
* fixes Patch 1/8 to use new device-tree updates as per Oliver
  feedback to device-tree documentation in skiboot mailing list.
(https://lists.ozlabs.org/pipermail/skiboot/2019-September/015329.html)
* Includes feedbacks from Mimi, Thiago
  * moves function get_powerpc_fw_sb_node() from Patch 1 to Patch 3 
  * fixes Patch 2/8 to use CONFIG_MODULE_SIG_FORCE.
  * updates Patch description in Patch 5/8
  * adds a new patch to add wrapper is_binary_blacklisted()
  * removes the patch that deprecated permit_directio

v6:
* includes feedbacks from Michael Ellerman on the patchset v5
  * removed email ids from comments
  * add the doc for the device-tree
  * renames the secboot.c to secure_boot.c and secboot.h to secure_boot.h
  * other code specific fixes
* split the patches to differentiate between secureboot and trustedboot
state of the system
* adds the patches to support the blacklisting of the binary hash.

v5:
* secureboot state is now read via device tree entry rather than OPAL
secure variables
* ima arch policies are updated to use policy based template for
measurement rules

v4:
* Fixed the build issue as reported by Satheesh Rajendran.

v3:
* OPAL APIs in Patch 1 are updated to provide generic interface based on
key/keylen. This patchset updates kernel OPAL APIs to be compatible with
generic interface.
* Patch 2 is cleaned up to use new OPAL APIs.
* Since OPAL can support different types of backend which can vary in the
variable interpretation, the Patch 2 is updated to add a check for the
backend version
* OPAL API now expects consumer to first check the supported backend version
before calling other secvar OPAL APIs. This check is now added in patch 2.
* IMA policies in Patch 3 is updated to specify appended signature and
per policy template.
* The patches now are free of any EFIisms.

v2:

* Removed Patch 1: powerpc/include: Override unneeded early ioremap
functions
* Updated Subject line and patch description of the Patch 1 of this series
* Removed dependency of OPAL_SECVAR on EFI, CPU_BIG_ENDIAN and UCS2_STRING
* Changed OPAL APIs from static to non-static. Added opal-secvar.h for the
same
* Removed EFI hooks from opal_secvar.c
* Removed opal_secvar_get_next(), opal_secvar_enqueue() and
opal_query_variable_info() function
* get_powerpc_sb_mode() in secboot.c now directly calls OPAL Runtime API
rather than via EFI hooks.
* Fixed log messages in get_powerpc_sb_mode() function.
* Added dependency for PPC_SECURE_BOOT on configs PPC64 and OPAL_SECVAR
* Replaced obj-$(CONFIG_IMA) with obj-$(CONFIG_PPC_SECURE_BOOT) in
arch/powerpc/kernel/Makefile

Nayna Jain (8):
  powerpc: detect the secure boot mode of the system
  powerpc/ima: add support to initialize ima policy rules

[PATCH v8 2/8] powerpc/ima: add support to initialize ima policy rules

2019-10-19 Thread Nayna Jain
PowerNV system use a Linux-based bootloader, which relies on the IMA
subsystem to enforce different secure boot modes. Since the verification
policy may differ based on the secure boot mode of the system, the
policies must be defined at runtime.

This patch implements arch-specific support to define IMA policy
rules based on the runtime secure boot mode of the system.

This patch provides arch-specific IMA policies if PPC_SECURE_BOOT
config is enabled.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/Kconfig   |  1 +
 arch/powerpc/kernel/Makefile   |  2 +-
 arch/powerpc/kernel/ima_arch.c | 39 ++
 include/linux/ima.h|  3 ++-
 4 files changed, 43 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/kernel/ima_arch.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 56ea0019b616..c795039bdc73 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -938,6 +938,7 @@ config PPC_SECURE_BOOT
prompt "Enable secure boot support"
bool
depends on PPC_POWERNV
+   depends on IMA_ARCH_POLICY
help
  Systems with firmware secure boot enabled need to define security
  policies to extend secure boot to the OS. This config allows a user
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index e2a54fa240ac..e8eb2955b7d5 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -161,7 +161,7 @@ ifneq ($(CONFIG_PPC_POWERNV)$(CONFIG_PPC_SVM),)
 obj-y  += ucall.o
 endif
 
-obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o
+obj-$(CONFIG_PPC_SECURE_BOOT)  += secure_boot.o ima_arch.o
 
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
new file mode 100644
index ..65d82ee74ea4
--- /dev/null
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ */
+
+#include 
+#include 
+
+bool arch_ima_get_secureboot(void)
+{
+   return is_ppc_secureboot_enabled();
+}
+
+/*
+ * The "secure_rules" are enabled only on "secureboot" enabled systems.
+ * These rules verify the file signatures against known good values.
+ * The "appraise_type=imasig|modsig" option allows the known good signature
+ * to be stored as an xattr or as an appended signature.
+ */
+static const char *const secure_rules[] = {
+   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig",
+#ifndef CONFIG_MODULE_SIG_FORCE
+   "appraise func=MODULE_CHECK appraise_type=imasig|modsig",
+#endif
+   NULL
+};
+
+/*
+ * Returns the relevant IMA arch-specific policies based on the system secure
+ * boot state.
+ */
+const char *const *arch_get_ima_policy(void)
+{
+   if (is_ppc_secureboot_enabled())
+   return secure_rules;
+
+   return NULL;
+}
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 1c37f17f7203..6d904754d858 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -29,7 +29,8 @@ extern void ima_kexec_cmdline(const void *buf, int size);
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
 
-#if (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390)
+#if (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390) \
+   || defined(CONFIG_PPC_SECURE_BOOT)
 extern bool arch_ima_get_secureboot(void);
 extern const char * const *arch_get_ima_policy(void);
 #else
-- 
2.20.1



  1   2   >