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

2019-10-19 Thread Nayna Jain
While secure boot permits only properly verified signed kernels to be
booted, trusted boot takes a measurement of the kernel image 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  | 24 
 2 files changed, 30 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 99bba7915629..9753470ab08a 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;
@@ -28,3 +39,16 @@ 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");
+
+   pr_info("Trusted boot mode %s\n", enabled ? "enabled" : "disabled");
+
+   return enabled;
+}
-- 
2.20.1



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

2019-10-19 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).

This patch modifies the function to conditionally retrieve the policy
defined pcr and template based on the func.

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, 
int size,
  */
 void ima_kexec_cmdline(const void *buf, int size)
 {
-   u32 secid;
-
-   if (buf && size != 0) {
-

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

2019-10-19 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  | 30 ++
 4 files changed, 65 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 ..99bba7915629
--- /dev/null
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -0,0 +1,30 @@
+// 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:
+   pr_info("Secure boot mode %s\n", enabled ? "enabled" : "disabled");
+   return enabled;
+}
-- 
2.20.1



[PATCH v8 4/8] powerpc/ima: add measurement rules to ima arch specific policy

2019-10-19 Thread Nayna Jain
This patch adds the measurement rules to the arch specific policies on
trusted boot enabled systems.

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

diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index 65d82ee74ea4..710872ea8f35 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -26,6 +26,32 @@ static const char *const secure_rules[] = {
NULL
 };
 
+/*
+ * The "measure_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.
@@ -33,7 +59,13 @@ 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 v8 0/8] powerpc: Enabling IMA arch specific secure boot policies

2019-10-19 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:
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
  powerpc: detect the trusted boot state of the system
  powerpc/ima: add measurement rules to ima arch specific policy
  ima: make process_buffer_measurement() generic
  certs: add wrapper function to check blacklisted binary hash
  ima: check against blacklisted hashes for files with modsig
  powerpc/ima: update ima arch policy to check for blacklist

 Documentation/ABI/testing/ima_policy   |  1 +
 arch/powerpc/Kconfig   | 11 
 arch/powerpc/include/asm/secure_boot.h

[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



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

2019-10-19 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 710872ea8f35..98f3f8d9f9e4 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -19,9 +19,9 @@ bool arch_ima_get_secureboot(void)
  * 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",
+   "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
 };
@@ -45,9 +45,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 v8 7/8] ima: check against blacklisted hashes for files with modsig

2019-10-19 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".

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

diff --git a/Documentation/ABI/testing/ima_policy 
b/Documentation/ABI/testing/ima_policy
index 29ebe9afdac4..4c97afcc0f3c 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=[check_blacklist]]
base:   func:= 
[BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK]
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
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,
+   const struct modsig *modsig, int pcr);
 int ima_appraise_measurement(enum ima_hooks func,
 struct integrity_iint_cache *iint,
 struct file *file, const unsigned char *filename,
@@ -271,6 +273,12 @@ int ima_read_xattr(struct dentry *dentry,
   struct evm_ima_xattr_data **xattr_value);
 
 #else
+static inline int ima_check_blacklist(struct integrity_iint_cache *iint,
+ const struct modsig *modsig, int pcr)
+{
+   return 0;
+}
+
 static inline int ima_appraise_measurement(enum ima_hooks func,
   struct integrity_iint_cache *iint,
   struct file *file,
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 136ae4e0ee92..7a002b08dde8 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ima.h"
 
@@ -303,6 +304,36 @@ static int modsig_verify(enum ima_hooks func, const struct 
modsig *modsig,
return rc;
 }
 
+/*
+ * ima_blacklist_measurement - Checks whether the binary is blacklisted. If
+ * yes, then adds the hash of the blacklisted binary to the measurement list.
+ *
+ * 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);
+   }
+
+   return rc;
+}
+
 /*
  * ima_appraise_measurement - appraise file measurement
  *
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index fe0b704ffdeb..13a0d64580ef 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -335,10 +335,14 @@ static int process_measurement(struct file *file, const 
struct cred *cred,
  xattr_value, xattr_len, modsig, pcr,
  template_desc);
if (rc ==

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

2019-10-19 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 v7 3/8] powerpc: detect the trusted boot state of the system

2019-10-07 Thread Nayna Jain
PowerNV systems enables the IMA measurement rules only if the
trusted boot is enabled on the system.

This patch adds the function to detect if the system has trusted
boot enabled.

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

diff --git a/arch/powerpc/include/asm/secure_boot.h 
b/arch/powerpc/include/asm/secure_boot.h
index 23d2ef2f1f7b..ecd08515e301 100644
--- a/arch/powerpc/include/asm/secure_boot.h
+++ b/arch/powerpc/include/asm/secure_boot.h
@@ -12,6 +12,7 @@
 
 bool is_powerpc_os_secureboot_enabled(void);
 struct device_node *get_powerpc_os_sb_node(void);
+bool is_powerpc_trustedboot_enabled(void);
 
 #else
 
@@ -25,5 +26,10 @@ static inline struct device_node 
*get_powerpc_os_sb_node(void)
return NULL;
 }
 
+static inline bool is_powerpc_os_trustedboot_enabled(void)
+{
+   return false;
+}
+
 #endif
 #endif
diff --git a/arch/powerpc/kernel/secure_boot.c 
b/arch/powerpc/kernel/secure_boot.c
index 0488dbcab6b9..9d5ac1b39e46 100644
--- a/arch/powerpc/kernel/secure_boot.c
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -7,6 +7,27 @@
 #include 
 #include 
 
+static const char * const fwsecureboot_compat[] = {
+   "ibm,secureboot-v1",
+   "ibm,secureboot-v2",
+   NULL,
+};
+
+static struct device_node *get_powerpc_fw_sb_node(void)
+{
+   struct device_node *node;
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(fwsecureboot_compat); ++i) {
+   node = of_find_compatible_node(NULL, NULL,
+  fwsecureboot_compat[i]);
+   if (node)
+   return node;
+   }
+
+   return NULL;
+}
+
 struct device_node *get_powerpc_os_sb_node(void)
 {
return of_find_compatible_node(NULL, NULL, "ibm,secvar-v1");
@@ -40,3 +61,17 @@ bool is_powerpc_os_secureboot_enabled(void)
pr_info("secureboot mode disabled\n");
return false;
 }
+
+bool is_powerpc_trustedboot_enabled(void)
+{
+   struct device_node *node;
+
+   node = get_powerpc_fw_sb_node();
+   if (node && (of_find_property(node, "trusted-enabled", NULL))) {
+   pr_info("trustedboot mode enabled\n");
+   return true;
+   }
+
+   pr_info("trustedboot mode disabled\n");
+   return false;
+}
-- 
2.20.1



[PATCH v7 4/8] powerpc/ima: add measurement rules to ima arch specific policy

2019-10-07 Thread Nayna Jain
This patch adds the measurement rules to the arch specific policies on
trusted boot enabled systems.

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

diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index c22d82965eb4..88bfe4a1a9a5 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -12,8 +12,19 @@ bool arch_ima_get_secureboot(void)
return is_powerpc_os_secureboot_enabled();
 }
 
-/* Defines IMA appraise rules for secureboot */
+/*
+ * The "arch_rules" contains both the securebot and trustedboot rules for 
adding
+ * the kexec kernel image and kernel modules file hashes to the IMA measurement
+ * list and verifying the file signatures against known good values.
+ *
+ * The "appraise_type=imasig|modsig" option allows the good signature to be
+ * stored as an xattr or as an appended signature. The "template=ima-modsig"
+ * option includes the appended signature, when available, in the IMA
+ * measurement list.
+ */
 static const char *const arch_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",
 #if !IS_ENABLED(CONFIG_MODULE_SIG_FORCE)
"appraise func=MODULE_CHECK appraise_type=imasig|modsig",
@@ -22,12 +33,40 @@ static const char *const arch_rules[] = {
 };
 
 /*
- * Returns the relevant IMA arch policies based on the system secureboot state.
+ * The "measure_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 measure_rules[] = {
+   "measure func=KEXEC_KERNEL_CHECK",
+   "measure func=MODULE_CHECK",
+   NULL
+};
+
+/*
+ * Returns the relevant IMA arch policies based on the system secureboot
+ * and trustedboot state.
  */
 const char *const *arch_get_ima_policy(void)
 {
-   if (is_powerpc_os_secureboot_enabled())
+   const char *const *rules;
+   int offset = 0;
+
+   for (rules = arch_rules; *rules != NULL; rules++) {
+   if (strncmp(*rules, "appraise", 8) == 0)
+   break;
+   offset++;
+   }
+
+   if (is_powerpc_os_secureboot_enabled()
+   && is_powerpc_trustedboot_enabled())
return arch_rules;
 
+   if (is_powerpc_os_secureboot_enabled())
+   return arch_rules + offset;
+
+   if (is_powerpc_trustedboot_enabled())
+   return measure_rules;
+
return NULL;
 }
-- 
2.20.1



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

2019-10-07 Thread Nayna Jain
This patch updates the arch specific policies for PowernV systems
to add check against blacklisted binary hashes before doing the
verification.

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

diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index 88bfe4a1a9a5..4fa41537b846 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -25,9 +25,9 @@ bool arch_ima_get_secureboot(void)
 static const char *const arch_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",
 #if !IS_ENABLED(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 v7 5/8] ima: make process_buffer_measurement() generic

2019-10-07 Thread Nayna Jain
An additional measurement record is needed to indicate the blacklisted
binary. The record will measure the blacklisted binary hash.

This patch makes the function process_buffer_measurement() generic to be
called by the blacklisting function. It modifies the function to handle
more than just the KEXEC_CMDLINE.

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

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 3689081aaf38..ed86c1f70d7f 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, int pcr,
+   struct ima_template_desc *template_desc);
 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..77115e884496 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.
+ * @pcr: pcr to extend the measurement
+ * @template_desc: template description
  *
  * 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, int pcr,
+   struct ima_template_desc *template_desc)
 {
int ret = 0;
struct ima_template_entry *entry = NULL;
@@ -642,19 +642,11 @@ 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 {
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;
-
-   action = ima_get_action(NULL, cred, secid, 0, KEXEC_CMDLINE, ,
-   _desc);
-   if (!(action & IMA_MEASURE))
-   return;
 
iint.ima_hash = 
iint.ima_hash->algo = ima_hash_algo;
@@ -686,12 +678,19 @@ static void process_buffer_measurement(const void *buf, 
int size,
  */
 void ima_kexec_cmdline(const void *buf, int size)
 {
+   int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+   struct ima_template_desc *template_desc = NULL;
+   int action;
u32 secid;
 
if (buf && size != 0) {
security_task_getsecid(current, );
-   process_buffer_measurement(buf, size, "kexec-cmdline",
-  current_cred(), secid);
+   action = ima_get_action(NULL, current_cred(), secid, 0,
+   KEXEC_CMDLINE, , _desc);
+   if (!(action & IMA_MEASURE))
+   return;
+   process_buffer_measurement(buf, size, "kexec-cmdline", pcr,
+  template_desc);
}
 }
 
-- 
2.20.1



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

2019-10-07 Thread Nayna Jain
PowerNV systems uses kernel based bootloader, thus its secure boot
implementation uses kernel IMA security subsystem to verify the kernel
before kexec. Since the verification policy might differ based on the
secure boot mode of the system, the policies are defined at runtime.

This patch implements the arch-specific support to define the 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   |  2 ++
 arch/powerpc/kernel/Makefile   |  2 +-
 arch/powerpc/kernel/ima_arch.c | 33 +
 include/linux/ima.h|  3 ++-
 4 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/kernel/ima_arch.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index b4a221886fcf..deb19ec6ba3d 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -938,6 +938,8 @@ config PPC_SECURE_BOOT
prompt "Enable secure boot support"
bool
depends on PPC_POWERNV
+   depends on IMA
+   depends on IMA_ARCH_POLICY
help
  Systems with firmware secure boot enabled needs to define security
  policies to extend secure boot to the OS. This config allows 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 ..c22d82965eb4
--- /dev/null
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ */
+
+#include 
+#include 
+
+bool arch_ima_get_secureboot(void)
+{
+   return is_powerpc_os_secureboot_enabled();
+}
+
+/* Defines IMA appraise rules for secureboot */
+static const char *const arch_rules[] = {
+   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig",
+#if !IS_ENABLED(CONFIG_MODULE_SIG_FORCE)
+   "appraise func=MODULE_CHECK appraise_type=imasig|modsig",
+#endif
+   NULL
+};
+
+/*
+ * Returns the relevant IMA arch policies based on the system secureboot state.
+ */
+const char *const *arch_get_ima_policy(void)
+{
+   if (is_powerpc_os_secureboot_enabled())
+   return arch_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 v7 7/8] ima: check against blacklisted hashes for files with modsig

2019-10-07 Thread Nayna Jain
Asymmetric private keys are used to sign multiple files. The kernel
currently support checking against the 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 blacklisting binaries with appended signatures,
based on the IMA policy.  Defined is a new policy option
"appraise_flag=check_blacklist".

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

diff --git a/Documentation/ABI/testing/ima_policy 
b/Documentation/ABI/testing/ima_policy
index 29ebe9afdac4..4c97afcc0f3c 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=[check_blacklist]]
base:   func:= 
[BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK]
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index ed86c1f70d7f..63e20ccc91ce 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,
+   const struct modsig *modsig, int action, int pcr);
 int ima_appraise_measurement(enum ima_hooks func,
 struct integrity_iint_cache *iint,
 struct file *file, const unsigned char *filename,
@@ -271,6 +273,13 @@ int ima_read_xattr(struct dentry *dentry,
   struct evm_ima_xattr_data **xattr_value);
 
 #else
+static inline int ima_check_blacklist(struct integrity_iint_cache *iint,
+ const struct modsig *modsig, int action,
+ int pcr)
+{
+   return 0;
+}
+
 static inline int ima_appraise_measurement(enum ima_hooks func,
   struct integrity_iint_cache *iint,
   struct file *file,
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 136ae4e0ee92..fe34d64a684c 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ima.h"
 
@@ -303,6 +304,44 @@ static int modsig_verify(enum ima_hooks func, const struct 
modsig *modsig,
return rc;
 }
 
+/*
+ * ima_blacklist_measurement - Checks whether the binary is blacklisted. If
+ * yes, then adds the hash of the blacklisted binary to the measurement list.
+ *
+ * Returns -EPERM if the hash is blacklisted.
+ */
+int ima_check_blacklist(struct integrity_iint_cache *iint,
+   const struct modsig *modsig, int action, int pcr)
+{
+   enum hash_algo hash_algo;
+   const u8 *digest = NULL;
+   u32 digestsize = 0;
+   u32 secid;
+   int rc = 0;
+   struct ima_template_desc *template_desc;
+
+   template_desc = lookup_template_desc("ima-buf");
+   template_desc_init_fields(template_desc->fmt, &(template_desc->fields),
+ &(template_desc->num_fields));
+
+   if (!(iint->flags & IMA_CHECK_BLACKLIST))
+   return 0;
+
+   if (iint->flags & IMA_MODSIG_ALLOWED) {
+   security_task_getsecid(current, );
+   ima_get_modsig_digest(modsig, _algo, , );
+   rc = is_binary_blacklisted(digest, digestsize);
+
+   /* Returns -EPERM on blacklisted hash found */
+   if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
+   process_buffer_measurement(digest, digestsize,
+  "blacklisted-hash", pcr,
+  template_desc);
+   }
+
+   return rc;
+}
+
 /*
  * ima_appraise_measurement - appraise file measurement
  *
diff --git a/security/integrity/ima/i

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

2019-10-07 Thread Nayna Jain
The existing is_hash_blacklisted() function returns -EKEYREJECTED
error code for both the blacklisted keys and binaries.

This patch adds a wrapper function is_binary_blacklisted() to check
against binary hashes and returns -EPERM.

Signed-off-by: Nayna Jain 
---
 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 v7 0/8] powerpc: Enabling IMA arch specific secure boot policies

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

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

PowerNV systems uses the linux based bootloader and kexec the Host OS.
It rely on IMA for signature verification of the kernel before doing the
kexec. This patchset adds support for powerpc arch specific ima policies
that are defined based on system's OS secureboot and trustedboot state.
The OS secureboot and trustedboot state are determined via device-tree
properties.

The verification needs to be done only for the binaries which are not
blacklisted. The kernel currently checks against the blacklisted keys.
However that results in blacklisting all the binaries that are signed by
that key. In order to prevent single binary from loading, it is required
to support checking against blacklisting of the binary hash. This patchset
adds the support in IMA to check against blacklisted hashes for the files
signed by appended signature.

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

Changelog:
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
*** BLURB HERE ***

Nayna Jain (8):
  powerpc: detect the secure boot mode of the system
  powerpc: add support to initialize ima policy rules
  powerpc: detect the trusted boot state of the system
  powerpc/ima: add measurement rules to ima arch specific policy
  ima: make process_buffer_measurement() generic
  certs: add wrapper function to check blacklisted binary hash
  ima: check against blacklisted hashes for files with modsig
  powerpc/ima: update ima arch policy to check for blacklist

 Documentation/ABI/testing/ima_policy   |  1 +
 arch/powerpc/Kconfig   | 12 
 arch/powerpc/include/asm/secure_boot.h | 35 
 arch/powerpc/kernel/Makefile   |  2 +
 arch/powerpc/kernel/ima_arch.c | 72 
 arch/powerpc/kernel/secure_boot.c  | 77 ++
 certs/blacklist.c  |  9 +++
 include/keys/system_keyring.h  |  6 ++
 include/linux/ima.h|  3 +-
 security/integrity/ima/ima.h   | 12 
 security/integrity

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

2019-10-07 Thread Nayna Jain
Secure boot on PowerNV defines different IMA policies based on the secure
boot state of the system.

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

The PPC_SECURE_BOOT config represents the base enablement of secureboot
on POWER.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/Kconfig   | 10 ++
 arch/powerpc/include/asm/secure_boot.h | 29 ++
 arch/powerpc/kernel/Makefile   |  2 ++
 arch/powerpc/kernel/secure_boot.c  | 42 ++
 4 files changed, 83 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..b4a221886fcf 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 needs to define security
+ policies to extend secure boot to the OS. This config allows 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 ..23d2ef2f1f7b
--- /dev/null
+++ b/arch/powerpc/include/asm/secure_boot.h
@@ -0,0 +1,29 @@
+/* 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_powerpc_os_secureboot_enabled(void);
+struct device_node *get_powerpc_os_sb_node(void);
+
+#else
+
+static inline bool is_powerpc_os_secureboot_enabled(void)
+{
+   return false;
+}
+
+static inline struct device_node *get_powerpc_os_sb_node(void)
+{
+   return NULL;
+}
+
+#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 ..0488dbcab6b9
--- /dev/null
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ */
+#include 
+#include 
+#include 
+
+struct device_node *get_powerpc_os_sb_node(void)
+{
+   return of_find_compatible_node(NULL, NULL, "ibm,secvar-v1");
+}
+
+bool is_powerpc_os_secureboot_enabled(void)
+{
+   struct device_node *node;
+
+   node = get_powerpc_os_sb_node();
+   if (!node)
+   goto disabled;
+
+   if (!of_device_is_available(node)) {
+   pr_err("Secure variables support is in error state, fail 
secure\n");
+   goto enabled;
+   }
+
+   /*
+* secureboot is enabled if os-secure-enforcing property exists,
+* else disabled.
+*/
+   if (!of_find_property(node, "os-secure-enforcing", NULL))
+   goto disabled;
+
+enabled:
+   pr_info("secureboot mode enabled\n");
+   return true;
+
+disabled:
+   pr_info("secureboot mode disabled\n");
+   return false;
+}
-- 
2.20.1



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

2019-10-01 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 
---
 security/integrity/Kconfig|  8 ++
 security/integrity/Makefile   |  3 +
 .../integrity/platform_certs/load_powerpc.c   | 86 +++
 3 files changed, 97 insertions(+)
 create mode 100644 security/integrity/platform_certs/load_powerpc.c

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 525bf1d6e0db..9eeb6b053de3 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -14,6 +14,9 @@ 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)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 
 subdir-$(CONFIG_IMA)   += ima
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 (!dbx) {
+   pr_info("Couldn't get dbx list from firmware\n");
+   } else {
+   rc = parse_efi_signature_list("powerpc:dbx", dbx, dbxsize,
+ get_handler_for_dbx);
+   if (rc)
+   pr_err("Couldn't parse dbx signatures: %d\n", rc);
+   kfree(dbx);
+   }
+
+   return rc;
+}
+late_initcall(load_powerpc_certs);
-- 
2.20.1



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

2019-10-01 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. This patchset is
dependent on the base CONFIG PPC_SECURE_BOOT added by ima arch specific
patches for POWER[3]

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 0 Oct  1 15:10 data
-r--r--r--. 1 root root 65536 Oct  1 15:10 size
--w---. 1 root root 0 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
[3] https://lkml.org/lkml/2019/9/27/407

Changelog:
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 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/tes

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

2019-10-01 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  |   8 ++
 arch/powerpc/include/asm/powernv.h   |   2 +
 arch/powerpc/include/asm/secvar.h|  35 +
 arch/powerpc/kernel/Makefile |   2 +-
 arch/powerpc/kernel/secvar-ops.c |  19 +++
 arch/powerpc/platforms/powernv/Kconfig   |   6 +
 arch/powerpc/platforms/powernv/Makefile  |   1 +
 arch/powerpc/platforms/powernv/opal-call.c   |   3 +
 arch/powerpc/platforms/powernv/opal-secvar.c | 137 +++
 arch/powerpc/platforms/powernv/opal.c|   5 +
 11 files changed, 221 insertions(+), 2 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..03392dc3f5e2 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);
@@ -392,6 +399,7 @@ void opal_wake_poller(void);
 void opal_powercap_init(void);
 void opal_psr_init(void);
 void opal_sensor_groups_init(void);
+void opal_secvar_init(void);
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/powerpc/include/asm/powernv.h 
b/arch/powerpc/include/asm/powernv.h
index e1a858718716..cff980a85dd2 100644
--- a/arch/powerpc/include/asm/powernv.h
+++ b/arch/powerpc/include/asm/powernv.h
@@ -12,10 +12,12 @@ extern void powernv_set_nmmu_ptcr(unsigned long ptcr);
 void pnv_program_cpu_hotplug_lpcr(unsigned int cpu, u64 lpcr_val);
 
 void pnv_tm_init(void);
+
 #else
 static inline void powernv_set_nmmu_ptcr(unsigned long ptcr) { }
 
 static inline void pnv_tm_init(void) { }
+
 #endif
 
 #endif /* _ASM_POWERNV_H */
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

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

2019-10-01 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 19faace69644..525bf1d6e0db 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)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 
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] sysfs: Fixes __BIN_ATTR_WO() macro

2019-10-01 Thread Nayna Jain
This patch fixes the size and write parameter for the macro
__BIN_ATTR_WO().

Fixes: 7f905761e15a8 ("sysfs: add BIN_ATTR_WO() macro")
Signed-off-by: Nayna Jain 
---
 include/linux/sysfs.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 5420817ed317..fa7ee503fb76 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -196,9 +196,9 @@ struct bin_attribute {
.size   = _size,\
 }
 
-#define __BIN_ATTR_WO(_name) { \
+#define __BIN_ATTR_WO(_name, _size) {  \
.attr   = { .name = __stringify(_name), .mode = 0200 }, \
-   .store  = _name##_store,\
+   .write  = _name##_write,\
.size   = _size,\
 }
 
-- 
2.20.1



[PATCH v6 8/9] ima: deprecate permit_directio, instead use appraise_flag

2019-09-27 Thread Nayna Jain
This patch deprecates the existing permit_directio flag, instead adds
it as possible value to appraise_flag parameter.
For eg.
appraise_flag=permit_directio

Signed-off-by: Nayna Jain 
---
 Documentation/ABI/testing/ima_policy | 4 ++--
 security/integrity/ima/ima_policy.c  | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy 
b/Documentation/ABI/testing/ima_policy
index 4c97afcc0f3c..9a2a140dc561 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -24,8 +24,8 @@ Description:
[euid=] [fowner=] [fsname=]]
lsm:[[subj_user=] [subj_role=] [subj_type=]
 [obj_user=] [obj_role=] [obj_type=]]
-   option: [[appraise_type=]] [template=] [permit_directio]
-   [appraise_flag=[check_blacklist]]
+   option: [[appraise_type=]] [template=] 
[permit_directio(deprecated)]
+   
[appraise_flag=[check_blacklist]|[permit_directio]]
base:   func:= 
[BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK]
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index ad3b3af69460..d9df54c75d46 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -1177,6 +1177,8 @@ static int ima_parse_rule(char *rule, struct 
ima_rule_entry *entry)
ima_log_string(ab, "appraise_flag", args[0].from);
if (strstr(args[0].from, "blacklist"))
entry->flags |= IMA_CHECK_BLACKLIST;
+   if (strstr(args[0].from, "permit_directio"))
+   entry->flags |= IMA_PERMIT_DIRECTIO;
break;
case Opt_permit_directio:
entry->flags |= IMA_PERMIT_DIRECTIO;
-- 
2.20.1



[PATCH v6 9/9] powerpc/ima: update ima arch policy to check for blacklist

2019-09-27 Thread Nayna Jain
This patch updates the arch specific policies for PowernV systems
to add check against blacklisted hashes before doing the verification.

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

diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index 77c61b142042..3f57433c0824 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -24,9 +24,9 @@ bool arch_ima_get_secureboot(void)
 static const char *const arch_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",
 #if !IS_ENABLED(CONFIG_MODULE_SIG)
-   "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 v6 6/9] ima: make process_buffer_measurement() non static

2019-09-27 Thread Nayna Jain
To add the support for checking against blacklist, it would be needed
to add an additional measurement record that identifies the record
as blacklisted.

This patch modifies the process_buffer_measurement() and makes it
non static to be used by blacklist functionality. It modifies the
function to handle more than just the KEXEC_CMDLINE.

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

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 19769bf5f6ab..9bf509217e8e 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -215,6 +215,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, int pcr,
+   struct ima_template_desc *template_desc);
 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 79c01516211b..ae0c1bdc4eaf 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.
+ * @pcr: pcr to extend the measurement
+ * @template_desc: template description
  *
  * 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, int pcr,
+   struct ima_template_desc *template_desc)
 {
int ret = 0;
struct ima_template_entry *entry = NULL;
@@ -642,19 +642,11 @@ 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 {
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;
-
-   action = ima_get_action(NULL, cred, secid, 0, KEXEC_CMDLINE, ,
-   _desc);
-   if (!(action & IMA_MEASURE))
-   return;
 
iint.ima_hash = 
iint.ima_hash->algo = ima_hash_algo;
@@ -686,12 +678,19 @@ static void process_buffer_measurement(const void *buf, 
int size,
  */
 void ima_kexec_cmdline(const void *buf, int size)
 {
+   int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
+   struct ima_template_desc *template_desc = NULL;
+   int action;
u32 secid;
 
if (buf && size != 0) {
security_task_getsecid(current, );
-   process_buffer_measurement(buf, size, "kexec-cmdline",
-  current_cred(), secid);
+   action = ima_get_action(NULL, current_cred(), secid, 0,
+   KEXEC_CMDLINE, , _desc);
+   if (!(action & IMA_MEASURE))
+   return;
+   process_buffer_measurement(buf, size, "kexec-cmdline", pcr,
+  template_desc);
}
 }
 
-- 
2.20.1



[PATCH v6 4/9] powerpc: detect the trusted boot state of the system

2019-09-27 Thread Nayna Jain
PowerNV systems enables the IMA measurement rules only if the
trusted boot is enabled on the system.

This patch adds the function to detect if the system has trusted
boot enabled.

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

diff --git a/arch/powerpc/include/asm/secure_boot.h 
b/arch/powerpc/include/asm/secure_boot.h
index 4e8e2b08a993..192caaedbe7a 100644
--- a/arch/powerpc/include/asm/secure_boot.h
+++ b/arch/powerpc/include/asm/secure_boot.h
@@ -14,6 +14,7 @@
 
 bool is_powerpc_os_secureboot_enabled(void);
 int get_powerpc_os_sb_node(struct device_node **node);
+bool is_powerpc_trustedboot_enabled(void);
 
 #else
 
@@ -27,5 +28,10 @@ static inline int get_powerpc_os_sb_node(struct device_node 
**node)
return -ENOENT;
 }
 
+static inline bool is_powerpc_os_trustedboot_enabled(void)
+{
+   return false;
+}
+
 #endif
 #endif
diff --git a/arch/powerpc/kernel/secure_boot.c 
b/arch/powerpc/kernel/secure_boot.c
index 45ca19f5e836..9d452e1550ae 100644
--- a/arch/powerpc/kernel/secure_boot.c
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -80,3 +80,17 @@ bool is_powerpc_os_secureboot_enabled(void)
pr_info("secureboot mode disabled\n");
return false;
 }
+
+bool is_powerpc_trustedboot_enabled(void)
+{
+   struct device_node *node;
+
+   node = get_powerpc_fw_sb_node();
+   if (node && (of_find_property(node, "trusted-enabled", NULL))) {
+   pr_info("trustedboot mode enabled\n");
+   return true;
+   }
+
+   pr_info("trustedboot mode disabled\n");
+   return false;
+}
-- 
2.20.1



[PATCH v6 5/9] powerpc/ima: add measurement rules to ima arch specific policy

2019-09-27 Thread Nayna Jain
This patch adds the measurement rules to the arch specific policies for the
systems with trusted boot.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/kernel/ima_arch.c | 44 +++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
index 39401b67f19e..77c61b142042 100644
--- a/arch/powerpc/kernel/ima_arch.c
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -12,8 +12,18 @@ bool arch_ima_get_secureboot(void)
return is_powerpc_os_secureboot_enabled();
 }
 
-/* Defines IMA appraise rules for secureboot */
+/*
+ * The "arch_rules" contains both the securebot and trustedboot rules for 
adding
+ * the kexec kernel image and kernel modules file hashes to the IMA measurement
+ * list and verifying the file signatures against known good values.
+ *
+ * The "appraise_type=imasig|modsig" option allows the good signature to be
+ * stored as an xattr or as an appended signature. The "template=ima-modsig"
+ * option includes the appended signature in the IMA measurement list.
+ */
 static const char *const arch_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",
 #if !IS_ENABLED(CONFIG_MODULE_SIG)
"appraise func=MODULE_CHECK appraise_type=imasig|modsig",
@@ -22,12 +32,40 @@ static const char *const arch_rules[] = {
 };
 
 /*
- * Returns the relevant IMA arch policies based on the system secureboot state.
+ * The "measure_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 measure_rules[] = {
+   "measure func=KEXEC_KERNEL_CHECK",
+   "measure func=MODULE_CHECK",
+   NULL
+};
+
+/*
+ * Returns the relevant IMA arch policies based on the system secureboot
+ * and trustedboot state.
  */
 const char *const *arch_get_ima_policy(void)
 {
-   if (is_powerpc_os_secureboot_enabled())
+   const char *const *rules;
+   int offset = 0;
+
+   for (rules = arch_rules; *rules != NULL; rules++) {
+   if (strncmp(*rules, "appraise", 8) == 0)
+   break;
+   offset++;
+   }
+
+   if (is_powerpc_os_secureboot_enabled()
+   && is_powerpc_trustedboot_enabled())
return arch_rules;
 
+   if (is_powerpc_os_secureboot_enabled())
+   return arch_rules + offset;
+
+   if (is_powerpc_trustedboot_enabled())
+   return measure_rules;
+
return NULL;
 }
-- 
2.20.1



[PATCH v6 2/9] powerpc: detect the secure boot mode of the system

2019-09-27 Thread Nayna Jain
Secure boot on PowerNV defines different IMA policies based on the secure
boot state of the system.

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

The PPC_SECURE_BOOT config represents the base enablement of secureboot
on POWER.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/Kconfig   | 10 
 arch/powerpc/include/asm/secure_boot.h | 31 ++
 arch/powerpc/kernel/Makefile   |  2 +
 arch/powerpc/kernel/secure_boot.c  | 82 ++
 4 files changed, 125 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 77f6ebf97113..2c54beb29f1a 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -912,6 +912,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 needs to define security
+ policies to extend secure boot to the OS. This config allows 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 ..4e8e2b08a993
--- /dev/null
+++ b/arch/powerpc/include/asm/secure_boot.h
@@ -0,0 +1,31 @@
+/* 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
+
+#define SECURE_BOOT_MASK   0x
+
+bool is_powerpc_os_secureboot_enabled(void);
+int get_powerpc_os_sb_node(struct device_node **node);
+
+#else
+
+static inline bool is_powerpc_os_secureboot_enabled(void)
+{
+   return false;
+}
+
+static inline int get_powerpc_os_sb_node(struct device_node **node)
+{
+   return -ENOENT;
+}
+
+#endif
+#endif
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index ea0c69236789..875b0785a20e 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -157,6 +157,8 @@ endif
 obj-$(CONFIG_EPAPR_PARAVIRT)   += epapr_paravirt.o epapr_hcalls.o
 obj-$(CONFIG_KVM_GUEST)+= kvm.o kvm_emul.o
 
+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 ..45ca19f5e836
--- /dev/null
+++ b/arch/powerpc/kernel/secure_boot.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ */
+#include 
+#include 
+#include 
+
+static struct device_node *get_powerpc_fw_sb_node(void)
+{
+   return of_find_node_by_name(NULL, "ibm,secureboot");
+}
+
+bool is_powerpc_os_sb_supported(void)
+{
+   struct device_node *node = NULL;
+
+   node = get_powerpc_fw_sb_node();
+   if (node && of_device_is_compatible(node, "ibm,secureboot-v3"))
+   return true;
+
+   return false;
+}
+
+int get_powerpc_os_sb_node(struct device_node **node)
+{
+   struct device_node *fwsbnode;
+
+   if (!is_powerpc_os_sb_supported())
+   return -ENOTSUPP;
+
+   fwsbnode = get_powerpc_fw_sb_node();
+   if (!fwsbnode)
+   return -ENOENT;
+
+   *node = of_find_node_by_name(fwsbnode, "secvar");
+   if (*node)
+   return 0;
+
+   return -ENOENT;
+}
+
+bool is_powerpc_os_secureboot_enabled(void)
+{
+   struct device_node *node;
+   u64 sbmode = 0;
+   int rc;
+
+   rc = get_powerpc_os_sb_node();
+   if (rc == -ENOTSUPP)
+   goto disabled;
+
+   /* Fail secure for any failure related to secvar */
+   if (rc) {
+   pr_err("Expected secure variables support, fail secure\n");
+   goto enabled;
+   }
+
+   if (!of_device_is_available(node)) {
+   pr_err("Secure variables support is in error state, fail 
secure\n");
+   goto enabled;
+   }
+
+   rc = of_property_read_u64(node, "os-secure-mode", );
+   if (rc)
+   goto enabled;
+
+   sbmode = be64_to_cpu(sbmode);
+
+   /* checks for the secure mode enforcing bit */
+   if (!(sbmode & SECURE_BOOT_MASK))
+   goto disabled;
+
+enabled:
+   pr_info("secureboot mode enabled\n");
+   return true;
+
+disabled:
+   pr_info("secureboot mode disabled\n");
+   return false;
+}
-- 
2.20.1



[PATCH v6 3/9] powerpc: add support to initialize ima policy rules

2019-09-27 Thread Nayna Jain
PowerNV systems uses kernel based bootloader, thus its secure boot
implementation uses kernel IMA security subsystem to verify the kernel
before kexec. Since the verification policy might differ based on the
secure boot mode of the system, the policies are defined at runtime.

This patch implements the arch-specific support to define the 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   |  2 ++
 arch/powerpc/kernel/Makefile   |  2 +-
 arch/powerpc/kernel/ima_arch.c | 33 +
 include/linux/ima.h|  3 ++-
 4 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/kernel/ima_arch.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2c54beb29f1a..54eda07c74e5 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -916,6 +916,8 @@ config PPC_SECURE_BOOT
prompt "Enable secure boot support"
bool
depends on PPC_POWERNV
+   depends on IMA
+   depends on IMA_ARCH_POLICY
help
  Systems with firmware secure boot enabled needs to define security
  policies to extend secure boot to the OS. This config allows user
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 875b0785a20e..7156ac1fc956 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -157,7 +157,7 @@ endif
 obj-$(CONFIG_EPAPR_PARAVIRT)   += epapr_paravirt.o epapr_hcalls.o
 obj-$(CONFIG_KVM_GUEST)+= kvm.o kvm_emul.o
 
-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 ..39401b67f19e
--- /dev/null
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ */
+
+#include 
+#include 
+
+bool arch_ima_get_secureboot(void)
+{
+   return is_powerpc_os_secureboot_enabled();
+}
+
+/* Defines IMA appraise rules for secureboot */
+static const char *const arch_rules[] = {
+   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig",
+#if !IS_ENABLED(CONFIG_MODULE_SIG)
+   "appraise func=MODULE_CHECK appraise_type=imasig|modsig",
+#endif
+   NULL
+};
+
+/*
+ * Returns the relevant IMA arch policies based on the system secureboot state.
+ */
+const char *const *arch_get_ima_policy(void)
+{
+   if (is_powerpc_os_secureboot_enabled())
+   return arch_rules;
+
+   return NULL;
+}
diff --git a/include/linux/ima.h b/include/linux/ima.h
index a20ad398d260..10af09b5b478 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 v6 0/9] powerpc: Enabling IMA arch specific secure boot policies

2019-09-27 Thread Nayna Jain
This patchset extends the previous version of the patchset[1] by adding
the support for checking against the binary blacklisted hashes.

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

PowerNV systems uses the linux based bootloader and kexec the Host OS.
It rely on IMA for signature verification of the kernel before doing the
kexec. This patchset adds support for powerpc arch specific ima policies
that are defined based on system's OS secureboot and trustedboot state.
The OS secureboot and trustedboot state are determined via device-tree
properties.

The verification needs to be done only for the binaries which are not
blacklisted. The kernel currently checks against the blacklisted keys.
However that results in blacklisting all the binaries that are signed by
that key. In order to prevent single binary from loading, it is required
to support checking against blacklisting of the binary hash. This patchset
adds the support in IMA to check against blacklisted hashes for the files
signed by appended signature.

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

Changelog:
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 (9):
  dt-bindings: ibm,secureboot: secure boot specific properties for
PowerNV
  powerpc: detect the secure boot mode of the system
  powerpc: add support to initialize ima policy rules
  powerpc: detect the trusted boot state of the system
  powerpc/ima: add measurement rules to ima arch specific policy
  ima: make process_buffer_measurement() non-static
  ima: check against blacklisted hashes for files with modsig
  ima: deprecate permit_directio, instead use appraise_flag
  powerpc/ima: update ima arch policy to check for blacklist

 Documentation/ABI/testing/ima_policy  |  3 +-
 .../bindings/powerpc/ibm,secureboot.rst   | 76 +++
 .../devicetree/bindings/powerpc/secvar.rst| 89 +
 arch/powerpc/Kconfig  | 12 +++
 arch/powerpc/include/asm/secure_boot.h| 37 +++
 arch/powerpc/kernel/Makefile  |  2 +
 arch/powerpc/kernel/ima_arch.c| 71 ++
 arch/powerpc/kernel/secure_boot.c | 96 +++
 include/linux/ima.h   |  3 +-
 security/integrity/ima/ima.h  | 15 +++
 security/integrity/ima/ima_appraise.c | 35 +++
 security/integrity/ima/ima_main.c | 37 +++
 security/integrity/ima/ima_policy.c   | 12 ++-
 security/integrity/integrity.h|  1 +
 14 files changed, 468 insertions(+), 21 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/powerpc/ibm,secureboot.rst
 create mode 100644 Documentation/devicetree/bindings/powerpc/secvar.rst
 create mode 100644 arch/powerpc/include

[PATCH v6 1/9] dt-bindings: ibm,secureboot: secure boot specific properties for PowerNV

2019-09-27 Thread Nayna Jain
PowerNV represents both the firmware and Host OS secureboot state of the
system via device tree. This patch adds the documentation to give
the definition of the nodes and the properties.

Signed-off-by: Nayna Jain 
---
 .../bindings/powerpc/ibm,secureboot.rst   | 76 
 .../devicetree/bindings/powerpc/secvar.rst| 89 +++
 2 files changed, 165 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/powerpc/ibm,secureboot.rst
 create mode 100644 Documentation/devicetree/bindings/powerpc/secvar.rst

diff --git a/Documentation/devicetree/bindings/powerpc/ibm,secureboot.rst 
b/Documentation/devicetree/bindings/powerpc/ibm,secureboot.rst
new file mode 100644
index ..03d32099d2eb
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/ibm,secureboot.rst
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: GPL-2.0
+*** NOTE ***
+This document is copied from OPAL firmware
+(skiboot/doc/device-tree/ibm,secureboot.rst)
+
+.. _device-tree/ibm,secureboot:
+
+ibm,secureboot
+==
+
+The ``??bm,secureboot`` node provides secure boot and trusted boot information
+up to the target OS. Further information can be found in :ref:`stb-overview`.
+
+Required properties
+---
+
+.. code-block:: none
+
+compatible: Either one of the following values:
+
+ibm,secureboot-v1  :  The container-verification-code
+  is stored in a secure ROM memory.
+
+ibm,secureboot-v2  :  The container-verification-code
+  is stored in a reserved memory.
+  It described by the ibm,cvc child
+  node.
+
+ibm,secureboot-v3  :  The container-verification-code
+  is stored in a reserved memory.
+  It described by the ibm,cvc child
+  node. Secure variables are
+  supported. `secvar` node should
+  be created.
+
+secure-enabled: this property exists when the firmware stack is booting
+in secure mode (hardware secure boot jumper asserted).
+
+trusted-enabled:this property exists when the firmware stack is booting
+in trusted mode.
+
+hw-key-hash:hash of the three hardware public keys trusted by the
+platformw owner. This is used to verify if a firmware
+code is signed with trusted keys.
+
+hw-key-hash-size:   hw-key-hash size
+
+secvar: this node is created if the platform supports secure
+variables. Contains information about the current
+secvar status, see 'secvar.rst'.
+
+Obsolete properties
+---
+
+.. code-block:: none
+
+hash-algo:  Superseded by the hw-key-hash-size property in
+'ibm,secureboot-v2'.
+
+Example
+---
+
+.. code-block:: dts
+
+ibm,secureboot {
+compatible = "ibm,secureboot-v2";
+secure-enabled;
+trusted-enabled;
+hw-key-hash-size = <0x40>;
+hw-key-hash = <0x40d487ff 0x7380ed6a 0xd54775d5 0x795fea0d 0xe2f541fe
+   0xa9db06b8 0x466a42a3 0x20e65f75 0xb4866546 0x0017d907
+   0x515dc2a5 0xf9fc5095 0x4d6ee0c9 0xb67d219d 0xfb708535
+   0x1d01d6d1>;
+phandle = <0x10fd>;
+linux,phandle = <0x10fd>;
+};
diff --git a/Documentation/devicetree/bindings/powerpc/secvar.rst 
b/Documentation/devicetree/bindings/powerpc/secvar.rst
new file mode 100644
index ..47793ab9c2a7
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/secvar.rst
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: GPL-2.0
+*** NOTE ***
+This document is copied from OPAL firmware
+(skiboot/doc/device-tree/secvar.rst)
+
+.. _device-tree/ibm,secureboot/secvar:
+
+secvar
+==
+
+The ``secvar`` node provides secure variable information for the secure
+boot of the target OS.
+
+Required properties
+---
+
+.. code-block:: none
+
+compatible: this property is set based on the current secure
+variable scheme as set by the platform.
+
+status: set to "fail" if the secure variables could not
+be initialized, validated, or some other
+catastrophic failure.
+
+update-status:  contains the return code of the update queue
+process run during initialization. Signifies if
+updates were processed or not, and if there was

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

2019-08-26 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 
---
 security/integrity/Kconfig|  8 ++
 security/integrity/Makefile   |  3 +
 .../integrity/platform_certs/load_powerpc.c   | 88 +++
 3 files changed, 99 insertions(+)
 create mode 100644 security/integrity/platform_certs/load_powerpc.c

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 525bf1d6e0db..9eeb6b053de3 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -14,6 +14,9 @@ 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)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 
 subdir-$(CONFIG_IMA)   += ima
diff --git a/security/integrity/platform_certs/load_powerpc.c 
b/security/integrity/platform_certs/load_powerpc.c
new file mode 100644
index ..359d5063d4da
--- /dev/null
+++ b/security/integrity/platform_certs/load_powerpc.c
@@ -0,0 +1,88 @@
+// 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 (!dbx) {
+   pr_info("Couldn't get dbx list from firmware\n");
+   } else {
+   rc = parse_efi_signature_list("powerpc:dbx",
+   dbx, dbxsize,
+   get_handler_for_dbx);
+   if (rc)
+   pr_err("Couldn't parse dbx signatures: %d\n", rc);
+   kfree(dbx);
+   }
+
+   return rc;
+}
+late_initcall(load_powerpc_certs);
-- 
2.20.1



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

2019-08-26 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 
---
 Documentation/ABI/testing/sysfs-secvar |  37 +
 arch/powerpc/Kconfig   |  10 ++
 arch/powerpc/kernel/Makefile   |   1 +
 arch/powerpc/kernel/secvar-sysfs.c | 200 +
 4 files changed, 248 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 ..815bd8ec4d5e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-secvar
@@ -0,0 +1,37 @@
+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 
+Description:   A read-only file containing the value of the variable
+
+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.
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 42109682b727..11f553e68e1f 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -925,6 +925,16 @@ config PPC_SECURE_BOOT
  allows user to enable OS Secure Boot on PowerPC systems that
  have firmware secure boot support.
 
+config SECVAR_SYSFS
+   tristate "Enable sysfs interface for POWER secure variables"
+   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 9041563f1c74..cbdac2e6b6f8 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -158,6 +158,7 @@ obj-$(CONFIG_EPAPR_PARAVIRT)+= epapr_paravirt.o 
epapr_hcalls.o
 obj-$(CONFIG_KVM_GUEST)+= kvm.o kvm_emul.o
 
 obj-$(CONFIG_PPC_SECURE_BOOT)  += secboot.o ima_arch.o secvar-ops.o
+obj-$(CONFIG_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 ..020529a5f6fb
--- /dev/null
+++ b/arch/powerpc/kernel/secvar-sysfs.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 IBM Corporation 
+ *
+ * This code exposes secure variables to user via sysfs
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Approximating it for now. It will be read from device tree */
+#define VARIABLE_MAX_SIZE  32000
+/* Approximate value */
+#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 %d\n", rc);
+   return rc;
+   }
+
+   rc = sprintf(buf, "%llu\n", dsize)

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

2019-08-26 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/powernv.h   |   2 +
 arch/powerpc/include/asm/secvar.h|  35 +
 arch/powerpc/kernel/Makefile |   2 +-
 arch/powerpc/kernel/secvar-ops.c |  19 +++
 arch/powerpc/platforms/powernv/Kconfig   |   6 +
 arch/powerpc/platforms/powernv/Makefile  |   1 +
 arch/powerpc/platforms/powernv/opal-call.c   |   3 +
 arch/powerpc/platforms/powernv/opal-secvar.c | 138 +++
 arch/powerpc/platforms/powernv/opal.c|   5 +
 11 files changed, 220 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 383242eb0dea..b238b4f26c5b 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -208,7 +208,10 @@
 #define OPAL_HANDLE_HMI2   166
 #defineOPAL_NX_COPROC_INIT 167
 #define OPAL_XIVE_GET_VP_STATE 170
-#define OPAL_LAST  170
+#define OPAL_SECVAR_GET 173
+#define OPAL_SECVAR_GET_NEXT174
+#define OPAL_SECVAR_ENQUEUE_UPDATE  175
+#define OPAL_LAST   175
 
 #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 57bd029c715e..0606b1d22db4 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -296,7 +296,11 @@ int opal_set_power_shift_ratio(u32 handle, int token, u32 
psr);
 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_size);
+int opal_secvar_enqueue_update(const char *key, uint64_t key_len, u8 *data,
+  uint64_t data_size);
 s64 opal_signal_system_reset(s32 cpu);
 s64 opal_quiesce(u64 shutdown_type, s32 cpu);
 
@@ -387,6 +391,7 @@ void opal_wake_poller(void);
 void opal_powercap_init(void);
 void opal_psr_init(void);
 void opal_sensor_groups_init(void);
+void opal_secvar_init(void);
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/powerpc/include/asm/powernv.h 
b/arch/powerpc/include/asm/powernv.h
index e1a858718716..cff980a85dd2 100644
--- a/arch/powerpc/include/asm/powernv.h
+++ b/arch/powerpc/include/asm/powernv.h
@@ -12,10 +12,12 @@ extern void powernv_set_nmmu_ptcr(unsigned long ptcr);
 void pnv_program_cpu_hotplug_lpcr(unsigned int cpu, u64 lpcr_val);
 
 void pnv_tm_init(void);
+
 #else
 static inline void powernv_set_nmmu_ptcr(unsigned long ptcr) { }
 
 static inline void pnv_tm_init(void) { }
+
 #endif
 
 #endif /* _ASM_POWERNV_H */
diff --git a/arch/powerpc/include/asm/secvar.h 
b/arch/powerpc/include/asm/secvar.h
new file mode 100644
index ..f27655cb5db8
--- /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 keysize);
+   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 520b1c814197..9041563f1c74 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -157,7 +157,7 @@ endif
 obj-$(CONFIG_EPAPR_PARAVIRT)   += epapr_paravirt.o epapr_hcalls.o
 obj

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

2019-08-26 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 
---
 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 19faace69644..525bf1d6e0db 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)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 
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 db.
+ */
+efi_element_hand

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

2019-08-26 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. This patchset is
dependent on the base CONFIG PPC_SECURE_BOOT added by ima arch specific
patches for POWER[3]

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):
[PK]$ ls -l
total 0
-r--r--r--. 1 root root 32000 Aug 21 08:28 data
-r--r--r--. 1 root root 65536 Aug 21 08:28 size
--w---. 1 root root 32000 Aug 21 08:28 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. The new version with the changes are going to be posted soon.
[2] https://lkml.org/lkml/2019/6/13/1644
[3] https://lkml.org/lkml/2019/8/19/402

Changelog:
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 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|  37 
 arch/powerpc/Kconfig  |  10 +
 arch/powerpc/include/asm/opal-api.h   |   5 +-
 arch/powerpc/include/asm/opal.h   |   7 +-
 arch/powerpc/include/asm/powernv.h|   2 +
 arch/powerpc/include/asm/secvar.h |  35 +++
 arch/powerpc/kernel/Makefile  |   3 +-
 arch/powerpc/kernel/secvar-ops.c  

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

2019-08-21 Thread Nayna Jain
The keys used to verify the Host OS kernel are managed by OPAL as secure
variables. This patch loads the verification keys into the .platform
keyring and revocation keys 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 
---
 security/integrity/Kconfig|  9 ++
 security/integrity/Makefile   |  3 +
 .../integrity/platform_certs/load_powerpc.c   | 94 +++
 3 files changed, 106 insertions(+)
 create mode 100644 security/integrity/platform_certs/load_powerpc.c

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 0bae6adb63a9..2b4109c157e2 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 revocation keys for POWER"
+   depends on INTEGRITY_PLATFORM_KEYRING
+   depends on PPC_SECURE_BOOT
+   def_bool y
+   help
+ Enable loading of db keys to the .platform keyring and dbx keys 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 525bf1d6e0db..9eeb6b053de3 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -14,6 +14,9 @@ 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)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 
 subdir-$(CONFIG_IMA)   += ima
diff --git a/security/integrity/platform_certs/load_powerpc.c 
b/security/integrity/platform_certs/load_powerpc.c
new file mode 100644
index ..f4d869171062
--- /dev/null
+++ b/security/integrity/platform_certs/load_powerpc.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * load_powernv.c
+ *  - loads keys and certs stored and controlled
+ *  by the firmware.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "keyring_handler.h"
+
+static struct secvar_operations *secvarops;
+
+/*
+ * Get a certificate list blob from the named EFI variable.
+ */
+static __init void *get_cert_list(u8 *key, unsigned long keylen,
+ unsigned long *size)
+{
+   int rc;
+   void *db;
+
+   rc = secvarops->get_variable(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 = secvarops->get_variable(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 UEFI databases into the platform trusted
+ * keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist
+ * keyring.
+ */
+static int __init load_powerpc_certs(void)
+{
+   void *db = NULL, *dbx = NULL;
+   unsigned long dbsize = 0, dbxsize = 0;
+   int rc = 0;
+
+   secvarops = get_secvar_ops();
+   if (!secvarops)
+   return -ENOENT;
+
+   /* 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 OPAL\n");
+   } else {
+   rc = parse_efi_signature_list("OPAL: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 (!dbx) {
+   pr_info("Couldn't get dbx list from OPAL\n");
+   } else {
+   rc = parse_efi_signature_list("OPAL:dbx",
+   dbx, dbxsize,
+   get_handler_for_dbx);
+   if (rc)
+   pr_err("Couldn't parse dbx signatures: %d\n", rc);
+   kfree(dbx);
+   }
+
+   return rc;
+}
+late_initcall(load_powerpc_certs);
-- 
2.20.1



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

2019-08-21 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  |   6 ++
 arch/powerpc/include/asm/secvar.h|  55 ++
 arch/powerpc/kernel/Makefile |   2 +-
 arch/powerpc/kernel/secvar-ops.c |  25 +
 arch/powerpc/platforms/powernv/Kconfig   |   6 ++
 arch/powerpc/platforms/powernv/Makefile  |   1 +
 arch/powerpc/platforms/powernv/opal-call.c   |   3 +
 arch/powerpc/platforms/powernv/opal-secvar.c | 102 +++
 arch/powerpc/platforms/powernv/opal.c|   5 +
 10 files changed, 208 insertions(+), 2 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 383242eb0dea..b238b4f26c5b 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -208,7 +208,10 @@
 #define OPAL_HANDLE_HMI2   166
 #defineOPAL_NX_COPROC_INIT 167
 #define OPAL_XIVE_GET_VP_STATE 170
-#define OPAL_LAST  170
+#define OPAL_SECVAR_GET 173
+#define OPAL_SECVAR_GET_NEXT174
+#define OPAL_SECVAR_ENQUEUE_UPDATE  175
+#define OPAL_LAST   175
 
 #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 57bd029c715e..247adec2375f 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -388,6 +388,12 @@ void opal_powercap_init(void);
 void opal_psr_init(void);
 void opal_sensor_groups_init(void);
 
+extern int opal_secvar_get(uint64_t k_key, uint64_t k_key_len,
+  uint64_t k_data, uint64_t k_data_size);
+extern int opal_secvar_get_next(uint64_t k_key, uint64_t k_key_len,
+   uint64_t k_key_size);
+extern int opal_secvar_enqueue_update(uint64_t k_key, uint64_t k_key_len,
+ uint64_t k_data, uint64_t k_data_size);
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_OPAL_H */
diff --git a/arch/powerpc/include/asm/secvar.h 
b/arch/powerpc/include/asm/secvar.h
new file mode 100644
index ..645654456265
--- /dev/null
+++ b/arch/powerpc/include/asm/secvar.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PowerPC secure variable operations.
+ *
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ */
+#ifndef SECVAR_OPS_H
+#define SECVAR_OPS_H
+
+#include
+#include
+
+struct secvar_operations {
+   int (*get_variable)(const char *key, unsigned long key_len, u8 *data,
+   unsigned long *data_size);
+   int (*get_next_variable)(const char *key, unsigned long *key_len,
+unsigned long keysize);
+   int (*set_variable)(const char *key, unsigned long key_len, u8 *data,
+   unsigned long data_size);
+};
+
+#ifdef CONFIG_PPC_SECURE_BOOT
+
+extern void set_secvar_ops(struct secvar_operations *ops);
+extern struct secvar_operations *get_secvar_ops(void);
+
+#else
+
+static inline void set_secvar_ops(struct secvar_operations *ops)
+{
+}
+
+static inline struct secvar_operations *get_secvar_ops(void)
+{
+   return NULL;
+}
+
+#endif
+
+#ifdef CONFIG_OPAL_SECVAR
+
+extern int secvar_init(void);
+
+#else
+
+static inline int secvar_init(void)
+{
+   return -EINVAL;
+}
+
+#endif
+
+#endif
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 520b1c814197..9041563f1c74 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -157,7 +157,7 @@ endif
 obj-$(CONFIG_EPAPR_PARAVIRT)   += epapr_paravirt.o epapr_hcalls.o
 obj-$(CONFIG_KVM_GUEST)+= kvm.o kvm_emul.o
 
-obj-$(CONFIG_PPC_SECURE_BOOT)  += secboot.o ima_arch.o
+obj-$(CONFIG_PPC_SECURE_BOOT)  += secboot.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 ..198222499848
--- /dev/null
+++ b/arch/powerpc/kernel/secvar-ops.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: N

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

2019-08-21 Thread Nayna Jain
This patch moves the common code to keyring_handler.c

Signed-off-by: Nayna Jain 
---
 security/integrity/Makefile   |  3 +-
 .../platform_certs/keyring_handler.c  | 80 +++
 .../platform_certs/keyring_handler.h  | 35 
 security/integrity/platform_certs/load_uefi.c | 67 +---
 4 files changed, 118 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 19faace69644..525bf1d6e0db 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)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 
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 ..829a14b95218
--- /dev/null
+++ b/security/integrity/platform_certs/keyring_handler.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ */
+#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 db.
+ */
+efi_element_handler_t get_handler_for_db(const efi_guid_t *sig_type);
+
+/*
+ * Return the handler for particular signature list types found in the dbx.
+ */
+efi_element

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

2019-08-21 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. This patchset is
dependent on the base CONFIG PPC_SECURE_BOOT added by ima arch specific
patches for POWER[3]

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):
[PK]$ ls -l
total 0
-r--r--r--. 1 root root 32000 Aug 21 08:28 data
-r--r--r--. 1 root root 65536 Aug 21 08:28 name
-r--r--r--. 1 root root 65536 Aug 21 08:28 size
--w---. 1 root root 32000 Aug 21 08:28 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. The new version with the changes are going to be posted soon.
[2] https://lkml.org/lkml/2019/6/13/1644
[3] https://lkml.org/lkml/2019/8/19/402

Changelog:

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 into kernel keyring

 Documentation/ABI/testing/sysfs-secvar|  27 +++
 arch/powerpc/Kconfig  |   9 +
 arch/powerpc/include/asm/opal-api.h   |   5 +-
 arch/powerpc/include/asm/opal.h   |   6 +
 arch/powerpc/include/asm/secvar.h |  55 +
 arch/powerpc/kernel/Makefile  |   3 +-
 arch/powerpc/kernel/secvar-ops.c  |  25 +++
 arch/powerpc/kernel/secvar-sysfs.c| 210 ++
 arch/powerpc/platforms/powernv/Kconfig|   6 +
 arch/powerpc/platforms/powernv/Makefile   |   1 +
 arch/powerpc/platforms/powernv/opal-call.c|   3 +
 arch/powerpc/platforms/powernv/opal-secvar.c  | 102 +
 arch/powerpc/platforms/powernv/opal.c |   5 +
 security/integrity/Kconfig|   9 +
 security/integrity/Makefile   |   6 +-
 .../platform_certs/keyring_handler.c  |  80 +++
 .../platform_certs/keyring_handler.h  |  35 +++
 .../integrity/platform_certs/load_powerpc.c   |  94 
 security/integrity/platform_certs/load_uefi.c |  67 +-
 19 files changed, 679 insertions(+), 69 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



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

2019-08-21 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 
---
 Documentation/ABI/testing/sysfs-secvar |  27 
 arch/powerpc/Kconfig   |   9 ++
 arch/powerpc/kernel/Makefile   |   1 +
 arch/powerpc/kernel/secvar-sysfs.c | 210 +
 4 files changed, 247 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 ..68f0e03d873d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-secvar
@@ -0,0 +1,27 @@
+What:  /sys/firmware/secvar
+Date:  August 2019
+Contact:   Nayna Jain 
+Description:
+   This directory exposes interfaces for interacting with
+   the secure variables managed by OPAL firmware.
+
+   This is only for the powerpc/powernv platform.
+
+   Directory:
+   vars:   This directory lists all the variables that
+   are supported by the OPAL. The variables are
+   represented in the form of directories with
+   their variable names. The variable name is
+   unique and is in ASCII representation. The data
+   and size can be determined by reading their
+   respective attribute files.
+
+   Each variable directory has the following files:
+   name:   An ASCII representation of the variable name
+   data:   A read-only file containing the value of the
+   variable
+   size:   An integer representation of the size of the
+   content of the variable. In other works, it
+   represents the size of the data
+   update: A write-only file that is used to submit the new
+   value for the variable.
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 42109682b727..b4bdf77837b2 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -925,6 +925,15 @@ config PPC_SECURE_BOOT
  allows user to enable OS Secure Boot on PowerPC systems that
  have firmware secure boot support.
 
+config SECVAR_SYSFS
+tristate "Enable sysfs interface for POWER secure variables"
+depends on PPC_SECURE_BOOT
+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 9041563f1c74..4ea7b738c3a3 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -158,6 +158,7 @@ obj-$(CONFIG_EPAPR_PARAVIRT)+= epapr_paravirt.o 
epapr_hcalls.o
 obj-$(CONFIG_KVM_GUEST)+= kvm.o kvm_emul.o
 
 obj-$(CONFIG_PPC_SECURE_BOOT)  += secboot.o ima_arch.o secvar-ops.o
+obj-$(CONFIG_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 ..e46986bb29a0
--- /dev/null
+++ b/arch/powerpc/kernel/secvar-sysfs.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 IBM Corporation 
+ *
+ * This code exposes secure variables to user via sysfs
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+//Approximating it for now, it is bound to change.
+#define VARIABLE_MAX_SIZE  32000
+
+static struct kobject *powerpc_kobj;
+static struct secvar_operations *secvarops;
+struct kset *secvar_kset;
+
+static ssize_t name_show(struct kobject *kobj, struct kobj_attribute *attr,
+char *buf)
+{
+   return sprintf(buf, "%s", kobj->name);
+}
+
+static ssize_t size_show(struct kobject *kobj, struct kobj_attribute *attr,
+char *buf)
+{
+   unsigned long dsize;
+   int rc;
+
+   rc = secvarops->get_variable(kobj->name, strlen(kobj->name) + 1, NULL,
+);
+   if (rc) {
+   pr_err("

[PATCH 2/2] powerpc: expose secure variables via sysfs

2019-06-13 Thread Nayna Jain
As part of PowerNV secure boot support, OS verification keys are stored
and controlled by OPAL as secure variables. These need to be exposed to
the userspace so that sysadmins can perform key management tasks.

This patch adds the support to expose secure variables via a sysfs
interface It reuses the the existing efi defined hooks and backend in
order to maintain the compatibility with the userspace tools.

Though it reuses a great deal of efi, POWER platforms do not use EFI.
A new config, POWER_SECVAR_SYSFS, is defined to enable this new sysfs
interface.

Signed-off-by: Nayna Jain 
---
 arch/powerpc/Kconfig |   2 +
 drivers/firmware/Makefile|   1 +
 drivers/firmware/efi/efivars.c   |   2 +-
 drivers/firmware/powerpc/Kconfig |  12 +
 drivers/firmware/powerpc/Makefile|   3 +
 drivers/firmware/powerpc/efi_error.c |  46 
 drivers/firmware/powerpc/secvar.c| 326 +++
 7 files changed, 391 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/powerpc/Kconfig
 create mode 100644 drivers/firmware/powerpc/Makefile
 create mode 100644 drivers/firmware/powerpc/efi_error.c
 create mode 100644 drivers/firmware/powerpc/secvar.c

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 9de77bb14f54..1548dd8cf1a0 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -916,6 +916,8 @@ config PPC_SECURE_BOOT
  allows user to enable OS Secure Boot on PowerPC systems that
  have firmware secure boot support.
 
+source "drivers/firmware/powerpc/Kconfig"
+
 endmenu
 
 config ISA_DMA_API
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 3fa0b34eb72f..8cfaf7e6769d 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -33,3 +33,4 @@ obj-$(CONFIG_UEFI_CPER)   += efi/
 obj-y  += imx/
 obj-y  += tegra/
 obj-y  += xilinx/
+obj-$(CONFIG_POWER_SECVAR_SYSFS) += powerpc/
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
index 7576450c8254..30ef53003c24 100644
--- a/drivers/firmware/efi/efivars.c
+++ b/drivers/firmware/efi/efivars.c
@@ -664,7 +664,7 @@ int efivars_sysfs_init(void)
struct kobject *parent_kobj = efivars_kobject();
int error = 0;
 
-   if (!efi_enabled(EFI_RUNTIME_SERVICES))
+   if (IS_ENABLED(CONFIG_EFI) && !efi_enabled(EFI_RUNTIME_SERVICES))
return -ENODEV;
 
/* No efivars has been registered yet */
diff --git a/drivers/firmware/powerpc/Kconfig b/drivers/firmware/powerpc/Kconfig
new file mode 100644
index ..e0303fc517d5
--- /dev/null
+++ b/drivers/firmware/powerpc/Kconfig
@@ -0,0 +1,12 @@
+config POWER_SECVAR_SYSFS
+   tristate "Enable sysfs interface for POWER secure variables"
+   default n
+   depends on PPC_SECURE_BOOT
+   select UCS2_STRING
+   help
+ POWER secure variables are managed and controlled by OPAL.
+ These variables are exposed to userspace via sysfs to allow
+ user to read/write these variables. Say Y if you have secure
+ boot enabled and want to expose variables to userspace.
+
+source "drivers/firmware/efi/Kconfig"
diff --git a/drivers/firmware/powerpc/Makefile 
b/drivers/firmware/powerpc/Makefile
new file mode 100644
index ..d5fa3b007315
--- /dev/null
+++ b/drivers/firmware/powerpc/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_POWER_SECVAR_SYSFS) += ../efi/efivars.o efi_error.o ../efi/vars.o 
secvar.o
diff --git a/drivers/firmware/powerpc/efi_error.c 
b/drivers/firmware/powerpc/efi_error.c
new file mode 100644
index ..b5cabd52e6b4
--- /dev/null
+++ b/drivers/firmware/powerpc/efi_error.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * efi_error.c
+ *  - Error codes as understood by efi based tools
+ *  Taken from drivers/firmware/efi/efi.c
+ */
+#include
+
+int efi_status_to_err(efi_status_t status)
+{
+   int err;
+
+   switch (status) {
+   case EFI_SUCCESS:
+   err = 0;
+   break;
+   case EFI_INVALID_PARAMETER:
+   err = -EINVAL;
+   break;
+   case EFI_OUT_OF_RESOURCES:
+   err = -ENOSPC;
+   break;
+   case EFI_DEVICE_ERROR:
+   err = -EIO;
+   break;
+   case EFI_WRITE_PROTECTED:
+   err = -EROFS;
+   break;
+   case EFI_SECURITY_VIOLATION:
+   err = -EACCES;
+   break;
+   case EFI_NOT_FOUND:
+   err = -ENOENT;
+   break;
+   case EFI_ABORTED:
+   err = -EINTR;
+   break;
+   default:
+   err = -EINVAL;
+   }
+
+   return err;
+}
diff --git a/drivers/firmware/powerpc/secvar.c 
b/drivers/f

[PATCH 1/2] powerpc/powernv: add OPAL APIs for secure variables

2019-06-13 Thread Nayna Jain
From: Claudio Carvalho 

The X.509 certificates trusted by the platform and other information
required to secure boot the OS kernel are wrapped in secure variables,
which are controlled by OPAL. These variables are manipulated by
userspace tools using filesystem interface. This patch adds support
for the OPAL APIs required to expose variables to userspace.

OPAL_SECVAR_GET_NEXT:
For a given secure variable, it returns the name and vendor GUID
of the next variable.

OPAL_SECVAR_ENQUEUE_UPDATE:
Enqueue the supplied secure variable update so that it can be processed
by OPAL in the next boot. Variable updates cannot be be processed right
away because the variable storage is write locked at runtime.

OPAL_SECVAR_GET_SIZE:
Returns size information about the variable.

Signed-off-by: Claudio Carvalho 
Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/opal-api.h  |  3 +
 arch/powerpc/include/asm/opal-secvar.h   |  9 +++
 arch/powerpc/include/asm/opal.h  |  8 +++
 arch/powerpc/platforms/powernv/opal-call.c   |  3 +
 arch/powerpc/platforms/powernv/opal-secvar.c | 60 +++-
 5 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/opal-api.h 
b/arch/powerpc/include/asm/opal-api.h
index a505e669b4b6..fa3083966efc 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -213,6 +213,9 @@
 #defineOPAL_NX_COPROC_INIT 167
 #define OPAL_XIVE_GET_VP_STATE 170
 #define OPAL_SECVAR_GET 173
+#define OPAL_SECVAR_GET_SIZE174
+#define OPAL_SECVAR_GET_NEXT175
+#define OPAL_SECVAR_ENQUEUE_UPDATE  176
 #define OPAL_SECVAR_BACKEND 177
 #define OPAL_LAST  177
 
diff --git a/arch/powerpc/include/asm/opal-secvar.h 
b/arch/powerpc/include/asm/opal-secvar.h
index b677171a0368..26ebbc63dd70 100644
--- a/arch/powerpc/include/asm/opal-secvar.h
+++ b/arch/powerpc/include/asm/opal-secvar.h
@@ -20,4 +20,13 @@ extern int opal_get_variable(u8 *key, unsigned long ksize,
 
 extern int opal_variable_version(unsigned long *backend);
 
+extern int opal_get_variable_size(u8 *key, unsigned long ksize,
+ unsigned long *mdsize, unsigned long *dsize);
+
+extern int opal_get_next_variable(u8 *key, unsigned long *keylen,
+ unsigned long keysize);
+
+extern int opal_set_variable(u8 *key, unsigned long ksize, u8 *metadata,
+unsigned long mdsize, u8 *data,
+unsigned long dsize);
 #endif
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 57d2c2356eda..a6fcb59c91cc 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -399,6 +399,14 @@ extern int opal_secvar_get(uint64_t k_key, uint64_t 
k_key_len,
   uint64_t k_data, uint64_t k_data_size);
 
 extern int opal_secvar_backend(uint64_t k_backend);
+extern int opal_secvar_get_size(uint64_t k_key, uint64_t k_key_len,
+   uint64_t k_metadata_size, uint64_t k_data_size);
+extern int opal_secvar_get_next(uint64_t k_key, uint64_t k_key_len,
+   uint64_t k_key_size);
+extern int opal_secvar_enqueue_update(uint64_t k_key, uint64_t k_key_len,
+ uint64_t k_metadata,
+ uint64_t k_metadata_size,
+ uint64_t k_data, uint64_t k_data_size);
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/powerpc/platforms/powernv/opal-call.c 
b/arch/powerpc/platforms/powernv/opal-call.c
index 0445980f294f..dda3a4c5bb79 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -290,3 +290,6 @@ OPAL_CALL(opal_sensor_group_enable, 
OPAL_SENSOR_GROUP_ENABLE);
 OPAL_CALL(opal_nx_coproc_init, OPAL_NX_COPROC_INIT);
 OPAL_CALL(opal_secvar_get,  OPAL_SECVAR_GET);
 OPAL_CALL(opal_secvar_backend,  OPAL_SECVAR_BACKEND);
+OPAL_CALL(opal_secvar_get_size, OPAL_SECVAR_GET_SIZE);
+OPAL_CALL(opal_secvar_get_next, OPAL_SECVAR_GET_NEXT);
+OPAL_CALL(opal_secvar_enqueue_update,   OPAL_SECVAR_ENQUEUE_UPDATE);
diff --git a/arch/powerpc/platforms/powernv/opal-secvar.c 
b/arch/powerpc/platforms/powernv/opal-secvar.c
index dba441dd5af1..afa67b87ad7a 100644
--- a/arch/powerpc/platforms/powernv/opal-secvar.c
+++ b/arch/powerpc/platforms/powernv/opal-secvar.c
@@ -30,7 +30,10 @@ static bool is_opal_secvar_supported(void)
return opal_secvar_supported;
 
if (!opal_check_token(OPAL_SECVAR_GET)
-   || !opal_check_token(OPAL_SECVAR_BACKEND)) {
+   || !opal_check_token(OPAL_SECVAR_BACKEND)
+   || !opal_check_token(OPAL_SECVAR_GET_SIZE

[PATCH 0/2] powerpc/powernv: expose secure variables to userspace

2019-06-13 Thread Nayna Jain
This patch set is part of a series that implements secure boot on PowerNV
systems[1]. The original series had been split into two patchsets:
1. powerpc: enable ima arch specific policies[2]
2. powerpc/powernv: expose secure variables to userspace, which is this
patchset.

Since there are major changes in this patchset compared to the previous
one[1], I am posting it as new series rather than v2.

As part of PowerNV secure boot support, NV OS verification keys are stored
and controlled by OPAL as secure variables. However, to allow users to
manage these 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[3]. This patchset defines the kernel interface for the
OPAL APIs. These APIs are used by the hooks, which expose these variables
to userspace for reading/writing.

In order to reuse the existing tools, we currently use the efi hooks to
expose the secure variables via sysfs. Keeping the usability and
maintainability in mind, we are starting with this scheme as simple sysfs
implementation. We expect to refine it over time as we incorporate the
feedback.

The patchset makes substantial reuse of drivers/firmware/efi/efivars.c and
drivers/firmware/efi/vars.c, however because POWER platforms do not use
EFI, a new config, POWER_SECVAR_SYSFS, is defined to enable this sysfs
interface in POWER.

This patchset has a pre-requisiste of other OPAL APIs which are posted as
part of ima arch specific patches[2].

[1]https://patchwork.kernel.org/cover/10882149/  
[2]https://lkml.org/lkml/2019/6/11/868
[3]https://patchwork.ozlabs.org/project/skiboot/list/?series=112868 

Claudio Carvalho (1):
  powerpc/powernv: add OPAL APIs for secure variables

Nayna Jain (1):
  powerpc: expose secure variables via sysfs

 arch/powerpc/Kconfig |   2 +
 arch/powerpc/include/asm/opal-api.h  |   3 +
 arch/powerpc/include/asm/opal-secvar.h   |   9 +
 arch/powerpc/include/asm/opal.h  |   8 +
 arch/powerpc/platforms/powernv/opal-call.c   |   3 +
 arch/powerpc/platforms/powernv/opal-secvar.c |  60 +++-
 drivers/firmware/Makefile|   1 +
 drivers/firmware/efi/efivars.c   |   2 +-
 drivers/firmware/powerpc/Kconfig |  12 +
 drivers/firmware/powerpc/Makefile|   3 +
 drivers/firmware/powerpc/efi_error.c |  46 +++
 drivers/firmware/powerpc/secvar.c| 326 +++
 12 files changed, 473 insertions(+), 2 deletions(-)
 create mode 100644 drivers/firmware/powerpc/Kconfig
 create mode 100644 drivers/firmware/powerpc/Makefile
 create mode 100644 drivers/firmware/powerpc/efi_error.c
 create mode 100644 drivers/firmware/powerpc/secvar.c

-- 
2.20.1



[PATCH v4 0/3] powerpc: Enabling IMA arch specific secure boot policies

2019-06-11 Thread Nayna Jain
This patch set, previously named "powerpc: Enabling secure boot on powernv
systems - Part 1", is part of a series that implements secure boot on
PowerNV systems.

In order to verify the OS kernel on PowerNV, secure boot requires X.509
certificates trusted by the platform, the secure boot modes, and several
other pieces of information. These are stored in secure variables
controlled by OPAL, also known as OPAL secure variables.

The IMA architecture specific policy support on POWER is dependent on OPAL
runtime services to access secure variables. OPAL APIs in skiboot are
modified to define generic interface compatible to any backend. This
patchset is consequently updated to be compatible with new OPAL API
interface. This has cleaned up any EFIsms in the arch specific code.
Further, the ima arch specific policies are updated to be able to support
appended signatures. They also now use per policy template.

Exposing the OPAL secure variables to userspace will be posted as a
separate patch set, allowing the IMA architecture specific policy on POWER
to be upstreamed independently.

This patch set adds the following features:

1. Add support for OPAL Runtime API to access secure variables controlled
by OPAL.
2. Define IMA arch-specific policies based on the secure boot state and
mode of the system. On secure boot enabled PowerNV systems, the OS kernel
signature will be verified by IMA appraisal.

Pre-requisites for this patchset are:
1. OPAL APIs in Skiboot[1]
2. Appended signature support in IMA [2]
3. Per policy template support in IMA [3]

[1] https://patchwork.ozlabs.org/project/skiboot/list/?series=112868 
[2] https://patchwork.ozlabs.org/cover/1087361/. Updated version will be
posted soon
[3] Repo: 
https://kernel.googlesource.com/pub/scm/linux/kernel/git/zohar/linux-integrity
Branch: next-queued-testing. Commit: f241bb1f42aa95

--

Original Cover Letter:

This patch set is part of a series that implements secure boot on PowerNV
systems.

In order to verify the OS kernel on PowerNV, secure boot requires X.509
certificates trusted by the platform, the secure boot modes, and several
other pieces of information. These are stored in secure variables
controlled by OPAL, also known as OPAL secure variables.

The IMA architecture specific policy support on Power is dependent on OPAL
runtime services to access secure variables. Instead of directly accessing
the OPAL runtime services, version 3 of this patch set relied upon the
EFI hooks. This version drops that dependency and calls the OPAL runtime
services directly. Skiboot OPAL APIs are due to be posted soon.

Exposing the OPAL secure variables to userspace will be posted as a
separate patch set, allowing the IMA architecture specific policy on Power
to be upstreamed independently.

This patch set adds the following features:

1. Add support for OPAL Runtime API to access secure variables controlled
by OPAL.
2. Define IMA arch-specific policies based on the secure boot state and
mode of the system. On secure boot enabled powernv systems, the OS kernel
signature will be verified by IMA appraisal.

[1] https://patchwork.kernel.org/cover/10882149/

Changelog:

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

Claudio Carvalho (1):
  powerpc/powernv: Add OPAL API interface to get secureboot state

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

 arch/power

[PATCH v4 3/3] powerpc: Add support to initialize ima policy rules

2019-06-11 Thread Nayna Jain
PowerNV secure boot relies on the kernel IMA security subsystem to
perform the OS kernel image signature verification. Since each secure
boot mode has different IMA policy requirements, dynamic definition of
the policy rules based on the runtime secure boot mode of the system is
required. On systems that support secure boot, but have it disabled,
only measurement policy rules of the kernel image and modules are
defined.

This patch defines the arch-specific implementation to retrieve the
secure boot mode of the system and accordingly configures the IMA policy
rules.

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

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

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 8c1c636308c8..9de77bb14f54 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -902,6 +902,20 @@ config PPC_MEM_KEYS
 
  If unsure, say y.
 
+config PPC_SECURE_BOOT
+   prompt "Enable PowerPC Secure Boot"
+   bool
+   default n
+   depends on PPC64
+   depends on OPAL_SECVAR
+   depends on IMA
+   depends on IMA_ARCH_POLICY
+   help
+ Linux on POWER with firmware secure boot enabled needs to define
+ security policies to extend secure boot to the OS.This config
+ allows user to enable OS Secure Boot on PowerPC systems that
+ have firmware secure boot support.
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 0ea6c4aa3a20..75c929b41341 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -131,6 +131,7 @@ ifdef CONFIG_IMA
 obj-y  += ima_kexec.o
 endif
 endif
+obj-$(CONFIG_PPC_SECURE_BOOT)  += ima_arch.o
 
 obj-$(CONFIG_AUDIT)+= audit.o
 obj64-$(CONFIG_AUDIT)  += compat_audit.o
diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
new file mode 100644
index ..1767bf6e6550
--- /dev/null
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * ima_arch.c
+ *  - initialize ima policies for PowerPC Secure Boot
+ */
+
+#include 
+#include 
+
+bool arch_ima_get_secureboot(void)
+{
+   bool sb_mode;
+
+   sb_mode = get_powerpc_sb_mode();
+   if (sb_mode)
+   return true;
+   else
+   return false;
+}
+
+/*
+ * File signature verification is not needed, include only measurements
+ */
+static const char *const default_arch_rules[] = {
+   "measure func=KEXEC_KERNEL_CHECK template=ima-modsig",
+   "measure func=MODULE_CHECK template=ima-modsig",
+   NULL
+};
+
+/* Both file signature verification and measurements are needed */
+static const char *const sb_arch_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 
template=ima-modsig",
+#if !IS_ENABLED(CONFIG_MODULE_SIG)
+   "appraise func=MODULE_CHECK appraise_type=imasig|modsig 
template=ima-modsig",
+#endif
+   NULL
+};
+
+/*
+ * On PowerPC, file measurements are to be added to the IMA measurement list
+ * irrespective of the secure boot state of the system. Signature verification
+ * is conditionally enabled based on the secure boot state.
+ */
+const char *const *arch_get_ima_policy(void)
+{
+   if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot())
+   return sb_arch_rules;
+   return default_arch_rules;
+}
diff --git a/include/linux/ima.h b/include/linux/ima.h
index fd9f7cf4cdf5..a01df076ecae 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -31,7 +31,8 @@ extern void ima_post_path_mknod(struct dentry *dentry);
 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 v4 1/3] powerpc/powernv: Add OPAL API interface to get secureboot state

2019-06-11 Thread Nayna Jain
From: Claudio Carvalho 

The X.509 certificates trusted by the platform and other information
required to secure boot the OS kernel are wrapped in secure variables,
which are controlled by OPAL.

This patch adds support to read OPAL secure variables through
OPAL_SECVAR_GET call. It returns the metadata and data for a given secure
variable based on the unique key.

Since OPAL can support different types of backend which can vary in the
variable interpretation, a new OPAL API call named OPAL_SECVAR_BACKEND, is
added to retrieve the supported backend version. This helps the consumer
to know how to interpret the variable.

This support can be enabled using CONFIG_OPAL_SECVAR

Signed-off-by: Claudio Carvalho 
Signed-off-by: Nayna Jain 
---
This patch depends on a new OPAL call that is being added to skiboot.
The patch set that implements the new call has been posted to
https://patchwork.ozlabs.org/project/skiboot/list/?series=112868

 arch/powerpc/include/asm/opal-api.h  |  4 +-
 arch/powerpc/include/asm/opal-secvar.h   | 23 ++
 arch/powerpc/include/asm/opal.h  |  6 ++
 arch/powerpc/platforms/powernv/Kconfig   |  6 ++
 arch/powerpc/platforms/powernv/Makefile  |  1 +
 arch/powerpc/platforms/powernv/opal-call.c   |  2 +
 arch/powerpc/platforms/powernv/opal-secvar.c | 85 
 7 files changed, 126 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/include/asm/opal-secvar.h
 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 e1577cfa7186..a505e669b4b6 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -212,7 +212,9 @@
 #define OPAL_HANDLE_HMI2   166
 #defineOPAL_NX_COPROC_INIT 167
 #define OPAL_XIVE_GET_VP_STATE 170
-#define OPAL_LAST  170
+#define OPAL_SECVAR_GET 173
+#define OPAL_SECVAR_BACKEND 177
+#define OPAL_LAST  177
 
 #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-secvar.h 
b/arch/powerpc/include/asm/opal-secvar.h
new file mode 100644
index ..b677171a0368
--- /dev/null
+++ b/arch/powerpc/include/asm/opal-secvar.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PowerNV definitions for secure variables OPAL API.
+ *
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Claudio Carvalho 
+ *
+ */
+#ifndef OPAL_SECVAR_H
+#define OPAL_SECVAR_H
+
+enum {
+   BACKEND_NONE = 0,
+   BACKEND_TC_COMPAT_V1,
+};
+
+extern int opal_get_variable(u8 *key, unsigned long ksize,
+u8 *metadata, unsigned long *mdsize,
+u8 *data, unsigned long *dsize);
+
+extern int opal_variable_version(unsigned long *backend);
+
+#endif
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 4cc37e708bc7..57d2c2356eda 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -394,6 +394,12 @@ void opal_powercap_init(void);
 void opal_psr_init(void);
 void opal_sensor_groups_init(void);
 
+extern int opal_secvar_get(uint64_t k_key, uint64_t k_key_len,
+  uint64_t k_metadata, uint64_t k_metadata_size,
+  uint64_t k_data, uint64_t k_data_size);
+
+extern int opal_secvar_backend(uint64_t k_backend);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_OPAL_H */
diff --git a/arch/powerpc/platforms/powernv/Kconfig 
b/arch/powerpc/platforms/powernv/Kconfig
index 850eee860cf2..65b060539b5c 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -47,3 +47,9 @@ config PPC_VAS
  VAS adapters are found in POWER9 based systems.
 
  If unsure, say N.
+
+config OPAL_SECVAR
+   bool "OPAL Secure Variables"
+   depends on PPC_POWERNV
+   help
+ This enables the kernel to access OPAL secure variables.
diff --git a/arch/powerpc/platforms/powernv/Makefile 
b/arch/powerpc/platforms/powernv/Makefile
index da2e99efbd04..6651c742e530 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_PERF_EVENTS) += opal-imc.o
 obj-$(CONFIG_PPC_MEMTRACE) += memtrace.o
 obj-$(CONFIG_PPC_VAS)  += vas.o vas-window.o vas-debug.o
 obj-$(CONFIG_OCXL_BASE)+= ocxl.o
+obj-$(CONFIG_OPAL_SECVAR) += opal-secvar.o
diff --git a/arch/powerpc/platforms/powernv/opal-call.c 
b/arch/powerpc/platforms/powernv/opal-call.c
index 36c8fa3647a2..0445980f294f 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -288,3 +288,5 @@ OPAL_CALL(opal_pci_set_pbcq_

[PATCH v4 2/3] powerpc/powernv: detect the secure boot mode of the system

2019-06-11 Thread Nayna Jain
PowerNV secure boot defines different IMA policies based on the secure
boot state of the system.

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

Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/secboot.h   | 21 
 arch/powerpc/platforms/powernv/Makefile  |  2 +-
 arch/powerpc/platforms/powernv/secboot.c | 61 
 3 files changed, 83 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/include/asm/secboot.h
 create mode 100644 arch/powerpc/platforms/powernv/secboot.c

diff --git a/arch/powerpc/include/asm/secboot.h 
b/arch/powerpc/include/asm/secboot.h
new file mode 100644
index ..1904fb4a3352
--- /dev/null
+++ b/arch/powerpc/include/asm/secboot.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PowerPC secure boot definitions
+ *
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ */
+#ifndef POWERPC_SECBOOT_H
+#define POWERPC_SECBOOT_H
+
+#if defined(CONFIG_OPAL_SECVAR)
+extern bool get_powerpc_sb_mode(void);
+#else
+static inline bool get_powerpc_sb_mode(void)
+{
+   return false;
+}
+#endif
+
+#endif
diff --git a/arch/powerpc/platforms/powernv/Makefile 
b/arch/powerpc/platforms/powernv/Makefile
index 6651c742e530..6f4af607a915 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -16,4 +16,4 @@ obj-$(CONFIG_PERF_EVENTS) += opal-imc.o
 obj-$(CONFIG_PPC_MEMTRACE) += memtrace.o
 obj-$(CONFIG_PPC_VAS)  += vas.o vas-window.o vas-debug.o
 obj-$(CONFIG_OCXL_BASE)+= ocxl.o
-obj-$(CONFIG_OPAL_SECVAR) += opal-secvar.o
+obj-$(CONFIG_OPAL_SECVAR) += opal-secvar.o secboot.o
diff --git a/arch/powerpc/platforms/powernv/secboot.c 
b/arch/powerpc/platforms/powernv/secboot.c
new file mode 100644
index ..9199e520ebed
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/secboot.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * secboot.c
+ *  - util function to get powerpc secboot state
+ */
+#include 
+#include 
+#include 
+#include 
+
+bool get_powerpc_sb_mode(void)
+{
+   u8 secure_boot_name[] = "SecureBoot";
+   u8 setup_mode_name[] = "SetupMode";
+   u8 secboot, setupmode;
+   unsigned long size = sizeof(secboot);
+   int status;
+   unsigned long version;
+
+   status = opal_variable_version();
+   if ((status != OPAL_SUCCESS) || (version != BACKEND_TC_COMPAT_V1)) {
+   pr_info("secboot: error retrieving compatible backend\n");
+   return false;
+   }
+
+   status = opal_get_variable(secure_boot_name, sizeof(secure_boot_name),
+  NULL, NULL, , );
+
+   /*
+* For now assume all failures reading the SecureBoot variable implies
+* secure boot is not enabled. Later differentiate failure types.
+*/
+   if (status != OPAL_SUCCESS) {
+   secboot = 0;
+   setupmode = 0;
+   goto out;
+   }
+
+   size = sizeof(setupmode);
+   status = opal_get_variable(setup_mode_name, sizeof(setup_mode_name),
+  NULL, NULL,  , );
+
+   /*
+* Failure to read the SetupMode variable does not prevent
+* secure boot mode
+*/
+   if (status != OPAL_SUCCESS)
+   setupmode = 0;
+
+out:
+   if ((secboot == 0) || (setupmode == 1)) {
+   pr_info("secboot: secureboot mode disabled\n");
+   return false;
+   }
+
+   pr_info("secboot: secureboot mode enabled\n");
+   return true;
+}
-- 
2.20.1



[PATCH v3 0/3] powerpc: Enabling IMA arch specific secure boot policies

2019-06-10 Thread Nayna Jain
This patch set, previously named "powerpc: Enabling secure boot on powernv
systems - Part 1", is part of a series that implements secure boot on
PowerNV systems.

In order to verify the OS kernel on PowerNV, secure boot requires X.509
certificates trusted by the platform, the secure boot modes, and several
other pieces of information. These are stored in secure variables
controlled by OPAL, also known as OPAL secure variables.

The IMA architecture specific policy support on POWER is dependent on OPAL
runtime services to access secure variables. OPAL APIs in skiboot are
modified to define generic interface compatible to any backend. This
patchset is consequently updated to be compatible with new OPAL API
interface. This has cleaned up any EFIsms in the arch specific code.
Further, the ima arch specific policies are updated to be able to support
appended signatures. They also now use per policy template.

Exposing the OPAL secure variables to userspace will be posted as a
separate patch set, allowing the IMA architecture specific policy on POWER
to be upstreamed independently.

This patch set adds the following features:

1. Add support for OPAL Runtime API to access secure variables controlled
by OPAL.
2. Define IMA arch-specific policies based on the secure boot state and
mode of the system. On secure boot enabled PowerNV systems, the OS kernel
signature will be verified by IMA appraisal.

Pre-requisites for this patchset are:
1. OPAL APIs in Skiboot[1]
2. Appended signature support in IMA [2]
3. Per policy template support in IMA [3]

[1] https://patchwork.ozlabs.org/project/skiboot/list/?series=112868 
[2] https://patchwork.ozlabs.org/cover/1087361/. Updated version will be
posted soon
[3] Repo: 
https://kernel.googlesource.com/pub/scm/linux/kernel/git/zohar/linux-integrity
Branch: next-queued-testing. Commit: f241bb1f42aa95

--

Original Cover Letter:

This patch set is part of a series that implements secure boot on PowerNV
systems.

In order to verify the OS kernel on PowerNV, secure boot requires X.509
certificates trusted by the platform, the secure boot modes, and several
other pieces of information. These are stored in secure variables
controlled by OPAL, also known as OPAL secure variables.

The IMA architecture specific policy support on Power is dependent on OPAL
runtime services to access secure variables. Instead of directly accessing
the OPAL runtime services, version 3 of this patch set relied upon the
EFI hooks. This version drops that dependency and calls the OPAL runtime
services directly. Skiboot OPAL APIs are due to be posted soon.

Exposing the OPAL secure variables to userspace will be posted as a
separate patch set, allowing the IMA architecture specific policy on Power
to be upstreamed independently.

This patch set adds the following features:

1. Add support for OPAL Runtime API to access secure variables controlled
by OPAL.
2. Define IMA arch-specific policies based on the secure boot state and
mode of the system. On secure boot enabled powernv systems, the OS kernel
signature will be verified by IMA appraisal.

[1] https://patchwork.kernel.org/cover/10882149/

Changelog:

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

Claudio Carvalho (1):
  powerpc/powernv: Add OPAL API interface to get secureboot state

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

 arch/powerpc/Kconfig | 14 
 arch/powerpc/include/asm/

[PATCH v3 1/3] powerpc/powernv: Add OPAL API interface to get secureboot state

2019-06-10 Thread Nayna Jain
From: Claudio Carvalho 

The X.509 certificates trusted by the platform and other information
required to secure boot the OS kernel are wrapped in secure variables,
which are controlled by OPAL.

This patch adds support to read OPAL secure variables through
OPAL_SECVAR_GET call. It returns the metadata and data for a given secure
variable based on the unique key.

Since OPAL can support different types of backend which can vary in the
variable interpretation, a new OPAL API call named OPAL_SECVAR_BACKEND, is
added to retrieve the supported backend version. This helps the consumer
to know how to interpret the variable.

This support can be enabled using CONFIG_OPAL_SECVAR

Signed-off-by: Claudio Carvalho 
Signed-off-by: Nayna Jain 
---
This patch depends on a new OPAL call that is being added to skiboot.
The patch set that implements the new call has been posted to
https://patchwork.ozlabs.org/project/skiboot/list/?series=112868

 arch/powerpc/include/asm/opal-api.h  |  4 +-
 arch/powerpc/include/asm/opal-secvar.h   | 23 ++
 arch/powerpc/include/asm/opal.h  |  6 ++
 arch/powerpc/platforms/powernv/Kconfig   |  6 ++
 arch/powerpc/platforms/powernv/Makefile  |  1 +
 arch/powerpc/platforms/powernv/opal-call.c   |  2 +
 arch/powerpc/platforms/powernv/opal-secvar.c | 85 
 7 files changed, 126 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/include/asm/opal-secvar.h
 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 e1577cfa7186..a505e669b4b6 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -212,7 +212,9 @@
 #define OPAL_HANDLE_HMI2   166
 #defineOPAL_NX_COPROC_INIT 167
 #define OPAL_XIVE_GET_VP_STATE 170
-#define OPAL_LAST  170
+#define OPAL_SECVAR_GET 173
+#define OPAL_SECVAR_BACKEND 177
+#define OPAL_LAST  177
 
 #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-secvar.h 
b/arch/powerpc/include/asm/opal-secvar.h
new file mode 100644
index ..b677171a0368
--- /dev/null
+++ b/arch/powerpc/include/asm/opal-secvar.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PowerNV definitions for secure variables OPAL API.
+ *
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Claudio Carvalho 
+ *
+ */
+#ifndef OPAL_SECVAR_H
+#define OPAL_SECVAR_H
+
+enum {
+   BACKEND_NONE = 0,
+   BACKEND_TC_COMPAT_V1,
+};
+
+extern int opal_get_variable(u8 *key, unsigned long ksize,
+u8 *metadata, unsigned long *mdsize,
+u8 *data, unsigned long *dsize);
+
+extern int opal_variable_version(unsigned long *backend);
+
+#endif
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 4cc37e708bc7..57d2c2356eda 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -394,6 +394,12 @@ void opal_powercap_init(void);
 void opal_psr_init(void);
 void opal_sensor_groups_init(void);
 
+extern int opal_secvar_get(uint64_t k_key, uint64_t k_key_len,
+  uint64_t k_metadata, uint64_t k_metadata_size,
+  uint64_t k_data, uint64_t k_data_size);
+
+extern int opal_secvar_backend(uint64_t k_backend);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_OPAL_H */
diff --git a/arch/powerpc/platforms/powernv/Kconfig 
b/arch/powerpc/platforms/powernv/Kconfig
index 850eee860cf2..65b060539b5c 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -47,3 +47,9 @@ config PPC_VAS
  VAS adapters are found in POWER9 based systems.
 
  If unsure, say N.
+
+config OPAL_SECVAR
+   bool "OPAL Secure Variables"
+   depends on PPC_POWERNV
+   help
+ This enables the kernel to access OPAL secure variables.
diff --git a/arch/powerpc/platforms/powernv/Makefile 
b/arch/powerpc/platforms/powernv/Makefile
index da2e99efbd04..6651c742e530 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_PERF_EVENTS) += opal-imc.o
 obj-$(CONFIG_PPC_MEMTRACE) += memtrace.o
 obj-$(CONFIG_PPC_VAS)  += vas.o vas-window.o vas-debug.o
 obj-$(CONFIG_OCXL_BASE)+= ocxl.o
+obj-$(CONFIG_OPAL_SECVAR) += opal-secvar.o
diff --git a/arch/powerpc/platforms/powernv/opal-call.c 
b/arch/powerpc/platforms/powernv/opal-call.c
index 36c8fa3647a2..0445980f294f 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -288,3 +288,5 @@ OPAL_CALL(opal_pci_set_pbcq_

[PATCH v3 2/3] powerpc/powernv: detect the secure boot mode of the system

2019-06-10 Thread Nayna Jain
PowerNV secure boot defines different IMA policies based on the secure
boot state of the system.

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

Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/secboot.h   | 21 
 arch/powerpc/platforms/powernv/Makefile  |  3 +-
 arch/powerpc/platforms/powernv/secboot.c | 61 
 3 files changed, 84 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/include/asm/secboot.h
 create mode 100644 arch/powerpc/platforms/powernv/secboot.c

diff --git a/arch/powerpc/include/asm/secboot.h 
b/arch/powerpc/include/asm/secboot.h
new file mode 100644
index ..1904fb4a3352
--- /dev/null
+++ b/arch/powerpc/include/asm/secboot.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PowerPC secure boot definitions
+ *
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ */
+#ifndef POWERPC_SECBOOT_H
+#define POWERPC_SECBOOT_H
+
+#if defined(CONFIG_OPAL_SECVAR)
+extern bool get_powerpc_sb_mode(void);
+#else
+static inline bool get_powerpc_sb_mode(void)
+{
+   return false;
+}
+#endif
+
+#endif
diff --git a/arch/powerpc/platforms/powernv/Makefile 
b/arch/powerpc/platforms/powernv/Makefile
index 6651c742e530..74705a3fc474 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -4,6 +4,7 @@ obj-y   += idle.o opal-rtc.o opal-nvram.o 
opal-lpc.o opal-flash.o
 obj-y  += rng.o opal-elog.o opal-dump.o opal-sysparam.o 
opal-sensor.o
 obj-y  += opal-msglog.o opal-hmi.o opal-power.o opal-irqchip.o
 obj-y  += opal-kmsg.o opal-powercap.o opal-psr.o 
opal-sensor-groups.o
+obj-y  += secboot.o
 
 obj-$(CONFIG_SMP)  += smp.o subcore.o subcore-asm.o
 obj-$(CONFIG_PCI)  += pci.o pci-ioda.o npu-dma.o pci-ioda-tce.o
@@ -16,4 +17,4 @@ obj-$(CONFIG_PERF_EVENTS) += opal-imc.o
 obj-$(CONFIG_PPC_MEMTRACE) += memtrace.o
 obj-$(CONFIG_PPC_VAS)  += vas.o vas-window.o vas-debug.o
 obj-$(CONFIG_OCXL_BASE)+= ocxl.o
-obj-$(CONFIG_OPAL_SECVAR) += opal-secvar.o
+obj-$(CONFIG_OPAL_SECVAR) += opal-secvar.o secboot.o
diff --git a/arch/powerpc/platforms/powernv/secboot.c 
b/arch/powerpc/platforms/powernv/secboot.c
new file mode 100644
index ..9199e520ebed
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/secboot.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * secboot.c
+ *  - util function to get powerpc secboot state
+ */
+#include 
+#include 
+#include 
+#include 
+
+bool get_powerpc_sb_mode(void)
+{
+   u8 secure_boot_name[] = "SecureBoot";
+   u8 setup_mode_name[] = "SetupMode";
+   u8 secboot, setupmode;
+   unsigned long size = sizeof(secboot);
+   int status;
+   unsigned long version;
+
+   status = opal_variable_version();
+   if ((status != OPAL_SUCCESS) || (version != BACKEND_TC_COMPAT_V1)) {
+   pr_info("secboot: error retrieving compatible backend\n");
+   return false;
+   }
+
+   status = opal_get_variable(secure_boot_name, sizeof(secure_boot_name),
+  NULL, NULL, , );
+
+   /*
+* For now assume all failures reading the SecureBoot variable implies
+* secure boot is not enabled. Later differentiate failure types.
+*/
+   if (status != OPAL_SUCCESS) {
+   secboot = 0;
+   setupmode = 0;
+   goto out;
+   }
+
+   size = sizeof(setupmode);
+   status = opal_get_variable(setup_mode_name, sizeof(setup_mode_name),
+  NULL, NULL,  , );
+
+   /*
+* Failure to read the SetupMode variable does not prevent
+* secure boot mode
+*/
+   if (status != OPAL_SUCCESS)
+   setupmode = 0;
+
+out:
+   if ((secboot == 0) || (setupmode == 1)) {
+   pr_info("secboot: secureboot mode disabled\n");
+   return false;
+   }
+
+   pr_info("secboot: secureboot mode enabled\n");
+   return true;
+}
-- 
2.20.1



[PATCH v3 3/3] powerpc: Add support to initialize ima policy rules

2019-06-10 Thread Nayna Jain
PowerNV secure boot relies on the kernel IMA security subsystem to
perform the OS kernel image signature verification. Since each secure
boot mode has different IMA policy requirements, dynamic definition of
the policy rules based on the runtime secure boot mode of the system is
required. On systems that support secure boot, but have it disabled,
only measurement policy rules of the kernel image and modules are
defined.

This patch defines the arch-specific implementation to retrieve the
secure boot mode of the system and accordingly configures the IMA policy
rules.

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

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

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 8c1c636308c8..9de77bb14f54 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -902,6 +902,20 @@ config PPC_MEM_KEYS
 
  If unsure, say y.
 
+config PPC_SECURE_BOOT
+   prompt "Enable PowerPC Secure Boot"
+   bool
+   default n
+   depends on PPC64
+   depends on OPAL_SECVAR
+   depends on IMA
+   depends on IMA_ARCH_POLICY
+   help
+ Linux on POWER with firmware secure boot enabled needs to define
+ security policies to extend secure boot to the OS.This config
+ allows user to enable OS Secure Boot on PowerPC systems that
+ have firmware secure boot support.
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 0ea6c4aa3a20..75c929b41341 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -131,6 +131,7 @@ ifdef CONFIG_IMA
 obj-y  += ima_kexec.o
 endif
 endif
+obj-$(CONFIG_PPC_SECURE_BOOT)  += ima_arch.o
 
 obj-$(CONFIG_AUDIT)+= audit.o
 obj64-$(CONFIG_AUDIT)  += compat_audit.o
diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
new file mode 100644
index ..1767bf6e6550
--- /dev/null
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * ima_arch.c
+ *  - initialize ima policies for PowerPC Secure Boot
+ */
+
+#include 
+#include 
+
+bool arch_ima_get_secureboot(void)
+{
+   bool sb_mode;
+
+   sb_mode = get_powerpc_sb_mode();
+   if (sb_mode)
+   return true;
+   else
+   return false;
+}
+
+/*
+ * File signature verification is not needed, include only measurements
+ */
+static const char *const default_arch_rules[] = {
+   "measure func=KEXEC_KERNEL_CHECK template=ima-modsig",
+   "measure func=MODULE_CHECK template=ima-modsig",
+   NULL
+};
+
+/* Both file signature verification and measurements are needed */
+static const char *const sb_arch_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 
template=ima-modsig",
+#if !IS_ENABLED(CONFIG_MODULE_SIG)
+   "appraise func=MODULE_CHECK appraise_type=imasig|modsig 
template=ima-modsig",
+#endif
+   NULL
+};
+
+/*
+ * On PowerPC, file measurements are to be added to the IMA measurement list
+ * irrespective of the secure boot state of the system. Signature verification
+ * is conditionally enabled based on the secure boot state.
+ */
+const char *const *arch_get_ima_policy(void)
+{
+   if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot())
+   return sb_arch_rules;
+   return default_arch_rules;
+}
diff --git a/include/linux/ima.h b/include/linux/ima.h
index fd9f7cf4cdf5..a01df076ecae 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -31,7 +31,8 @@ extern void ima_post_path_mknod(struct dentry *dentry);
 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 v2 1/3] powerpc/powernv: Add support for OPAL_SECVAR_GET

2019-04-08 Thread Nayna Jain
From: Claudio Carvalho 

The X.509 certificates trusted by the platform and other information
required to secure boot the OS kernel are wrapped in secure variables,
which are controlled by OPAL.

This patch adds support to read OPAL secure variables through
OPAL_SECVAR_GET call. It returns the data for a given secure variable
and vendor GUID. It can be configured using CONFIG_OPAL_SECVAR.

Signed-off-by: Claudio Carvalho 

---
This patch depends on a new OPAL call that is being added to skiboot.
The patch set that implements the new call has been posted to
https://patchwork.ozlabs.org/project/skiboot/list/?series=99805
---
 arch/powerpc/include/asm/opal-api.h  |   3 +-
 arch/powerpc/include/asm/opal-secvar.h   |  18 
 arch/powerpc/include/asm/opal.h  |   2 +
 arch/powerpc/platforms/powernv/Kconfig   |   6 ++
 arch/powerpc/platforms/powernv/Makefile  |   1 +
 arch/powerpc/platforms/powernv/opal-call.c   |   1 +
 arch/powerpc/platforms/powernv/opal-secvar.c | 107 +++
 7 files changed, 137 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/include/asm/opal-secvar.h
 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 870fb7b239ea..782eb20a08a7 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -210,7 +210,8 @@
 #define OPAL_PCI_GET_PBCQ_TUNNEL_BAR   164
 #define OPAL_PCI_SET_PBCQ_TUNNEL_BAR   165
 #defineOPAL_NX_COPROC_INIT 167
-#define OPAL_LAST  167
+#define OPAL_SECVAR_GET170
+#define OPAL_LAST  171
 
 #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-secvar.h 
b/arch/powerpc/include/asm/opal-secvar.h
new file mode 100644
index ..e3d5e4cbf3bc
--- /dev/null
+++ b/arch/powerpc/include/asm/opal-secvar.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PowerNV definitions for secure variables OPAL API.
+ *
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Claudio Carvalho 
+ *
+ */
+#ifndef OPAL_SECVAR_H
+#define OPAL_SECVAR_H
+
+#include 
+
+extern efi_status_t
+opal_get_variable(efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
+ unsigned long *data_size, void *data);
+
+#endif
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index a55b01c90bb1..eb654baf8764 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -385,6 +385,8 @@ void opal_powercap_init(void);
 void opal_psr_init(void);
 void opal_sensor_groups_init(void);
 
+extern int opal_secvar_get(uint64_t name, uint64_t vendor, uint64_t attr,
+  uint64_t data_size, uint64_t data);
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_OPAL_H */
diff --git a/arch/powerpc/platforms/powernv/Kconfig 
b/arch/powerpc/platforms/powernv/Kconfig
index 850eee860cf2..65b060539b5c 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -47,3 +47,9 @@ config PPC_VAS
  VAS adapters are found in POWER9 based systems.
 
  If unsure, say N.
+
+config OPAL_SECVAR
+   bool "OPAL Secure Variables"
+   depends on PPC_POWERNV
+   help
+ This enables the kernel to access OPAL secure variables.
diff --git a/arch/powerpc/platforms/powernv/Makefile 
b/arch/powerpc/platforms/powernv/Makefile
index da2e99efbd04..1511d836fd19 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_PERF_EVENTS) += opal-imc.o
 obj-$(CONFIG_PPC_MEMTRACE) += memtrace.o
 obj-$(CONFIG_PPC_VAS)  += vas.o vas-window.o vas-debug.o
 obj-$(CONFIG_OCXL_BASE)+= ocxl.o
+obj-$(CONFIG_OPAL_SECVAR)  += opal-secvar.o
diff --git a/arch/powerpc/platforms/powernv/opal-call.c 
b/arch/powerpc/platforms/powernv/opal-call.c
index daad8c45c8e7..eafd8f690b7a 100644
--- a/arch/powerpc/platforms/powernv/opal-call.c
+++ b/arch/powerpc/platforms/powernv/opal-call.c
@@ -282,3 +282,4 @@ OPAL_CALL(opal_pci_set_pbcq_tunnel_bar, 
OPAL_PCI_SET_PBCQ_TUNNEL_BAR);
 OPAL_CALL(opal_sensor_read_u64,OPAL_SENSOR_READ_U64);
 OPAL_CALL(opal_sensor_group_enable,OPAL_SENSOR_GROUP_ENABLE);
 OPAL_CALL(opal_nx_coproc_init, OPAL_NX_COPROC_INIT);
+OPAL_CALL(opal_secvar_get, OPAL_SECVAR_GET);
diff --git a/arch/powerpc/platforms/powernv/opal-secvar.c 
b/arch/powerpc/platforms/powernv/opal-secvar.c
new file mode 100644
index ..3ba02c9503f7
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-secvar.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PowerNV code for secure 

[PATCH v2 2/3] powerpc/powernv: detect the secure boot mode of the system

2019-04-08 Thread Nayna Jain
PowerNV secure boot defines different IMA policies based on the secure
boot state of the system.

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

Signed-off-by: Nayna Jain 
---
 arch/powerpc/include/asm/secboot.h   | 21 +
 arch/powerpc/platforms/powernv/Makefile  |  3 +-
 arch/powerpc/platforms/powernv/secboot.c | 54 
 3 files changed, 77 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/include/asm/secboot.h
 create mode 100644 arch/powerpc/platforms/powernv/secboot.c

diff --git a/arch/powerpc/include/asm/secboot.h 
b/arch/powerpc/include/asm/secboot.h
new file mode 100644
index ..1904fb4a3352
--- /dev/null
+++ b/arch/powerpc/include/asm/secboot.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PowerPC secure boot definitions
+ *
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ */
+#ifndef POWERPC_SECBOOT_H
+#define POWERPC_SECBOOT_H
+
+#if defined(CONFIG_OPAL_SECVAR)
+extern bool get_powerpc_sb_mode(void);
+#else
+static inline bool get_powerpc_sb_mode(void)
+{
+   return false;
+}
+#endif
+
+#endif
diff --git a/arch/powerpc/platforms/powernv/Makefile 
b/arch/powerpc/platforms/powernv/Makefile
index 1511d836fd19..e3224f1019eb 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -4,6 +4,7 @@ obj-y   += idle.o opal-rtc.o opal-nvram.o 
opal-lpc.o opal-flash.o
 obj-y  += rng.o opal-elog.o opal-dump.o opal-sysparam.o 
opal-sensor.o
 obj-y  += opal-msglog.o opal-hmi.o opal-power.o opal-irqchip.o
 obj-y  += opal-kmsg.o opal-powercap.o opal-psr.o 
opal-sensor-groups.o
+obj-y  += secboot.o
 
 obj-$(CONFIG_SMP)  += smp.o subcore.o subcore-asm.o
 obj-$(CONFIG_PCI)  += pci.o pci-ioda.o npu-dma.o pci-ioda-tce.o
@@ -16,4 +17,4 @@ obj-$(CONFIG_PERF_EVENTS) += opal-imc.o
 obj-$(CONFIG_PPC_MEMTRACE) += memtrace.o
 obj-$(CONFIG_PPC_VAS)  += vas.o vas-window.o vas-debug.o
 obj-$(CONFIG_OCXL_BASE)+= ocxl.o
-obj-$(CONFIG_OPAL_SECVAR)  += opal-secvar.o
+obj-$(CONFIG_OPAL_SECVAR)  += opal-secvar.o secboot.o
diff --git a/arch/powerpc/platforms/powernv/secboot.c 
b/arch/powerpc/platforms/powernv/secboot.c
new file mode 100644
index ..a9c5717bb78e
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/secboot.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * secboot.c
+ *  - util functions to get powerpc secboot state
+ */
+#include 
+#include 
+#include 
+
+bool get_powerpc_sb_mode(void)
+{
+   efi_char16_t efi_SecureBoot_name[] = L"SecureBoot";
+   efi_char16_t efi_SetupMode_name[] = L"SetupMode";
+   efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
+   efi_status_t status;
+   u8 secboot, setupmode;
+   unsigned long size = sizeof(secboot);
+
+   status = opal_get_variable(efi_SecureBoot_name, _variable_guid,
+ NULL, , );
+
+   /*
+* For now assume all failures reading the SecureBoot variable implies
+* secure boot is not enabled. Later differentiate failure types.
+*/
+   if (status != EFI_SUCCESS) {
+   secboot = 0;
+   setupmode = 0;
+   goto out;
+   }
+
+   size = sizeof(setupmode);
+   status = opal_get_variable(efi_SetupMode_name, _variable_guid,
+ NULL, , );
+
+   /*
+* Failure to read the SetupMode variable does not prevent
+* secure boot mode
+*/
+   if (status != EFI_SUCCESS)
+   setupmode = 0;
+
+out:
+   if ((secboot == 0) || (setupmode == 1)) {
+   pr_info("secboot: secureboot mode disabled\n");
+   return false;
+   }
+
+   pr_info("secboot: secureboot mode enabled\n");
+   return true;
+}
-- 
2.20.1



[PATCH v2 3/3] powerpc: Add support to initialize ima policy rules

2019-04-08 Thread Nayna Jain
PowerNV secure boot relies on the kernel IMA security subsystem to
perform the OS kernel image signature verification. Since each secure
boot mode has different IMA policy requirements, dynamic definition of
the policy rules based on the runtime secure boot mode of the system is
required. On systems that support secure boot, but have it disabled,
only measurement policy rules of the kernel image and modules are
defined.

This patch defines the arch-specific implementation to retrieve the
secure boot mode of the system and accordingly configures the IMA policy
rules.

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

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

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2d0be82c3061..7407af79ed8a 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -901,6 +901,20 @@ config PPC_MEM_KEYS
 
  If unsure, say y.
 
+config PPC_SECURE_BOOT
+   prompt "Enable PowerPC Secure Boot"
+   bool
+   default n
+   depends on PPC64
+   depends on OPAL_SECVAR
+   depends on IMA
+   depends on IMA_ARCH_POLICY
+   help
+ Linux on POWER with firmware secure boot enabled needs to define
+ security policies to extend secure boot to the OS.
+ This config allows user to enable OS Secure Boot on PowerPC systems
+ that have firmware secure boot support.
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index cddadccf551d..fcbc7a94888b 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -119,6 +119,7 @@ ifdef CONFIG_IMA
 obj-y  += ima_kexec.o
 endif
 endif
+obj-$(CONFIG_PPC_SECURE_BOOT)  += ima_arch.o
 
 obj-$(CONFIG_AUDIT)+= audit.o
 obj64-$(CONFIG_AUDIT)  += compat_audit.o
diff --git a/arch/powerpc/kernel/ima_arch.c b/arch/powerpc/kernel/ima_arch.c
new file mode 100644
index ..871b321656fb
--- /dev/null
+++ b/arch/powerpc/kernel/ima_arch.c
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * ima_arch.c
+ *  - initialize ima policies for PowerPC Secure Boot
+ */
+
+#include 
+#include 
+
+bool arch_ima_get_secureboot(void)
+{
+   bool sb_mode;
+
+   sb_mode = get_powerpc_sb_mode();
+   if (sb_mode)
+   return true;
+   else
+   return false;
+}
+
+/*
+ * File signature verification is not needed, include only measurements
+ */
+static const char *const default_arch_rules[] = {
+   "measure func=KEXEC_KERNEL_CHECK",
+   "measure func=MODULE_CHECK",
+   NULL
+};
+
+/* Both file signature verification and measurements are needed */
+static const char *const sb_arch_rules[] = {
+   "measure func=KEXEC_KERNEL_CHECK",
+   "measure func=MODULE_CHECK",
+   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig",
+#if !IS_ENABLED(CONFIG_MODULE_SIG)
+   "appraise func=MODULE_CHECK appraise_type=imasig",
+#endif
+   NULL
+};
+
+/*
+ * On PowerPC, file measurements are to be added to the IMA measurement list
+ * irrespective of the secure boot state of the system. Signature verification
+ * is conditionally enabled based on the secure boot state.
+ */
+const char *const *arch_get_ima_policy(void)
+{
+   if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot())
+   return sb_arch_rules;
+   return default_arch_rules;
+}
diff --git a/include/linux/ima.h b/include/linux/ima.h
index dc12fbcf484c..ab81a204cf4c 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -31,7 +31,8 @@ extern void ima_post_path_mknod(struct dentry *dentry);
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
 
-#if defined(CONFIG_X86) && defined(CONFIG_EFI)
+#if (defined(CONFIG_X86) && defined(CONFIG_EFI)) \
+|| 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 v2 0/3] powerpc: Enabling secure boot on powernv systems - Part 1

2019-04-08 Thread Nayna Jain
This patch set is part of a series that implements secure boot on PowerNV
systems.

In order to verify the OS kernel on PowerNV, secure boot requires X.509
certificates trusted by the platform, the secure boot modes, and several
other pieces of information. These are stored in secure variables
controlled by OPAL, also known as OPAL secure variables.

The IMA architecture specific policy support on Power is dependent on OPAL
runtime services to access secure variables. Instead of directly accessing
the OPAL runtime services, version 1[1] of this patch set relied upon the
EFI hooks. This version drops that dependency and calls the OPAL runtime
services directly.

Exposing the OPAL secure variables to userspace will be posted as a
separate patch set, allowing the IMA architecture specific policy on Power
to be upstreamed independently.

This patch set adds the following features:

1. Add support for OPAL Runtime API to access secure variables controlled
by OPAL.
2. Define IMA arch-specific policies based on the secure boot state and
mode of the system. On secure boot enabled powernv systems, the OS kernel
signature will be verified by IMA appraisal.

[1] https://patchwork.kernel.org/cover/10882149/

Changelog:

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

Claudio Carvalho (1):
  powerpc/powernv: Add support for OPAL_SECVAR_GET

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

 arch/powerpc/Kconfig |  14 +++
 arch/powerpc/include/asm/opal-api.h  |   3 +-
 arch/powerpc/include/asm/opal-secvar.h   |  18 
 arch/powerpc/include/asm/opal.h  |   2 +
 arch/powerpc/include/asm/secboot.h   |  21 
 arch/powerpc/kernel/Makefile |   1 +
 arch/powerpc/kernel/ima_arch.c   |  54 ++
 arch/powerpc/platforms/powernv/Kconfig   |   6 ++
 arch/powerpc/platforms/powernv/Makefile  |   2 +
 arch/powerpc/platforms/powernv/opal-call.c   |   1 +
 arch/powerpc/platforms/powernv/opal-secvar.c | 107 +++
 arch/powerpc/platforms/powernv/secboot.c |  54 ++
 include/linux/ima.h  |   3 +-
 13 files changed, 284 insertions(+), 2 deletions(-)
 create mode 100644 arch/powerpc/include/asm/opal-secvar.h
 create mode 100644 arch/powerpc/include/asm/secboot.h
 create mode 100644 arch/powerpc/kernel/ima_arch.c
 create mode 100644 arch/powerpc/platforms/powernv/opal-secvar.c
 create mode 100644 arch/powerpc/platforms/powernv/secboot.c

-- 
2.20.1



[PATCH v2a 5/7] efi: Import certificates from UEFI Secure Boot

2018-12-12 Thread Nayna Jain
From: Josh Boyer 

Secure Boot stores a list of allowed certificates in the 'db' variable.
This patch imports those certificates into the platform keyring. The shim
UEFI bootloader has a similar certificate list stored in the 'MokListRT'
variable. We import those as well.

Secure Boot also maintains a list of disallowed certificates in the 'dbx'
variable. We load those certificates into the system blacklist keyring
and forbid any kernel signed with those from loading.

[zo...@linux.ibm.com: dropped Josh's original patch description]
Signed-off-by: Josh Boyer 
Signed-off-by: David Howells 
Signed-off-by: Nayna Jain 
Acked-by: Serge Hallyn 
Signed-off-by: Mimi Zohar 
---
Changelog:

v2a:
- refactored uefi_blacklist_x509_tbs() and  uefi_blacklist_binary()

v2:
- Fixed the checkpatch.pl warnings

v0:
- This patch replaces the loading of certificates onto the secondary
  keyring with platform keyring
- removed the CONFIG LOAD_UEFI_KEYS
- moved the file load_uefi.o from certs to security/integrity/platform_certs

 security/integrity/Makefile   |   5 +-
 security/integrity/platform_certs/load_uefi.c | 169 ++
 2 files changed, 173 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/platform_certs/load_uefi.c

diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 6ee9058866cd..86df9aba8c0f 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -10,7 +10,10 @@ integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
 integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o \
- platform_certs/efi_parser.o
+ platform_certs/efi_parser.o \
+ platform_certs/load_uefi.o
+obj-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/load_uefi.o
+$(obj)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/platform_certs/load_uefi.c 
b/security/integrity/platform_certs/load_uefi.c
new file mode 100644
index ..8ceafa58d98c
--- /dev/null
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -0,0 +1,169 @@
+// 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;
+
+/*
+ * Get a certificate list blob from the named EFI variable.
+ */
+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
+ unsigned long *size)
+{
+   efi_status_t status;
+   unsigned long lsize = 4;
+   unsigned long tmpdb[4];
+   void *db;
+
+   status = efi.get_variable(name, guid, NULL, , );
+   if (status != EFI_BUFFER_TOO_SMALL) {
+   pr_err("Couldn't get size: 0x%lx\n", status);
+   return NULL;
+   }
+
+   db = kmalloc(lsize, GFP_KERNEL);
+   if (!db)
+   return NULL;
+
+   status = efi.get_variable(name, guid, NULL, , db);
+   if (status != EFI_SUCCESS) {
+   kfree(db);
+   pr_err("Error reading db var: 0x%lx\n", status);
+   return NULL;
+   }
+
+   *size = lsize;
+   return db;
+}
+
+/*
+ * 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.
+ */
+static __init efi_ele

Re: [PATCH v2 5/7] efi: Import certificates from UEFI Secure Boot

2018-12-12 Thread Nayna Jain




On 12/12/2018 12:17 AM, James Morris wrote:

On Sun, 9 Dec 2018, Nayna Jain wrote:


+/*
+ * Blacklist an X509 TBS hash.
+ */
+static __init void uefi_blacklist_x509_tbs(const char *source,
+  const void *data, size_t len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(4 + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, "tbs:", 4);
+   p += 4;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfree(hash);
+}
+
+/*
+ * Blacklist the hash of an executable.
+ */
+static __init void uefi_blacklist_binary(const char *source,
+const void *data, size_t len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(4 + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, "bin:", 4);
+   p += 4;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfree(hash);
+}


These could be refactored into one function.




Thanks James for reviewing.

Yes, the code should be refactored.  However, I think making it a single 
function would require adding a new field to the function callback 
definitions as well. Probably, a simpler approach would be to define a 
common function uefi_blacklist_hash(...)  which can then be used by the 
two functions uefi_blacklist_x509_tbs(...) and 
uefi_blacklist_binary(...). These two functions now act as wrapper 
functions. Below is the example code:


+/*
+ * Blacklist a hash.
+ */
+static __init void uefi_blacklist_hash(const char *source, const void 
*data,

+ size_t len, 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);
+}


Thanks & Regards,
   - Nayna





[PATCH v2 1/7] integrity: Define a trusted platform keyring

2018-12-08 Thread Nayna Jain
On secure boot enabled systems, a verified kernel may need to kexec
additional kernels. For example, it may be used as a bootloader needing
to kexec a target kernel or it may need to kexec a crashdump kernel. In
such cases, it may want to verify the signature of the next kernel
image.

It is further possible that the kernel image is signed with third party
keys which are stored as platform or firmware keys in the 'db' variable.
The kernel, however, can not directly verify these platform keys, and an
administrator may therefore not want to trust them for arbitrary usage.
In order to differentiate platform keys from other keys and provide the
necessary separation of trust, the kernel needs an additional keyring to
store platform keys.

This patch creates the new keyring called ".platform" to isolate keys
provided by platform from keys by kernel. These keys are used to
facilitate signature verification during kexec. Since the scope of this
keyring is only the platform/firmware keys, it cannot be updated from
userspace.

This keyring can be enabled by setting CONFIG_INTEGRITY_PLATFORM_KEYRING.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Acked-by: Serge Hallyn 
---
 security/integrity/Kconfig | 11 +
 security/integrity/Makefile|  1 +
 security/integrity/digsig.c| 48 +++---
 security/integrity/integrity.h |  3 +-
 .../integrity/platform_certs/platform_keyring.c| 35 
 5 files changed, 83 insertions(+), 15 deletions(-)
 create mode 100644 security/integrity/platform_certs/platform_keyring.c

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index da9565891738..4b4d2aeef539 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -51,6 +51,17 @@ config INTEGRITY_TRUSTED_KEYRING
   .evm keyrings be signed by a key on the system trusted
   keyring.
 
+config INTEGRITY_PLATFORM_KEYRING
+bool "Provide keyring for platform/firmware trusted keys"
+depends on INTEGRITY_ASYMMETRIC_KEYS
+depends on SYSTEM_BLACKLIST_KEYRING
+depends on EFI
+help
+ Provide a separate, distinct keyring for platform trusted keys, which
+ the kernel automatically populates during initialization from values
+ provided by the platform for verifying the kexec'ed kerned image
+ and, possibly, the initramfs signature.
+
 config INTEGRITY_AUDIT
bool "Enables integrity auditing support "
depends on AUDIT
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 04d6e462b079..046ffc1bb42d 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -9,6 +9,7 @@ integrity-y := iint.o
 integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
+integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 5eacba858e4b..fef2a858300c 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -35,6 +35,7 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] 
= {
".ima",
 #endif
"_module",
+   ".platform",
 };
 
 #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
@@ -73,12 +74,39 @@ int integrity_digsig_verify(const unsigned int id, const 
char *sig, int siglen,
return -EOPNOTSUPP;
 }
 
-int __init integrity_init_keyring(const unsigned int id)
+static int __integrity_init_keyring(const unsigned int id, key_perm_t perm,
+   struct key_restriction *restriction)
 {
const struct cred *cred = current_cred();
+   int err = 0;
+
+   keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
+   KGIDT_INIT(0), cred, perm,
+   KEY_ALLOC_NOT_IN_QUOTA,
+   restriction, NULL);
+   if (IS_ERR(keyring[id])) {
+   err = PTR_ERR(keyring[id]);
+   pr_info("Can't allocate %s keyring (%d)\n",
+   keyring_name[id], err);
+   keyring[id] = NULL;
+   }
+
+   return err;
+}
+
+int __init integrity_init_keyring(const unsigned int id)
+{
struct key_restriction *restriction;
+   key_perm_t perm;
int err = 0;
 
+   if (id == INTEGRITY_KEYRING_PLATFORM) {
+   restriction = NULL;
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
+   | KEY_USR_READ | KEY_USR_SEARCH;
+   goto out;
+   }
+
if (!IS_ENABLED(CONFIG

[PATCH v2 6/7] efi: Allow the "db" UEFI variable to be suppressed

2018-12-08 Thread Nayna Jain
From: Josh Boyer 

If a user tells shim to not use the certs/hashes in the UEFI db variable
for verification purposes, shim will set a UEFI variable called
MokIgnoreDB. Have the uefi import code look for this and ignore the db
variable if it is found.

Signed-off-by: Josh Boyer 
Signed-off-by: David Howells 
Acked-by: Nayna Jain 
Acked-by: Serge Hallyn 
---
Changelog:

v0:
- No changes

v2:
- Fixed the checkpatch.pl warnings

 security/integrity/platform_certs/load_uefi.c | 45 +--
 1 file changed, 35 insertions(+), 10 deletions(-)

diff --git a/security/integrity/platform_certs/load_uefi.c 
b/security/integrity/platform_certs/load_uefi.c
index acd9db90dde7..8bd2e9b421e1 100644
--- a/security/integrity/platform_certs/load_uefi.c
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -16,6 +16,26 @@ static efi_guid_t efi_cert_x509_sha256_guid __initdata =
 static efi_guid_t efi_cert_sha256_guid __initdata = EFI_CERT_SHA256_GUID;
 
 /*
+ * Look to see if a UEFI variable called MokIgnoreDB exists and return true if
+ * it does.
+ *
+ * This UEFI variable is set by the shim if a user tells the shim to not use
+ * the certs/hashes in the UEFI db variable for verification purposes.  If it
+ * is set, we should ignore the db variable also and the true return indicates
+ * this.
+ */
+static __init bool uefi_check_ignore_db(void)
+{
+   efi_status_t status;
+   unsigned int db = 0;
+   unsigned long size = sizeof(db);
+   efi_guid_t guid = EFI_SHIM_LOCK_GUID;
+
+   status = efi.get_variable(L"MokIgnoreDB", , NULL, , );
+   return status == EFI_SUCCESS;
+}
+
+/*
  * Get a certificate list blob from the named EFI variable.
  */
 static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
@@ -116,7 +136,9 @@ static __init efi_element_handler_t 
get_handler_for_dbx(const efi_guid_t *
 }
 
 /*
- * Load the certs contained in the UEFI databases
+ * Load the certs contained in the UEFI databases into the secondary trusted
+ * keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist
+ * keyring.
  */
 static int __init load_uefi_certs(void)
 {
@@ -132,15 +154,18 @@ static int __init load_uefi_certs(void)
/* Get db, MokListRT, and dbx.  They might not exist, so it isn't
 * an error if we can't get them.
 */
-   db = get_cert_list(L"db", _var, );
-   if (!db) {
-   pr_err("Couldn't get UEFI db list\n");
-   } else {
-   rc = parse_efi_signature_list("UEFI:db",
- db, dbsize, get_handler_for_db);
-   if (rc)
-   pr_err("Couldn't parse db signatures: %d\n", rc);
-   kfree(db);
+   if (!uefi_check_ignore_db()) {
+   db = get_cert_list(L"db", _var, );
+   if (!db) {
+   pr_err("MODSIGN: Couldn't get UEFI db list\n");
+   } else {
+   rc = parse_efi_signature_list("UEFI:db",
+   db, dbsize, get_handler_for_db);
+   if (rc)
+   pr_err("Couldn't parse db signatures: %d\n",
+  rc);
+   kfree(db);
+   }
}
 
mok = get_cert_list(L"MokListRT", _var, );
-- 
2.13.6



[PATCH v2 4/7] efi: Add an EFI signature blob parser

2018-12-08 Thread Nayna Jain
From: Dave Howells 

Add a function to parse an EFI signature blob looking for elements of
interest. A list is made up of a series of sublists, where all the
elements in a sublist are of the same type, but sublists can be of
different types.

For each sublist encountered, the function pointed to by the
get_handler_for_guid argument is called with the type specifier GUID and
returns either a pointer to a function to handle elements of that type or
NULL if the type is not of interest.

If the sublist is of interest, each element is passed to the handler
function in turn.

Signed-off-by: David Howells 
Signed-off-by: Nayna Jain 
Acked-by: Serge Hallyn 
---
Changelog:

v0:
- removed the CONFIG EFI_SIGNATURE_LIST_PARSER
- moved efi_parser.c from certs to security/integrity/platform_certs
  directory

v2:
- Fixed the checkpatch.pl warnings

 include/linux/efi.h|   9 +++
 security/integrity/Makefile|   3 +-
 security/integrity/platform_certs/efi_parser.c | 108 +
 3 files changed, 119 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/platform_certs/efi_parser.c

diff --git a/include/linux/efi.h b/include/linux/efi.h
index 214516b29b36..c3206b134137 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1141,6 +1141,15 @@ extern int efi_memattr_apply_permissions(struct 
mm_struct *mm,
 char * __init efi_md_typeattr_format(char *buf, size_t size,
 const efi_memory_desc_t *md);
 
+
+typedef void (*efi_element_handler_t)(const char *source,
+ const void *element_data,
+ size_t element_size);
+extern int __init parse_efi_signature_list(
+   const char *source,
+   const void *data, size_t size,
+   efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *));
+
 /**
  * efi_range_is_wc - check the WC bit on an address range
  * @start: starting kvirt address
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 046ffc1bb42d..6ee9058866cd 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -9,7 +9,8 @@ integrity-y := iint.o
 integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 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_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o \
+ platform_certs/efi_parser.o
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/platform_certs/efi_parser.c 
b/security/integrity/platform_certs/efi_parser.c
new file mode 100644
index ..18f01f36fe6a
--- /dev/null
+++ b/security/integrity/platform_certs/efi_parser.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* EFI signature/key/certificate list parser
+ *
+ * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ */
+
+#define pr_fmt(fmt) "EFI: "fmt
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * parse_efi_signature_list - Parse an EFI signature list for certificates
+ * @source: The source of the key
+ * @data: The data blob to parse
+ * @size: The size of the data blob
+ * @get_handler_for_guid: Get the handler func for the sig type (or NULL)
+ *
+ * Parse an EFI signature list looking for elements of interest.  A list is
+ * made up of a series of sublists, where all the elements in a sublist are of
+ * the same type, but sublists can be of different types.
+ *
+ * For each sublist encountered, the @get_handler_for_guid function is called
+ * with the type specifier GUID and returns either a pointer to a function to
+ * handle elements of that type or NULL if the type is not of interest.
+ *
+ * If the sublist is of interest, each element is passed to the handler
+ * function in turn.
+ *
+ * Error EBADMSG is returned if the list doesn't parse correctly and 0 is
+ * returned if the list was parsed correctly.  No error can be returned from
+ * the @get_handler_for_guid function or the element handler function it
+ * returns.
+ */
+int __init parse_efi_signature_list(
+   const char *source,
+   const void *data, size_t size,
+   efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *))
+{
+   efi_element_handler_t handler;
+   unsigned int offs = 0;
+
+   pr_devel("-->%s(,%zu)\n", __func__, size);
+
+   while (size > 0) {
+   const efi_signature_data_t *elem;
+   efi_signature_list_t list;
+   size_t lsize, esize, hsize, elsize;
+
+   if (size < sizeof(list))
+   return -EBADMSG;
+
+   memcpy(, data, sizeof(list));
+ 

[PATCH v2 7/7] ima: Support platform keyring for kernel appraisal

2018-12-08 Thread Nayna Jain
On secure boot enabled systems, the bootloader verifies the kernel
image and possibly the initramfs signatures based on a set of keys. A
soft reboot(kexec) of the system, with the same kernel image and
initramfs, requires access to the original keys to verify the
signatures.

This patch allows IMA-appraisal access to those original keys, now
loaded on the platform keyring, needed for verifying the kernel image
and initramfs signatures.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Acked-by: Serge Hallyn 
- replace 'rc' with 'xattr_len' when calling integrity_digsig_verify()
with INTEGRITY_KEYRING_IMA for readability
Suggested-by: Serge Hallyn 
---
Changelog:

v2:
- replace 'rc' with 'xattr_len' when calling integrity_digsig_verify()
with INTEGRITY_KEYRING_IMA for readability

 security/integrity/ima/ima_appraise.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index deec1804a00a..e8f520450895 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -289,12 +289,21 @@ int ima_appraise_measurement(enum ima_hooks func,
case EVM_IMA_XATTR_DIGSIG:
set_bit(IMA_DIGSIG, >atomic_flags);
rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
-(const char *)xattr_value, rc,
+(const char *)xattr_value,
+xattr_len,
 iint->ima_hash->digest,
 iint->ima_hash->length);
if (rc == -EOPNOTSUPP) {
status = INTEGRITY_UNKNOWN;
-   } else if (rc) {
+   break;
+   }
+   if (rc && func == KEXEC_KERNEL_CHECK)
+   rc = integrity_digsig_verify(INTEGRITY_KEYRING_PLATFORM,
+(const char *)xattr_value,
+xattr_len,
+iint->ima_hash->digest,
+iint->ima_hash->length);
+   if (rc) {
cause = "invalid-signature";
status = INTEGRITY_FAIL;
} else {
-- 
2.13.6



[PATCH v2 5/7] efi: Import certificates from UEFI Secure Boot

2018-12-08 Thread Nayna Jain
From: Josh Boyer 

New Patch Description:
==

Secure Boot stores a list of allowed certificates in the 'db' variable.
This patch imports those certificates into the platform keyring. The shim
UEFI bootloader has a similar certificate list stored in the 'MokListRT'
variable. We import those as well.

Secure Boot also maintains a list of disallowed certificates in the 'dbx'
variable. We load those certificates into the system blacklist keyring
and forbid any kernel signed with those from loading.

Original Patch Description:


Secure Boot stores a list of allowed certificates in the 'db' variable.
This imports those certificates into the system trusted keyring.  This
allows for a third party signing certificate to be used in conjunction
with signed modules. By importing the public certificate into the 'db'
variable, a user can allow a module signed with that certificate to
load. The shim UEFI bootloader has a similar certificate list stored
in the 'MokListRT' variable. We import those as well.

Secure Boot also maintains a list of disallowed certificates in the 'dbx'
variable. We load those certificates into the newly introduced system
blacklist keyring and forbid any module signed with those from loading and
forbid the use within the kernel of any key with a matching hash.

This facility is enabled by setting CONFIG_LOAD_UEFI_KEYS.

Signed-off-by: Josh Boyer 
Signed-off-by: David Howells 
Signed-off-by: Nayna Jain 
Acked-by: Serge Hallyn 
---
Changelog:

v0:
- This patch replaces the loading of certificates onto the secondary
  keyring with platform keyring
- removed the CONFIG LOAD_UEFI_KEYS
- moved the file load_uefi.o from certs to security/integrity/platform_certs

v2:
- Fixed the checkpatch.pl warnings

 security/integrity/Makefile   |   5 +-
 security/integrity/platform_certs/load_uefi.c | 171 ++
 2 files changed, 175 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/platform_certs/load_uefi.c

diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 6ee9058866cd..86df9aba8c0f 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -10,7 +10,10 @@ integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
 integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o \
- platform_certs/efi_parser.o
+ platform_certs/efi_parser.o \
+ platform_certs/load_uefi.o
+obj-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/load_uefi.o
+$(obj)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/platform_certs/load_uefi.c 
b/security/integrity/platform_certs/load_uefi.c
new file mode 100644
index ..acd9db90dde7
--- /dev/null
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -0,0 +1,171 @@
+// 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;
+
+/*
+ * Get a certificate list blob from the named EFI variable.
+ */
+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
+ unsigned long *size)
+{
+   efi_status_t status;
+   unsigned long lsize = 4;
+   unsigned long tmpdb[4];
+   void *db;
+
+   status = efi.get_variable(name, guid, NULL, , );
+   if (status != EFI_BUFFER_TOO_SMALL) {
+   pr_err("Couldn't get size: 0x%lx\n", status);
+   return NULL;
+   }
+
+   db = kmalloc(lsize, GFP_KERNEL);
+   if (!db)
+   return NULL;
+
+   status = efi.get_variable(name, guid, NULL, , db);
+   if (status != EFI_SUCCESS) {
+   kfree(db);
+   pr_err("Error reading db var: 0x%lx\n", status);
+   return NULL;
+   }
+
+   *size = lsize;
+   return db;
+}
+
+/*
+ * Blacklist an X509 TBS hash.
+ */
+static __init void uefi_blacklist_x509_tbs(const char *source,
+  const void *data, size_t len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(4 + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, "tbs:", 4);
+   p += 4;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfre

[PATCH v2 3/7] efi: Add EFI signature data types

2018-12-08 Thread Nayna Jain
From: Dave Howells 

Add the data types that are used for containing hashes, keys and
certificates for cryptographic verification along with their corresponding
type GUIDs.

Signed-off-by: David Howells 
Acked-by: Nayna Jain 
Acked-by: Serge Hallyn 
---
Changelog:

v0:
- No changes

 include/linux/efi.h | 25 +
 1 file changed, 25 insertions(+)

diff --git a/include/linux/efi.h b/include/linux/efi.h
index 845174e113ce..214516b29b36 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -663,6 +663,10 @@ void efi_native_runtime_setup(void);
 #define EFI_IMAGE_SECURITY_DATABASE_GUID   EFI_GUID(0xd719b2cb, 0x3d3a, 
0x4596,  0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f)
 #define EFI_SHIM_LOCK_GUID EFI_GUID(0x605dab50, 0xe046, 
0x4300,  0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23)
 
+#define EFI_CERT_SHA256_GUID   EFI_GUID(0xc1c41626, 0x504c, 
0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28)
+#define EFI_CERT_X509_GUID EFI_GUID(0xa5c059a1, 0x94e4, 
0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72)
+#define EFI_CERT_X509_SHA256_GUID  EFI_GUID(0x3bd2a492, 0x96c0, 
0x4079, 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed)
+
 /*
  * This GUID is used to pass to the kernel proper the struct screen_info
  * structure that was populated by the stub based on the GOP protocol instance
@@ -934,6 +938,27 @@ typedef struct {
efi_memory_desc_t entry[0];
 } efi_memory_attributes_table_t;
 
+typedef struct  {
+   efi_guid_t signature_owner;
+   u8 signature_data[];
+} efi_signature_data_t;
+
+typedef struct {
+   efi_guid_t signature_type;
+   u32 signature_list_size;
+   u32 signature_header_size;
+   u32 signature_size;
+   u8 signature_header[];
+   /* efi_signature_data_t signatures[][] */
+} efi_signature_list_t;
+
+typedef u8 efi_sha256_hash_t[32];
+
+typedef struct {
+   efi_sha256_hash_t to_be_signed_hash;
+   efi_time_t time_of_revocation;
+} efi_cert_x509_sha256_t;
+
 /*
  * All runtime access to EFI goes through this structure:
  */
-- 
2.13.6



[PATCH v2 0/7] add platform/firmware keys support for kernel verification by IMA

2018-12-08 Thread Nayna Jain
On secure boot enabled systems, a verified kernel may need to kexec
additional kernels. For example, it may be used as a bootloader needing
to kexec a target kernel or it may need to kexec a crashdump kernel.
In such cases, it may want to verify the signature of the next kernel
image.

It is possible that the new kernel image is signed with third party keys
which are stored as platform or firmware keys in the 'db' variable. The
kernel, however, can not directly verify these platform keys, and an
administrator may therefore not want to trust them for arbitrary usage.
In order to differentiate platform keys from other keys and provide the
necessary separation of trust the kernel needs an additional keyring to
store platform/firmware keys.

The secure boot key database is expected to store the keys as EFI
Signature List(ESL). The patch set uses David Howells and Josh Boyer's
patch to access and parse the ESL to extract the certificates and load
them onto the platform keyring.

The last patch in this patch set adds support for IMA-appraisal to
verify the kexec'ed kernel image based on keys stored in the platform
keyring.

Changelog:

v0:
- The original patches loaded the certificates onto the secondary
  trusted keyring. This patch set defines a new keyring named
  ".platform" and adds the certificates to this new keyring  
- removed CONFIG EFI_SIGNATURE_LIST_PARSER and LOAD_UEFI_KEYS
- moved files from certs/ to security/integrity/platform_certs/

v2:
- fixed the checkpatch warnings and other formatting as suggested by
  Mimi Zohar 
- fixed coding style as suggested by Serge Hallyn in Patch "ima: Support
  platform keyring for kernel appraisal"

Dave Howells (2):
  efi: Add EFI signature data types
  efi: Add an EFI signature blob parser

Josh Boyer (2):
  efi: Import certificates from UEFI Secure Boot
  efi: Allow the "db" UEFI variable to be suppressed

Nayna Jain (3):
  integrity: Define a trusted platform keyring
  integrity: Load certs to the platform keyring
  ima: Support platform keyring for kernel appraisal

 include/linux/efi.h|  34 
 security/integrity/Kconfig |  11 ++
 security/integrity/Makefile|   5 +
 security/integrity/digsig.c| 115 
 security/integrity/ima/ima_appraise.c  |  13 +-
 security/integrity/integrity.h |  23 ++-
 security/integrity/platform_certs/efi_parser.c | 108 
 security/integrity/platform_certs/load_uefi.c  | 196 +
 .../integrity/platform_certs/platform_keyring.c|  62 +++
 9 files changed, 528 insertions(+), 39 deletions(-)
 create mode 100644 security/integrity/platform_certs/efi_parser.c
 create mode 100644 security/integrity/platform_certs/load_uefi.c
 create mode 100644 security/integrity/platform_certs/platform_keyring.c

-- 
2.13.6



[PATCH v2 1/7] integrity: Define a trusted platform keyring

2018-12-08 Thread Nayna Jain
On secure boot enabled systems, a verified kernel may need to kexec
additional kernels. For example, it may be used as a bootloader needing
to kexec a target kernel or it may need to kexec a crashdump kernel. In
such cases, it may want to verify the signature of the next kernel
image.

It is further possible that the kernel image is signed with third party
keys which are stored as platform or firmware keys in the 'db' variable.
The kernel, however, can not directly verify these platform keys, and an
administrator may therefore not want to trust them for arbitrary usage.
In order to differentiate platform keys from other keys and provide the
necessary separation of trust, the kernel needs an additional keyring to
store platform keys.

This patch creates the new keyring called ".platform" to isolate keys
provided by platform from keys by kernel. These keys are used to
facilitate signature verification during kexec. Since the scope of this
keyring is only the platform/firmware keys, it cannot be updated from
userspace.

This keyring can be enabled by setting CONFIG_INTEGRITY_PLATFORM_KEYRING.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Acked-by: Serge Hallyn 
---
 security/integrity/Kconfig | 11 +
 security/integrity/Makefile|  1 +
 security/integrity/digsig.c| 48 +++---
 security/integrity/integrity.h |  3 +-
 .../integrity/platform_certs/platform_keyring.c| 39 ++
 5 files changed, 87 insertions(+), 15 deletions(-)
 create mode 100644 security/integrity/platform_certs/platform_keyring.c

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index da9565891738..4b4d2aeef539 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -51,6 +51,17 @@ config INTEGRITY_TRUSTED_KEYRING
   .evm keyrings be signed by a key on the system trusted
   keyring.
 
+config INTEGRITY_PLATFORM_KEYRING
+bool "Provide keyring for platform/firmware trusted keys"
+depends on INTEGRITY_ASYMMETRIC_KEYS
+depends on SYSTEM_BLACKLIST_KEYRING
+depends on EFI
+help
+ Provide a separate, distinct keyring for platform trusted keys, which
+ the kernel automatically populates during initialization from values
+ provided by the platform for verifying the kexec'ed kerned image
+ and, possibly, the initramfs signature.
+
 config INTEGRITY_AUDIT
bool "Enables integrity auditing support "
depends on AUDIT
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 04d6e462b079..046ffc1bb42d 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -9,6 +9,7 @@ integrity-y := iint.o
 integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
+integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 5eacba858e4b..b5b180ff1434 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -35,6 +35,7 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] 
= {
".ima",
 #endif
"_module",
+   ".platform",
 };
 
 #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
@@ -73,12 +74,40 @@ int integrity_digsig_verify(const unsigned int id, const 
char *sig, int siglen,
return -EOPNOTSUPP;
 }
 
-int __init integrity_init_keyring(const unsigned int id)
+static int __integrity_init_keyring(const unsigned int id, key_perm_t perm,
+   struct key_restriction *restriction)
 {
const struct cred *cred = current_cred();
+   int err = 0;
+
+   keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
+   KGIDT_INIT(0), cred, perm,
+   KEY_ALLOC_NOT_IN_QUOTA,
+   restriction, NULL);
+   if (IS_ERR(keyring[id])) {
+   err = PTR_ERR(keyring[id]);
+   pr_info("Can't allocate %s keyring (%d)\n",
+   keyring_name[id], err);
+   keyring[id] = NULL;
+   }
+
+   return err;
+}
+
+int __init integrity_init_keyring(const unsigned int id)
+{
struct key_restriction *restriction;
+   key_perm_t perm;
int err = 0;
 
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
+   | KEY_USR_READ | KEY_USR_SEARCH;
+
+   if (id == INTEGRITY_KEYRING_PLATFORM) {
+   restriction = NULL;
+   goto out;
+   }
+
if (!IS_ENABLED(CONFIG_INTEGR

[PATCH v2 2/7] integrity: Load certs to the platform keyring

2018-12-08 Thread Nayna Jain
The patch refactors integrity_load_x509(), making it a wrapper for a new
function named integrity_add_key(). This patch also defines a new
function named integrity_load_cert() for loading the platform keys.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
Acked-by: Serge Hallyn 
---
 security/integrity/digsig.c| 71 ++
 security/integrity/integrity.h | 20 ++
 .../integrity/platform_certs/platform_keyring.c| 23 +++
 3 files changed, 90 insertions(+), 24 deletions(-)

diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index b5b180ff1434..4ba167255225 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -82,8 +82,7 @@ static int __integrity_init_keyring(const unsigned int id, 
key_perm_t perm,
 
keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
KGIDT_INIT(0), cred, perm,
-   KEY_ALLOC_NOT_IN_QUOTA,
-   restriction, NULL);
+   KEY_ALLOC_NOT_IN_QUOTA, restriction, NULL);
if (IS_ERR(keyring[id])) {
err = PTR_ERR(keyring[id]);
pr_info("Can't allocate %s keyring (%d)\n",
@@ -124,16 +123,38 @@ int __init integrity_init_keyring(const unsigned int id)
return err;
 }
 
-int __init integrity_load_x509(const unsigned int id, const char *path)
+int __init integrity_add_key(const unsigned int id, const void *data,
+off_t size, key_perm_t perm)
 {
key_ref_t key;
-   void *data;
-   loff_t size;
-   int rc;
+   int rc = 0;
 
if (!keyring[id])
return -EINVAL;
 
+   key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric",
+  NULL, data, size, 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);
+   }
+
+   return rc;
+
+}
+
+int __init integrity_load_x509(const unsigned int id, const char *path)
+{
+   void *data;
+   loff_t size;
+   int rc;
+   key_perm_t perm;
+
rc = kernel_read_file_from_path(path, , , 0,
READING_X509_CERTIFICATE);
if (rc < 0) {
@@ -141,23 +162,25 @@ int __init integrity_load_x509(const unsigned int id, 
const char *path)
return rc;
}
 
-   key = key_create_or_update(make_key_ref(keyring[id], 1),
-  "asymmetric",
-  NULL,
-  data,
-  size,
-  ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-   KEY_USR_VIEW | KEY_USR_READ),
-  KEY_ALLOC_NOT_IN_QUOTA);
-   if (IS_ERR(key)) {
-   rc = PTR_ERR(key);
-   pr_err("Problem loading X.509 certificate (%d): %s\n",
-  rc, path);
-   } else {
-   pr_notice("Loaded X.509 cert '%s': %s\n",
- key_ref_to_ptr(key)->description, path);
-   key_ref_put(key);
-   }
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ;
+
+   pr_info("Loading X.509 certificate: %s\n", path);
+   rc = integrity_add_key(id, (const void *)data, size, perm);
+
vfree(data);
-   return 0;
+   return rc;
+}
+
+int __init integrity_load_cert(const unsigned int id, const char *source,
+  const void *data, size_t len, key_perm_t perm)
+{
+   int rc;
+
+   if (!data)
+   return -EINVAL;
+
+   pr_info("Loading X.509 certificate: %s\n", source);
+   rc = integrity_add_key(id, data, len, perm);
+
+   return rc;
 }
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index c2332a44799e..3517d2852a07 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -154,6 +154,8 @@ int integrity_digsig_verify(const unsigned int id, const 
char *sig, int siglen,
 
 int __init integrity_init_keyring(const unsigned int id);
 int __init integrity_load_x509(const unsigned int id, const char *path);
+int __init integrity_load_cert(const unsigned int id, const char *source,
+  const void *data, size_t len, key_perm_t perm);
 #else
 
 static inline int integrity_digsig_verify(const unsigned int id,
@@ -167,6 +169,14 @@ static inline int integrity_init_keyring(const unsi

[PATCH 7/7] ima: Support platform keyring for kernel appraisal

2018-11-25 Thread Nayna Jain
On secure boot enabled systems, the bootloader verifies the kernel
image and possibly the initramfs signatures based on a set of keys. A
soft reboot(kexec) of the system, with the same kernel image and
initramfs, requires access to the original keys to verify the
signatures.

This patch allows IMA-appraisal access to those original keys, now
loaded on the platform keyring, needed for verifying the kernel image
and initramfs signatures.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
---
 security/integrity/ima/ima_appraise.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index deec1804a00a..9c13585e7d3e 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -294,7 +294,16 @@ int ima_appraise_measurement(enum ima_hooks func,
 iint->ima_hash->length);
if (rc == -EOPNOTSUPP) {
status = INTEGRITY_UNKNOWN;
-   } else if (rc) {
+   break;
+   }
+   if (rc && func == KEXEC_KERNEL_CHECK)
+   rc = integrity_digsig_verify(
+   INTEGRITY_KEYRING_PLATFORM,
+   (const char *)xattr_value,
+   xattr_len,
+   iint->ima_hash->digest,
+   iint->ima_hash->length);
+   if (rc) {
cause = "invalid-signature";
status = INTEGRITY_FAIL;
} else {
-- 
2.13.6



[PATCH 5/7] efi: Import certificates from UEFI Secure Boot

2018-11-25 Thread Nayna Jain
From: Josh Boyer 

New Patch Description:
==

Secure Boot stores a list of allowed certificates in the 'db' variable.
This patch imports those certificates into the platform keyring. The shim
UEFI bootloader has a similar certificate list stored in the 'MokListRT'
variable. We import those as well.

Secure Boot also maintains a list of disallowed certificates in the 'dbx'
variable. We load those certificates into the system blacklist keyring
and forbid any kernel signed with those from loading.

Original Patch Description:


Secure Boot stores a list of allowed certificates in the 'db' variable.
This imports those certificates into the system trusted keyring.  This
allows for a third party signing certificate to be used in conjunction
with signed modules. By importing the public certificate into the 'db'
variable, a user can allow a module signed with that certificate to
load. The shim UEFI bootloader has a similar certificate list stored
in the 'MokListRT' variable. We import those as well.

Secure Boot also maintains a list of disallowed certificates in the 'dbx'
variable. We load those certificates into the newly introduced system
blacklist keyring and forbid any module signed with those from loading and
forbid the use within the kernel of any key with a matching hash.

This facility is enabled by setting CONFIG_LOAD_UEFI_KEYS.

Signed-off-by: Josh Boyer 
Signed-off-by: David Howells 
Signed-off-by: Nayna Jain 
---
Changelog:

v0:
- This patch replaces the loading of certificates onto the secondary
  keyring with platform keyring
- removed the CONFIG LOAD_UEFI_KEYS
- moved the file load_uefi.o from certs to
  security/integrity/platform_certs

 security/integrity/Makefile   |   5 +-
 security/integrity/platform_certs/load_uefi.c | 168 ++
 2 files changed, 172 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/platform_certs/load_uefi.c

diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 6ee9058866cd..86df9aba8c0f 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -10,7 +10,10 @@ integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
 integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o \
- platform_certs/efi_parser.o
+ platform_certs/efi_parser.o \
+ platform_certs/load_uefi.o
+obj-$(CONFIG_LOAD_UEFI_KEYS) += platform_certs/load_uefi.o
+$(obj)/load_uefi.o: KBUILD_CFLAGS += -fshort-wchar
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/platform_certs/load_uefi.c 
b/security/integrity/platform_certs/load_uefi.c
new file mode 100644
index ..dbccb45147ef
--- /dev/null
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -0,0 +1,168 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../integrity.h"
+
+static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID;
+static __initdata efi_guid_t efi_cert_x509_sha256_guid = 
EFI_CERT_X509_SHA256_GUID;
+static __initdata efi_guid_t efi_cert_sha256_guid = EFI_CERT_SHA256_GUID;
+
+/*
+ * Get a certificate list blob from the named EFI variable.
+ */
+static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
+ unsigned long *size)
+{
+   efi_status_t status;
+   unsigned long lsize = 4;
+   unsigned long tmpdb[4];
+   void *db;
+
+   status = efi.get_variable(name, guid, NULL, , );
+   if (status != EFI_BUFFER_TOO_SMALL) {
+   pr_err("Couldn't get size: 0x%lx\n", status);
+   return NULL;
+   }
+
+   db = kmalloc(lsize, GFP_KERNEL);
+   if (!db) {
+   pr_err("Couldn't allocate memory for uefi cert list\n");
+   return NULL;
+   }
+
+   status = efi.get_variable(name, guid, NULL, , db);
+   if (status != EFI_SUCCESS) {
+   kfree(db);
+   pr_err("Error reading db var: 0x%lx\n", status);
+   return NULL;
+   }
+
+   *size = lsize;
+   return db;
+}
+
+/*
+ * Blacklist an X509 TBS hash.
+ */
+static __init void uefi_blacklist_x509_tbs(const char *source,
+  const void *data, size_t len)
+{
+   char *hash, *p;
+
+   hash = kmalloc(4 + len * 2 + 1, GFP_KERNEL);
+   if (!hash)
+   return;
+   p = memcpy(hash, "tbs:", 4);
+   p += 4;
+   bin2hex(p, data, len);
+   p += len * 2;
+   *p = 0;
+
+   mark_hash_blacklisted(hash);
+   kfree(hash)

[PATCH 0/7] add platform/firmware keys support for kernel verification by IMA

2018-11-25 Thread Nayna Jain
On secure boot enabled systems, a verified kernel may need to kexec
additional kernels. For example, it may be used as a bootloader needing
to kexec a target kernel or it may need to kexec a crashdump kernel.
In such cases, it may want to verify the signature of the next kernel
image.

It is possible that the new kernel image is signed with third party keys
which are stored as platform or firmware keys in the 'db' variable. The
kernel, however, can not directly verify these platform keys, and an
administrator may therefore not want to trust them for arbitrary usage.
In order to differentiate platform keys from other keys and provide the
necessary separation of trust the kernel needs an additional keyring to
store platform/firmware keys.

The secure boot key database is expected to store the keys as EFI
Signature List(ESL). The patch set uses David Howells and Josh Boyer's
patch to access and parse the ESL to extract the certificates and load
them onto the platform keyring.

The last patch in this patch set adds support for IMA-appraisal to
verify the kexec'ed kernel image based on keys stored in the platform
keyring.

Changelog:

v0:
- The original patches loaded the certificates onto the secondary
  trusted keyring. This patch set defines a new keyring named
  ".platform" and adds the certificates to this new keyring  
- removed CONFIG EFI_SIGNATURE_LIST_PARSER and LOAD_UEFI_KEYS
- moved files from certs/ to security/integrity/platform_certs/

Dave Howells (2):
  efi: Add EFI signature data types
  efi: Add an EFI signature blob parser

Josh Boyer (2):
  efi: Import certificates from UEFI Secure Boot
  efi: Allow the "db" UEFI variable to be suppressed

Nayna Jain (3):
  integrity: define a trusted platform keyring
  integrity: load certs to the platform keyring
  ima: support platform keyring for kernel appraisal

 include/linux/efi.h|  34 
 security/integrity/Kconfig |  11 ++
 security/integrity/Makefile|   5 +
 security/integrity/digsig.c| 115 
 security/integrity/ima/ima_appraise.c  |  11 +-
 security/integrity/integrity.h |  23 ++-
 security/integrity/platform_certs/efi_parser.c | 112 
 security/integrity/platform_certs/load_uefi.c  | 192 +
 .../integrity/platform_certs/platform_keyring.c|  62 +++
 9 files changed, 527 insertions(+), 38 deletions(-)
 create mode 100644 security/integrity/platform_certs/efi_parser.c
 create mode 100644 security/integrity/platform_certs/load_uefi.c
 create mode 100644 security/integrity/platform_certs/platform_keyring.c

-- 
2.13.6



[PATCH 6/7] efi: Allow the "db" UEFI variable to be suppressed

2018-11-25 Thread Nayna Jain
From: Josh Boyer 

If a user tells shim to not use the certs/hashes in the UEFI db variable
for verification purposes, shim will set a UEFI variable called
MokIgnoreDB. Have the uefi import code look for this and ignore the db
variable if it is found.

Signed-off-by: Josh Boyer 
Signed-off-by: David Howells 
Acked-by: Nayna Jain 
---
Changelog:

v0:
- No changes

 security/integrity/platform_certs/load_uefi.c | 44 +--
 1 file changed, 34 insertions(+), 10 deletions(-)

diff --git a/security/integrity/platform_certs/load_uefi.c 
b/security/integrity/platform_certs/load_uefi.c
index dbccb45147ef..978c8d0dc151 100644
--- a/security/integrity/platform_certs/load_uefi.c
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -13,6 +13,26 @@ static __initdata efi_guid_t efi_cert_x509_sha256_guid = 
EFI_CERT_X509_SHA256_GU
 static __initdata efi_guid_t efi_cert_sha256_guid = EFI_CERT_SHA256_GUID;
 
 /*
+ * Look to see if a UEFI variable called MokIgnoreDB exists and return true if
+ * it does.
+ *
+ * This UEFI variable is set by the shim if a user tells the shim to not use
+ * the certs/hashes in the UEFI db variable for verification purposes.  If it
+ * is set, we should ignore the db variable also and the true return indicates
+ * this.
+ */
+static __init bool uefi_check_ignore_db(void)
+{
+   efi_status_t status;
+   unsigned int db = 0;
+   unsigned long size = sizeof(db);
+   efi_guid_t guid = EFI_SHIM_LOCK_GUID;
+
+   status = efi.get_variable(L"MokIgnoreDB", , NULL, , );
+   return status == EFI_SUCCESS;
+}
+
+/*
  * Get a certificate list blob from the named EFI variable.
  */
 static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
@@ -113,7 +133,9 @@ static __init efi_element_handler_t 
get_handler_for_dbx(const efi_guid_t *sig_ty
 }
 
 /*
- * Load the certs contained in the UEFI databases
+ * Load the certs contained in the UEFI databases into the secondary trusted
+ * keyring and the UEFI blacklisted X.509 cert SHA256 hashes into the blacklist
+ * keyring.
  */
 static int __init load_uefi_certs(void)
 {
@@ -129,15 +151,17 @@ static int __init load_uefi_certs(void)
/* Get db, MokListRT, and dbx.  They might not exist, so it isn't
 * an error if we can't get them.
 */
-   db = get_cert_list(L"db", _var, );
-   if (!db) {
-   pr_err("Couldn't get UEFI db list\n");
-   } else {
-   rc = parse_efi_signature_list("UEFI:db",
- db, dbsize, get_handler_for_db);
-   if (rc)
-   pr_err("Couldn't parse db signatures: %d\n", rc);
-   kfree(db);
+   if (!uefi_check_ignore_db()) {
+   db = get_cert_list(L"db", _var, );
+   if (!db) {
+   pr_err("MODSIGN: Couldn't get UEFI db list\n");
+   } else {
+   rc = parse_efi_signature_list("UEFI:db",
+   db, dbsize, get_handler_for_db);
+   if (rc)
+   pr_err("Couldn't parse db signatures: %d\n", 
rc);
+   kfree(db);
+   }
}
 
mok = get_cert_list(L"MokListRT", _var, );
-- 
2.13.6



[PATCH 4/7] efi: Add an EFI signature blob parser

2018-11-25 Thread Nayna Jain
From: Dave Howells 

Add a function to parse an EFI signature blob looking for elements of
interest. A list is made up of a series of sublists, where all the
elements in a sublist are of the same type, but sublists can be of
different types.

For each sublist encountered, the function pointed to by the
get_handler_for_guid argument is called with the type specifier GUID and
returns either a pointer to a function to handle elements of that type or
NULL if the type is not of interest.

If the sublist is of interest, each element is passed to the handler
function in turn.

Signed-off-by: David Howells 
Signed-off-by: Nayna Jain 
---
Changelog:

v0:
- removed the CONFIG EFI_SIGNATURE_LIST_PARSER
- moved efi_parser.c from certs to security/integrity/platform_certs
  directory

 include/linux/efi.h|   9 ++
 security/integrity/Makefile|   3 +-
 security/integrity/platform_certs/efi_parser.c | 112 +
 3 files changed, 123 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/platform_certs/efi_parser.c

diff --git a/include/linux/efi.h b/include/linux/efi.h
index 99cba6fe1234..2016145e2d6d 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1138,6 +1138,15 @@ extern int efi_memattr_apply_permissions(struct 
mm_struct *mm,
 char * __init efi_md_typeattr_format(char *buf, size_t size,
 const efi_memory_desc_t *md);
 
+
+typedef void (*efi_element_handler_t)(const char *source,
+ const void *element_data,
+ size_t element_size);
+extern int __init parse_efi_signature_list(
+   const char *source,
+   const void *data, size_t size,
+   efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *));
+
 /**
  * efi_range_is_wc - check the WC bit on an address range
  * @start: starting kvirt address
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 046ffc1bb42d..6ee9058866cd 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -9,7 +9,8 @@ integrity-y := iint.o
 integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 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_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o \
+ platform_certs/efi_parser.o
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/platform_certs/efi_parser.c 
b/security/integrity/platform_certs/efi_parser.c
new file mode 100644
index ..4e396f98f5c7
--- /dev/null
+++ b/security/integrity/platform_certs/efi_parser.c
@@ -0,0 +1,112 @@
+/* EFI signature/key/certificate list parser
+ *
+ * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowe...@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "EFI: "fmt
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * parse_efi_signature_list - Parse an EFI signature list for certificates
+ * @source: The source of the key
+ * @data: The data blob to parse
+ * @size: The size of the data blob
+ * @get_handler_for_guid: Get the handler func for the sig type (or NULL)
+ *
+ * Parse an EFI signature list looking for elements of interest.  A list is
+ * made up of a series of sublists, where all the elements in a sublist are of
+ * the same type, but sublists can be of different types.
+ *
+ * For each sublist encountered, the @get_handler_for_guid function is called
+ * with the type specifier GUID and returns either a pointer to a function to
+ * handle elements of that type or NULL if the type is not of interest.
+ *
+ * If the sublist is of interest, each element is passed to the handler
+ * function in turn.
+ *
+ * Error EBADMSG is returned if the list doesn't parse correctly and 0 is
+ * returned if the list was parsed correctly.  No error can be returned from
+ * the @get_handler_for_guid function or the element handler function it
+ * returns.
+ */
+int __init parse_efi_signature_list(
+   const char *source,
+   const void *data, size_t size,
+   efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *))
+{
+   efi_element_handler_t handler;
+   unsigned offs = 0;
+
+   pr_devel("-->%s(,%zu)\n", __func__, size);
+
+   while (size > 0) {
+   const efi_signature_data_t *elem;
+   efi_signature_list_t list;
+   size_t l

[PATCH 2/7] integrity: Load certs to the platform keyring

2018-11-25 Thread Nayna Jain
The patch refactors integrity_load_x509(), making it a wrapper for a new
function named integrity_add_key(). This patch also defines a new
function named integrity_load_cert() for loading the platform keys.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
---
 security/integrity/digsig.c| 71 ++
 security/integrity/integrity.h | 20 ++
 .../integrity/platform_certs/platform_keyring.c| 23 +++
 3 files changed, 90 insertions(+), 24 deletions(-)

diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index fef2a858300c..ab30c451a19b 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -82,8 +82,7 @@ static int __integrity_init_keyring(const unsigned int id, 
key_perm_t perm,
 
keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
KGIDT_INIT(0), cred, perm,
-   KEY_ALLOC_NOT_IN_QUOTA,
-   restriction, NULL);
+   KEY_ALLOC_NOT_IN_QUOTA, restriction, NULL);
if (IS_ERR(keyring[id])) {
err = PTR_ERR(keyring[id]);
pr_info("Can't allocate %s keyring (%d)\n",
@@ -124,16 +123,38 @@ int __init integrity_init_keyring(const unsigned int id)
return err;
 }
 
-int __init integrity_load_x509(const unsigned int id, const char *path)
+int __init integrity_add_key(const unsigned int id, const void *data,
+off_t size, key_perm_t perm)
 {
key_ref_t key;
-   void *data;
-   loff_t size;
-   int rc;
+   int rc = 0;
 
if (!keyring[id])
return -EINVAL;
 
+   key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric",
+  NULL, data, size, 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);
+   }
+
+   return rc;
+
+}
+
+int __init integrity_load_x509(const unsigned int id, const char *path)
+{
+   void *data;
+   loff_t size;
+   int rc;
+   key_perm_t perm;
+
rc = kernel_read_file_from_path(path, , , 0,
READING_X509_CERTIFICATE);
if (rc < 0) {
@@ -141,23 +162,25 @@ int __init integrity_load_x509(const unsigned int id, 
const char *path)
return rc;
}
 
-   key = key_create_or_update(make_key_ref(keyring[id], 1),
-  "asymmetric",
-  NULL,
-  data,
-  size,
-  ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-   KEY_USR_VIEW | KEY_USR_READ),
-  KEY_ALLOC_NOT_IN_QUOTA);
-   if (IS_ERR(key)) {
-   rc = PTR_ERR(key);
-   pr_err("Problem loading X.509 certificate (%d): %s\n",
-  rc, path);
-   } else {
-   pr_notice("Loaded X.509 cert '%s': %s\n",
- key_ref_to_ptr(key)->description, path);
-   key_ref_put(key);
-   }
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ;
+
+   pr_info("Loading X.509 certificate: %s\n", path);
+   rc = integrity_add_key(id, (const void *)data, size, perm);
+
vfree(data);
-   return 0;
+   return rc;
+}
+
+int __init integrity_load_cert(const unsigned int id, const char *source,
+  const void *data, size_t len, key_perm_t perm)
+{
+   int rc;
+
+   if (!data)
+   return -EINVAL;
+
+   pr_info("Loading X.509 certificate: %s\n", source);
+   rc = integrity_add_key(id, data, len, perm);
+
+   return rc;
 }
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index c2332a44799e..3517d2852a07 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -154,6 +154,8 @@ int integrity_digsig_verify(const unsigned int id, const 
char *sig, int siglen,
 
 int __init integrity_init_keyring(const unsigned int id);
 int __init integrity_load_x509(const unsigned int id, const char *path);
+int __init integrity_load_cert(const unsigned int id, const char *source,
+  const void *data, size_t len, key_perm_t perm);
 #else
 
 static inline int integrity_digsig_verify(const unsigned int id,
@@ -167,6 +169,14 @@ static inline int integrity_init_keyring(const unsi

[PATCH 3/7] efi: Add EFI signature data types

2018-11-25 Thread Nayna Jain
From: Dave Howells 

Add the data types that are used for containing hashes, keys and
certificates for cryptographic verification along with their corresponding
type GUIDs.

Signed-off-by: David Howells 
Acked-by: Nayna Jain 
---
Changelog:

v0: 
- No changes

 include/linux/efi.h | 25 +
 1 file changed, 25 insertions(+)

diff --git a/include/linux/efi.h b/include/linux/efi.h
index 401e4b254e30..99cba6fe1234 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -663,6 +663,10 @@ void efi_native_runtime_setup(void);
 #define EFI_IMAGE_SECURITY_DATABASE_GUID   EFI_GUID(0xd719b2cb, 0x3d3a, 
0x4596,  0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f)
 #define EFI_SHIM_LOCK_GUID EFI_GUID(0x605dab50, 0xe046, 
0x4300,  0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23)
 
+#define EFI_CERT_SHA256_GUID   EFI_GUID(0xc1c41626, 0x504c, 
0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28)
+#define EFI_CERT_X509_GUID EFI_GUID(0xa5c059a1, 0x94e4, 
0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72)
+#define EFI_CERT_X509_SHA256_GUID  EFI_GUID(0x3bd2a492, 0x96c0, 
0x4079, 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed)
+
 /*
  * This GUID is used to pass to the kernel proper the struct screen_info
  * structure that was populated by the stub based on the GOP protocol instance
@@ -933,6 +937,27 @@ typedef struct {
efi_memory_desc_t entry[0];
 } efi_memory_attributes_table_t;
 
+typedef struct  {
+   efi_guid_t signature_owner;
+   u8 signature_data[];
+} efi_signature_data_t;
+
+typedef struct {
+   efi_guid_t signature_type;
+   u32 signature_list_size;
+   u32 signature_header_size;
+   u32 signature_size;
+   u8 signature_header[];
+   /* efi_signature_data_t signatures[][] */
+} efi_signature_list_t;
+
+typedef u8 efi_sha256_hash_t[32];
+
+typedef struct {
+   efi_sha256_hash_t to_be_signed_hash;
+   efi_time_t time_of_revocation;
+} efi_cert_x509_sha256_t;
+
 /*
  * All runtime access to EFI goes through this structure:
  */
-- 
2.13.6



[PATCH 1/7] integrity: Define a trusted platform keyring

2018-11-25 Thread Nayna Jain
On secure boot enabled systems, a verified kernel may need to kexec
additional kernels. For example, it may be used as a bootloader needing 
to kexec a target kernel or it may need to kexec a crashdump kernel. In
such cases, it may want to verify the signature of the next kernel
image.

It is further possible that the kernel image is signed with third party
keys which are stored as platform or firmware keys in the 'db' variable.
The kernel, however, can not directly verify these platform keys, and an
administrator may therefore not want to trust them for arbitrary usage.
In order to differentiate platform keys from other keys and provide the
necessary separation of trust, the kernel needs an additional keyring to
store platform keys.

This patch creates the new keyring called ".platform" to isolate keys
provided by platform from keys by kernel. These keys are used to
facilitate signature verification during kexec. Since the scope of this
keyring is only the platform/firmware keys, it cannot be updated from
userspace.

This keyring can be enabled by setting CONFIG_INTEGRITY_PLATFORM_KEYRING.

Signed-off-by: Nayna Jain 
Reviewed-by: Mimi Zohar 
---
 security/integrity/Kconfig | 11 +
 security/integrity/Makefile|  1 +
 security/integrity/digsig.c| 48 +++---
 security/integrity/integrity.h |  3 +-
 .../integrity/platform_certs/platform_keyring.c| 39 ++
 5 files changed, 87 insertions(+), 15 deletions(-)
 create mode 100644 security/integrity/platform_certs/platform_keyring.c

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index da9565891738..4b4d2aeef539 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -51,6 +51,17 @@ config INTEGRITY_TRUSTED_KEYRING
   .evm keyrings be signed by a key on the system trusted
   keyring.
 
+config INTEGRITY_PLATFORM_KEYRING
+bool "Provide keyring for platform/firmware trusted keys"
+depends on INTEGRITY_ASYMMETRIC_KEYS
+depends on SYSTEM_BLACKLIST_KEYRING
+depends on EFI
+help
+ Provide a separate, distinct keyring for platform trusted keys, which
+ the kernel automatically populates during initialization from values
+ provided by the platform for verifying the kexec'ed kerned image
+ and, possibly, the initramfs signature.
+
 config INTEGRITY_AUDIT
bool "Enables integrity auditing support "
depends on AUDIT
diff --git a/security/integrity/Makefile b/security/integrity/Makefile
index 04d6e462b079..046ffc1bb42d 100644
--- a/security/integrity/Makefile
+++ b/security/integrity/Makefile
@@ -9,6 +9,7 @@ integrity-y := iint.o
 integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o
 integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
 integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
+integrity-$(CONFIG_INTEGRITY_PLATFORM_KEYRING) += 
platform_certs/platform_keyring.o
 
 subdir-$(CONFIG_IMA)   += ima
 obj-$(CONFIG_IMA)  += ima/
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 5eacba858e4b..fef2a858300c 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -35,6 +35,7 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] 
= {
".ima",
 #endif
"_module",
+   ".platform",
 };
 
 #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
@@ -73,12 +74,39 @@ int integrity_digsig_verify(const unsigned int id, const 
char *sig, int siglen,
return -EOPNOTSUPP;
 }
 
-int __init integrity_init_keyring(const unsigned int id)
+static int __integrity_init_keyring(const unsigned int id, key_perm_t perm,
+   struct key_restriction *restriction)
 {
const struct cred *cred = current_cred();
+   int err = 0;
+
+   keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
+   KGIDT_INIT(0), cred, perm,
+   KEY_ALLOC_NOT_IN_QUOTA,
+   restriction, NULL);
+   if (IS_ERR(keyring[id])) {
+   err = PTR_ERR(keyring[id]);
+   pr_info("Can't allocate %s keyring (%d)\n",
+   keyring_name[id], err);
+   keyring[id] = NULL;
+   }
+
+   return err;
+}
+
+int __init integrity_init_keyring(const unsigned int id)
+{
struct key_restriction *restriction;
+   key_perm_t perm;
int err = 0;
 
+   if (id == INTEGRITY_KEYRING_PLATFORM) {
+   restriction = NULL;
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
+   | KEY_USR_READ | KEY_USR_SEARCH;
+   goto out;
+   }
+
if (!IS_ENABLED(CONFIG_INTEGRITY_TRU

[PATCH v6 3/5] ima: refactor ima_init_policy()

2018-10-09 Thread Nayna Jain
From: Nayna Jain 

This patch removes the code duplication in ima_init_policy() by defining
a new function named add_rules(). The new function adds the rules to the
initial IMA policy, the custom policy or both based on the policy mask
(IMA_DEFAULT_POLICY, IMA_CUSTOM_POLICY).

Signed-off-by: Nayna Jain 
---
 security/integrity/ima/ima_policy.c | 97 +
 1 file changed, 56 insertions(+), 41 deletions(-)

diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 8c9499867c91..1e30d09a56db 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -58,6 +58,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, 
LSM_OBJ_TYPE,
 
 enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
 
+enum policy_rule_list { IMA_DEFAULT_POLICY = 1, IMA_CUSTOM_POLICY };
+
 struct ima_rule_entry {
struct list_head list;
int action;
@@ -473,6 +475,32 @@ static int ima_appraise_flag(enum ima_hooks func)
return 0;
 }
 
+static void add_rules(struct ima_rule_entry *entries, int count,
+ enum policy_rule_list policy_rule)
+{
+   int i = 0;
+
+   for (i = 0; i < count; i++) {
+   struct ima_rule_entry *entry;
+
+   if (policy_rule & IMA_DEFAULT_POLICY)
+   list_add_tail([i].list, _default_rules);
+
+   if (policy_rule & IMA_CUSTOM_POLICY) {
+   entry = kmemdup([i], sizeof(*entry),
+   GFP_KERNEL);
+   if (!entry)
+   continue;
+
+   list_add_tail(>list, _policy_rules);
+   }
+   if (entries[i].action == APPRAISE)
+   temp_ima_appraise |= ima_appraise_flag(entries[i].func);
+   if (entries[i].func == POLICY_CHECK)
+   temp_ima_appraise |= IMA_APPRAISE_POLICY;
+   }
+}
+
 /**
  * ima_init_policy - initialize the default measure rules.
  *
@@ -481,28 +509,23 @@ static int ima_appraise_flag(enum ima_hooks func)
  */
 void __init ima_init_policy(void)
 {
-   int i, measure_entries, appraise_entries, secure_boot_entries;
-
-   /* if !ima_policy set entries = 0 so we load NO default rules */
-   measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
-   appraise_entries = ima_use_appraise_tcb ?
-ARRAY_SIZE(default_appraise_rules) : 0;
-   secure_boot_entries = ima_use_secure_boot ?
-   ARRAY_SIZE(secure_boot_rules) : 0;
+   int build_appraise_entries;
 
-   for (i = 0; i < measure_entries; i++)
-   list_add_tail(_measure_rules[i].list, _default_rules);
+   /* if !ima_policy, we load NO default rules */
+   if (ima_policy)
+   add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules),
+ IMA_DEFAULT_POLICY);
 
switch (ima_policy) {
case ORIGINAL_TCB:
-   for (i = 0; i < ARRAY_SIZE(original_measurement_rules); i++)
-   list_add_tail(_measurement_rules[i].list,
- _default_rules);
+   add_rules(original_measurement_rules,
+ ARRAY_SIZE(original_measurement_rules),
+ IMA_DEFAULT_POLICY);
break;
case DEFAULT_TCB:
-   for (i = 0; i < ARRAY_SIZE(default_measurement_rules); i++)
-   list_add_tail(_measurement_rules[i].list,
- _default_rules);
+   add_rules(default_measurement_rules,
+ ARRAY_SIZE(default_measurement_rules),
+ IMA_DEFAULT_POLICY);
default:
break;
}
@@ -511,38 +534,30 @@ void __init ima_init_policy(void)
 * Insert the builtin "secure_boot" policy rules requiring file
 * signatures, prior to any other appraise rules.
 */
-   for (i = 0; i < secure_boot_entries; i++) {
-   list_add_tail(_boot_rules[i].list, _default_rules);
-   temp_ima_appraise |=
-   ima_appraise_flag(secure_boot_rules[i].func);
-   }
+   if (ima_use_secure_boot)
+   add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules),
+ IMA_DEFAULT_POLICY);
 
/*
 * Insert the build time appraise rules requiring file signatures
 * for both the initial and custom policies, prior to other appraise
-* rules.
+* rules. As the secure boot rules includes all of the build time
+* rules, include either one or the other set of rules, but not both.
 */
-   for (i = 0; i < ARRAY_SIZE(build_appraise_rules); i++) {
-   struct ima_rule_entry *entry;
-
-   if (!secure_boot_entries

[PATCH v6 4/5] ima: add support for arch specific policies

2018-10-09 Thread Nayna Jain
From: Nayna Jain 

Builtin IMA policies can be enabled on the boot command line, and replaced
with a custom policy, normally during early boot in the initramfs. Build
time IMA policy rules were recently added. These rules are automatically
enabled on boot and persist after loading a custom policy.

There is a need for yet another type of policy, an architecture specific
policy, which is derived at runtime during kernel boot, based on the
runtime secure boot flags.  Like the build time policy rules, these rules
persist after loading a custom policy.

This patch adds support for loading an architecture specific IMA policy.

Signed-off-by: Nayna Jain 
- Defined function to convert the arch policy strings to an array of
ima_entry_rules.  The memory can then be freed after loading a custom
policy.
- Rename ima_get_arch_policy to arch_get_ima_policy.
Signed-off-by: Mimi Zohar 
- Modified ima_init_arch_policy() and ima_init_policy() to use add_rules()
from previous patch.
Signed-off-by: Nayna Jain 
---
 include/linux/ima.h |  5 +++
 security/integrity/ima/ima_policy.c | 72 +++--
 2 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 4852255aa4f4..350fa957f8a6 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -39,6 +39,11 @@ static inline bool arch_ima_get_secureboot(void)
 }
 #endif
 
+static inline const char * const *arch_get_ima_policy(void)
+{
+   return NULL;
+}
+
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
 {
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 1e30d09a56db..b20770704b6c 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ima.h"
 
@@ -195,6 +196,9 @@ static struct ima_rule_entry secure_boot_rules[] 
__ro_after_init = {
 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
 };
 
+/* An array of architecture specific rules */
+struct ima_rule_entry *arch_policy_entry __ro_after_init;
+
 static LIST_HEAD(ima_default_rules);
 static LIST_HEAD(ima_policy_rules);
 static LIST_HEAD(ima_temp_rules);
@@ -501,6 +505,49 @@ static void add_rules(struct ima_rule_entry *entries, int 
count,
}
 }
 
+static int ima_parse_rule(char *rule, struct ima_rule_entry *entry);
+
+static int __init ima_init_arch_policy(void)
+{
+   const char * const *arch_rules;
+   const char * const *rules;
+   int arch_entries = 0;
+   int i = 0;
+
+   arch_rules = arch_get_ima_policy();
+   if (!arch_rules)
+   return arch_entries;
+
+   /* Get number of rules */
+   for (rules = arch_rules; *rules != NULL; rules++)
+   arch_entries++;
+
+   arch_policy_entry = kcalloc(arch_entries + 1,
+   sizeof(*arch_policy_entry), GFP_KERNEL);
+   if (!arch_policy_entry)
+   return 0;
+
+   /* Convert each policy string rules to struct ima_rule_entry format */
+   for (rules = arch_rules, i = 0; *rules != NULL; rules++) {
+   char rule[255];
+   int result;
+
+   result = strlcpy(rule, *rules, sizeof(rule));
+
+   INIT_LIST_HEAD(_policy_entry[i].list);
+   result = ima_parse_rule(rule, _policy_entry[i]);
+   if (result) {
+   pr_warn("Skipping unknown architecture policy rule: 
%s\n",
+   rule);
+   memset(_policy_entry[i], 0,
+  sizeof(*arch_policy_entry));
+   continue;
+   }
+   i++;
+   }
+   return i;
+}
+
 /**
  * ima_init_policy - initialize the default measure rules.
  *
@@ -509,7 +556,7 @@ static void add_rules(struct ima_rule_entry *entries, int 
count,
  */
 void __init ima_init_policy(void)
 {
-   int build_appraise_entries;
+   int build_appraise_entries, arch_entries;
 
/* if !ima_policy, we load NO default rules */
if (ima_policy)
@@ -531,8 +578,21 @@ void __init ima_init_policy(void)
}
 
/*
+* Based on runtime secure boot flags, insert arch specific measurement
+* and appraise rules requiring file signatures for both the initial
+* and custom policies, prior to other appraise rules.
+* (Highest priority)
+*/
+   arch_entries = ima_init_arch_policy();
+   if (!arch_entries)
+   pr_info("No architecture policies found\n");
+   else
+   add_rules(arch_policy_entry, arch_entries,
+ IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
+
+   /*
 * Insert the builtin "secure_boot" policy rules requiring file
-* signatures, prior to any other appraise rules.
+* signatures, prior to other appraise rules.
   

[PATCH v6 5/5] x86/ima: define arch_get_ima_policy() for x86

2018-10-09 Thread Nayna Jain
From: Eric Richter 

On x86, there are two methods of verifying a kexec'ed kernel image
signature being loaded via the kexec_file_load syscall - an architecture
specific implementaton or a IMA KEXEC_KERNEL_CHECK appraisal rule. Neither
of these methods verify the kexec'ed kernel image signature being loaded
via the kexec_load syscall.

Secure boot enabled systems require kexec images to be signed. Therefore,
this patch loads an IMA KEXEC_KERNEL_CHECK policy rule on secure boot
enabled systems not configured with CONFIG_KEXEC_VERIFY_SIG enabled.

When IMA_APPRAISE_BOOTPARAM is configured, different IMA appraise modes
(eg. fix, log) can be specified on the boot command line, allowing unsigned
or invalidly signed kernel images to be kexec'ed. This patch permits
enabling IMA_APPRAISE_BOOTPARAM or IMA_ARCH_POLICY, but not both.

Signed-off-by: Eric Richter 
- Removed the policy KEXEC_ORIG_KERNEL_CHECK which was defined to
  disable the kexec_load syscall.
- arch_get_ima_policy() uses arch_ima_get_secureboot() to get secureboot
  state
Signed-off-by: Nayna Jain 
Cc: David Howells 
Cc: Eric Biederman 
Cc: Peter Jones 
Cc: Vivek Goyal 
Cc: Dave Young 
---
 arch/x86/kernel/ima_arch.c | 16 
 include/linux/ima.h|  3 ++-
 security/integrity/ima/Kconfig | 10 +-
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/ima_arch.c b/arch/x86/kernel/ima_arch.c
index bb5a88d2b271..6c248616ee57 100644
--- a/arch/x86/kernel/ima_arch.c
+++ b/arch/x86/kernel/ima_arch.c
@@ -15,3 +15,19 @@ bool arch_ima_get_secureboot(void)
else
return false;
 }
+
+/* secureboot arch rules */
+static const char * const sb_arch_rules[] = {
+#if !IS_ENABLED(CONFIG_KEXEC_VERIFY_SIG)
+   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig",
+#endif /* CONFIG_KEXEC_VERIFY_SIG */
+   "measure func=KEXEC_KERNEL_CHECK",
+   NULL
+};
+
+const char * const *arch_get_ima_policy(void)
+{
+   if (IS_ENABLED(CONFIG_IMA_ARCH_POLICY) && arch_ima_get_secureboot())
+   return sb_arch_rules;
+   return NULL;
+}
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 350fa957f8a6..dca3a96db4cd 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -32,17 +32,18 @@ extern void ima_add_kexec_buffer(struct kimage *image);
 
 #ifdef CONFIG_X86
 extern bool arch_ima_get_secureboot(void);
+extern const char * const *arch_get_ima_policy(void);
 #else
 static inline bool arch_ima_get_secureboot(void)
 {
return false;
 }
-#endif
 
 static inline const char * const *arch_get_ima_policy(void)
 {
return NULL;
 }
+#endif
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 13b446328dda..a18f8c6d13b5 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -157,6 +157,14 @@ config IMA_APPRAISE
  <http://linux-ima.sourceforge.net>
  If unsure, say N.
 
+config IMA_ARCH_POLICY
+bool "Enable loading an IMA architecture specific policy"
+depends on KEXEC_VERIFY_SIG || IMA_APPRAISE && 
INTEGRITY_ASYMMETRIC_KEYS
+default n
+help
+  This option enables loading an IMA architecture specific policy
+  based on run time secure boot flags.
+
 config IMA_APPRAISE_BUILD_POLICY
bool "IMA build time configured policy rules"
depends on IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS
@@ -217,7 +225,7 @@ config IMA_APPRAISE_REQUIRE_POLICY_SIGS
 
 config IMA_APPRAISE_BOOTPARAM
bool "ima_appraise boot parameter"
-   depends on IMA_APPRAISE
+   depends on IMA_APPRAISE && !IMA_ARCH_POLICY
default y
help
  This option enables the different "ima_appraise=" modes
-- 
2.13.6



[PATCH v6 0/6] Add support for architecture specific IMA policies

2018-10-09 Thread Nayna Jain
From: Nayna Jain 

The architecture specific policy, introduced in this patch set, permits
different architectures to define IMA policy rules based on kernel
configuration and system runtime information.

For example, on x86, there are two methods of verifying the kexec'ed kernel
image signature - CONFIG_KEXEC_VERIFY_SIG and IMA appraisal policy
KEXEC_KERNEL_CHECK. CONFIG_KEXEC_VERIFY_SIG enforces the kexec_file_load
syscall to verify file signatures, but does not prevent the kexec_load
syscall. The IMA KEXEC_KERNEL_CHECK policy rule verifies the kexec'ed
kernel image, loaded via the kexec_file_load syscall, is validly signed and
prevents loading a kernel image via the kexec_load syscall. When secure
boot is enabled, the kexec'ed kernel image needs to be signed and the
signature verified. In this environment, either method of verifying the
kexec'ed kernel image is acceptable, as long as the kexec_load syscall is
disabled.

The previous version of this patchset introduced a new IMA policy rule to
disable the kexec_load syscall, when CONFIG_KEXEC_VERIFY_SIG was enabled,
however that is removed from this version by introducing a different
mechanism, as described below.

The patchset defines an arch_ima_get_secureboot() function to retrieve the
secureboot state of the system. If secureboot is enabled and
CONFIG_KEXEC_VERIFY_SIG is configured, it denies permission to kexec_load
syscall.

To support architecture specific policies, a new function
arch_get_ima_policy() is defined. This patch set defines IMA
KERNEL_KEXEC_POLICY rules for x86 *only* if CONFIG_KEXEC_VERIFY_SIG is
disabled and secure boot is enabled.

This patch set includes a patch, which refactors ima_init_policy() to
remove code duplication.

Changelog:

v6:
* ima: prevent kexec_load syscall based on runtime secureboot flag
- Includes Mimi's feedback - replace #ifdef with IS_ENABLED
in .c file
* ima: add support for arch specific policies
- Fixed one line exceeding 80 character's warning
* x86/ima: define arch_get_ima_policy() for x86
- Includes Mimi's feedback - replace #ifdef with IS_ENABLED
in .c file and fixed a comment

v5:

* ima: refactor ima_init_policy()
- Includes Mimi's feedback - updated patch description, and
code fixes. 
* ima: add support for arch specific policies
- Includes Mimi's feedback - updated comment.
* ima: add support for external setting of ima_appraise
- Includes Mimi's feedback - This patch is deleted. This is
handled by enabling IMA_APPRAISE_BOOTPARAM only if IMA_ARCH_POLICY
is not enabled. The change is done in the Patch 5/5.

v4:
* ima: refactor ima_init_policy()
- Fixed the issue reported by Dan Carpenter. Replaced logical
operator (&&) with bitwise operator (&).

v3:
* x86/ima: define arch_ima_get_secureboot
- Edited subject line, added x86.

* x86/ima: define arch_get_ima_policy() for x86
- Fixed the error reported by kbuild test robot. The error was
appearing when CONFIG_X86 is enabled, but CONFIG_IMA_ARCH_POLICY
is disabled.

v2:
* ima: define arch_ima_get_secureboot
- New Patch - to retrieve secureboot state of the system
* ima: prevent kexec_load syscall based on runtime secureboot flag
- New Patch - disables kexec_load if KEXEC_VERIFY_SIG is
  configured and secureboot is enabled
* ima: refactor ima_init_policy()
- New Patch - cleans up the code duplication in
  ima_init_policy(), adds new function add_rules()
* ima: add support for arch specific policies
- modified ima_init_arch_policy() and ima_init_policy() to
  use add_rules() from previous patch.
* ima: add support for external setting of ima_appraise
- sets ima_appraise flag explicitly for arch_specific setting
* ima: add support for KEXEC_ORIG_KERNEL_CHECK
- deleted the patch based on Seth's feedback
* x86/ima: define arch_get_ima_policy() for x86
- removes the policy KEXEC_ORIG_KERNEL_CHECK based on
  Seth's feedback.

Eric Richter (1):
  x86/ima: define arch_get_ima_policy() for x86

Nayna Jain (4):
  x86/ima: define arch_ima_get_secureboot
  ima: prevent kexec_load syscall based on runtime secureboot flag
  ima: refactor ima_init_policy()
  ima: add support for arch specific policies

 arch/x86/kernel/Makefile|   2 +
 arch/x86/kernel/ima_arch.c  |  33 +++
 include/linux/ima.h |  15 
 security/integrity/ima/Kconfig  |  10 ++-
 security/integrity/ima/ima_main.c   |  17 ++--
 security/integrity/ima/ima_policy.c | 167 +++-
 6 files changed, 195 insertions(+), 49 deletions(-)
 create mode 100644 arch/x86/kernel/ima_arch.c

-- 
2.13.6



[PATCH v6 1/5] x86/ima: define arch_ima_get_secureboot

2018-10-09 Thread Nayna Jain
From: Nayna Jain 

Distros are concerned about totally disabling the kexec_load syscall.
As a compromise, the kexec_load syscall will only be disabled when
CONFIG_KEXEC_VERIFY_SIG is configured and the system is booted with
secureboot enabled.

This patch defines the new arch specific function called
arch_ima_get_secureboot() to retrieve the secureboot state of the system.

Signed-off-by: Nayna Jain 
Suggested-by: Seth Forshee 
Cc: David Howells 
Cc: Eric Biederman 
Cc: Peter Jones 
Cc: Vivek Goyal 
Cc: Dave Young 
---
 arch/x86/kernel/Makefile   |  2 ++
 arch/x86/kernel/ima_arch.c | 17 +
 include/linux/ima.h|  9 +
 3 files changed, 28 insertions(+)
 create mode 100644 arch/x86/kernel/ima_arch.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 02d6f5cf4e70..f32406e51424 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -149,3 +149,5 @@ ifeq ($(CONFIG_X86_64),y)
obj-$(CONFIG_MMCONF_FAM10H) += mmconf-fam10h_64.o
obj-y   += vsmp_64.o
 endif
+
+obj-$(CONFIG_IMA)  += ima_arch.o
diff --git a/arch/x86/kernel/ima_arch.c b/arch/x86/kernel/ima_arch.c
new file mode 100644
index ..bb5a88d2b271
--- /dev/null
+++ b/arch/x86/kernel/ima_arch.c
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 IBM Corporation
+ */
+#include 
+#include 
+
+extern struct boot_params boot_params;
+
+bool arch_ima_get_secureboot(void)
+{
+   if (efi_enabled(EFI_BOOT) &&
+   (boot_params.secure_boot == efi_secureboot_mode_enabled))
+   return true;
+   else
+   return false;
+}
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 84806b54b50a..4852255aa4f4 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -30,6 +30,15 @@ extern void ima_post_path_mknod(struct dentry *dentry);
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
 
+#ifdef CONFIG_X86
+extern bool arch_ima_get_secureboot(void);
+#else
+static inline bool arch_ima_get_secureboot(void)
+{
+   return false;
+}
+#endif
+
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
 {
-- 
2.13.6



[PATCH v6 2/5] ima: prevent kexec_load syscall based on runtime secureboot flag

2018-10-09 Thread Nayna Jain
From: Nayna Jain 

When CONFIG_KEXEC_VERIFY_SIG is enabled, the kexec_file_load syscall
requires the kexec'd kernel image to be signed. Distros are concerned
about totally disabling the kexec_load syscall. As a compromise, the
kexec_load syscall will only be disabled when CONFIG_KEXEC_VERIFY_SIG
is configured and the system is booted with secureboot enabled.

This patch disables the kexec_load syscall only for systems booted with
secureboot enabled.

Signed-off-by: Nayna Jain 
Cc: David Howells 
Cc: Eric Biederman 
Cc: Peter Jones 
Cc: Vivek Goyal 
Cc: Dave Young 
---
 security/integrity/ima/ima_main.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index dce0a8a217bb..9031c99e37a6 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -505,20 +505,24 @@ int ima_post_read_file(struct file *file, void *buf, 
loff_t size,
  */
 int ima_load_data(enum kernel_load_data_id id)
 {
-   bool sig_enforce;
+   bool ima_enforce, sig_enforce;
 
-   if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE)
-   return 0;
+   ima_enforce =
+   (ima_appraise & IMA_APPRAISE_ENFORCE) == IMA_APPRAISE_ENFORCE;
 
switch (id) {
case LOADING_KEXEC_IMAGE:
-   if (ima_appraise & IMA_APPRAISE_KEXEC) {
+   if (IS_ENABLED(CONFIG_KEXEC_VERIFY_SIG)
+   && arch_ima_get_secureboot())
+   return -EACCES;
+
+   if (ima_enforce && (ima_appraise & IMA_APPRAISE_KEXEC)) {
pr_err("impossible to appraise a kernel image without a 
file descriptor; try using kexec_file_load syscall.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
break;
case LOADING_FIRMWARE:
-   if (ima_appraise & IMA_APPRAISE_FIRMWARE) {
+   if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE)) {
pr_err("Prevent firmware sysfs fallback loading.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
@@ -526,7 +530,8 @@ int ima_load_data(enum kernel_load_data_id id)
case LOADING_MODULE:
sig_enforce = is_module_sig_enforced();
 
-   if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) {
+   if (ima_enforce && (!sig_enforce
+   && (ima_appraise & IMA_APPRAISE_MODULES))) {
pr_err("impossible to appraise a module without a file 
descriptor. sig_enforce kernel parameter might help\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
-- 
2.13.6



Re: [PATCH v4 5/6] ima: add support for external setting of ima_appraise

2018-10-05 Thread Nayna Jain




On 09/27/2018 06:50 PM, Mimi Zohar wrote:

Hi Nayna,

On Wed, 2018-09-26 at 17:52 +0530, Nayna Jain wrote:

The "ima_appraise" mode defaults to enforcing, unless configured to allow
the boot command line "ima_appraise" option. This patch explicitly sets the
"ima_appraise" mode for the arch specific policy setting.

Eventually this patch might be needed if/when we need to differentiate
between different secure boot modes.

Only if CONFIG_IMA_APPRAISE_BOOTPARAM is enabled, can the IMA appraise
mode be modified on the boot command line.  Instead of this patch, how
about making the ability to change the IMA appraise mode also
dependent on CONFIG_IMA_ARCH_POLICY not being enabled?


Yes, I did this change. I also included other feedback and posted as v5 
version.


Thanks Mimi for all the feedback.

Thanks & Regards,
    - Nayna




Mimi


Signed-off-by: Nayna Jain 
---
  security/integrity/ima/ima.h  |  5 +
  security/integrity/ima/ima_appraise.c | 11 +--
  security/integrity/ima/ima_policy.c   |  5 -
  3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 588e4813370c..6e5fa7c42809 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -248,6 +248,7 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data 
*xattr_value,
 int xattr_len);
  int ima_read_xattr(struct dentry *dentry,
   struct evm_ima_xattr_data **xattr_value);
+void set_ima_appraise(char *str);
  
  #else

  static inline int ima_appraise_measurement(enum ima_hooks func,
@@ -290,6 +291,10 @@ static inline int ima_read_xattr(struct dentry *dentry,
return 0;
  }
  
+static inline void set_ima_appraise(char *str)

+{
+}
+
  #endif /* CONFIG_IMA_APPRAISE */
  
  /* LSM based policy rules require audit */

diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 8bd7a0733e51..e061613bcb87 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -18,15 +18,22 @@
  
  #include "ima.h"
  
-static int __init default_appraise_setup(char *str)

+void set_ima_appraise(char *str)
  {
-#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
if (strncmp(str, "off", 3) == 0)
ima_appraise = 0;
else if (strncmp(str, "log", 3) == 0)
ima_appraise = IMA_APPRAISE_LOG;
else if (strncmp(str, "fix", 3) == 0)
ima_appraise = IMA_APPRAISE_FIX;
+   else if (strncmp(str, "enforce", 7) == 0)
+   ima_appraise = IMA_APPRAISE_ENFORCE;
+}
+
+static int __init default_appraise_setup(char *str)
+{
+#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
+   set_ima_appraise(str);
  #endif
return 1;
  }
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 5fb4b0c123a3..410fee31b162 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -585,9 +585,12 @@ void __init ima_init_policy(void)
arch_entries = ima_init_arch_policy();
if (!arch_entries)
pr_info("No architecture policies found\n");
-   else
+   else {
add_rules(arch_policy_entry, arch_entries,
  IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
+   if (temp_ima_appraise)
+   set_ima_appraise("enforce");
+   }
  
  	/*

 * Insert the builtin "secure_boot" policy rules requiring file




[PATCH v5 4/5] ima: add support for arch specific policies

2018-10-05 Thread Nayna Jain
From: Nayna Jain 

Builtin IMA policies can be enabled on the boot command line, and replaced
with a custom policy, normally during early boot in the initramfs. Build
time IMA policy rules were recently added. These rules are automatically
enabled on boot and persist after loading a custom policy.

There is a need for yet another type of policy, an architecture specific
policy, which is derived at runtime during kernel boot, based on the
runtime secure boot flags.  Like the build time policy rules, these rules
persist after loading a custom policy.

This patch adds support for loading an architecture specific IMA policy.

Signed-off-by: Nayna Jain 
- Defined function to convert the arch policy strings to an array of
ima_entry_rules.  The memory can then be freed after loading a custom
policy.
- Rename ima_get_arch_policy to arch_get_ima_policy.
Signed-off-by: Mimi Zohar 
- Modified ima_init_arch_policy() and ima_init_policy() to use add_rules()
from previous patch.
Signed-off-by: Nayna Jain 
---
 include/linux/ima.h |  5 +++
 security/integrity/ima/ima_policy.c | 71 +++--
 2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 4852255aa4f4..350fa957f8a6 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -39,6 +39,11 @@ static inline bool arch_ima_get_secureboot(void)
 }
 #endif
 
+static inline const char * const *arch_get_ima_policy(void)
+{
+   return NULL;
+}
+
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
 {
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 1e30d09a56db..4e435f7561e0 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ima.h"
 
@@ -195,6 +196,9 @@ static struct ima_rule_entry secure_boot_rules[] 
__ro_after_init = {
 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
 };
 
+/* An array of architecture specific rules */
+struct ima_rule_entry *arch_policy_entry __ro_after_init;
+
 static LIST_HEAD(ima_default_rules);
 static LIST_HEAD(ima_policy_rules);
 static LIST_HEAD(ima_temp_rules);
@@ -501,6 +505,48 @@ static void add_rules(struct ima_rule_entry *entries, int 
count,
}
 }
 
+static int ima_parse_rule(char *rule, struct ima_rule_entry *entry);
+
+static int __init ima_init_arch_policy(void)
+{
+   const char * const *arch_rules;
+   const char * const *rules;
+   int arch_entries = 0;
+   int i = 0;
+
+   arch_rules = arch_get_ima_policy();
+   if (!arch_rules)
+   return arch_entries;
+
+   /* Get number of rules */
+   for (rules = arch_rules; *rules != NULL; rules++)
+   arch_entries++;
+
+   arch_policy_entry = kcalloc(arch_entries + 1,
+   sizeof(*arch_policy_entry), GFP_KERNEL);
+   if (!arch_policy_entry)
+   return 0;
+
+   /* Convert each policy string rules to struct ima_rule_entry format */
+   for (rules = arch_rules, i = 0; *rules != NULL; rules++) {
+   char rule[255];
+   int result;
+
+   result = strlcpy(rule, *rules, sizeof(rule));
+
+   INIT_LIST_HEAD(_policy_entry[i].list);
+   result = ima_parse_rule(rule, _policy_entry[i]);
+   if (result) {
+   pr_warn("Skipping unknown architecture policy rule: 
%s\n", rule);
+   memset(_policy_entry[i], 0,
+  sizeof(*arch_policy_entry));
+   continue;
+   }
+   i++;
+   }
+   return i;
+}
+
 /**
  * ima_init_policy - initialize the default measure rules.
  *
@@ -509,7 +555,7 @@ static void add_rules(struct ima_rule_entry *entries, int 
count,
  */
 void __init ima_init_policy(void)
 {
-   int build_appraise_entries;
+   int build_appraise_entries, arch_entries;
 
/* if !ima_policy, we load NO default rules */
if (ima_policy)
@@ -531,8 +577,21 @@ void __init ima_init_policy(void)
}
 
/*
+* Based on runtime secure boot flags, insert arch specific measurement
+* and appraise rules requiring file signatures for both the initial
+* and custom policies, prior to other appraise rules.
+* (Highest priority)
+*/
+   arch_entries = ima_init_arch_policy();
+   if (!arch_entries)
+   pr_info("No architecture policies found\n");
+   else
+   add_rules(arch_policy_entry, arch_entries,
+ IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
+
+   /*
 * Insert the builtin "secure_boot" policy rules requiring file
-* signatures, prior to any other appraise rules.
+* signatures, prior to other appraise rules.
 */
if (ima_us

[PATCH v5 3/5] ima: refactor ima_init_policy()

2018-10-05 Thread Nayna Jain
From: Nayna Jain 

This patch removes the code duplication in ima_init_policy() by defining
a new function named add_rules(). The new function adds the rules to the
initial IMA policy, the custom policy or both based on the policy mask
(IMA_DEFAULT_POLICY, IMA_CUSTOM_POLICY).

Signed-off-by: Nayna Jain 
---
 security/integrity/ima/ima_policy.c | 97 +
 1 file changed, 56 insertions(+), 41 deletions(-)

diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 8c9499867c91..1e30d09a56db 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -58,6 +58,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, 
LSM_OBJ_TYPE,
 
 enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
 
+enum policy_rule_list { IMA_DEFAULT_POLICY = 1, IMA_CUSTOM_POLICY };
+
 struct ima_rule_entry {
struct list_head list;
int action;
@@ -473,6 +475,32 @@ static int ima_appraise_flag(enum ima_hooks func)
return 0;
 }
 
+static void add_rules(struct ima_rule_entry *entries, int count,
+ enum policy_rule_list policy_rule)
+{
+   int i = 0;
+
+   for (i = 0; i < count; i++) {
+   struct ima_rule_entry *entry;
+
+   if (policy_rule & IMA_DEFAULT_POLICY)
+   list_add_tail([i].list, _default_rules);
+
+   if (policy_rule & IMA_CUSTOM_POLICY) {
+   entry = kmemdup([i], sizeof(*entry),
+   GFP_KERNEL);
+   if (!entry)
+   continue;
+
+   list_add_tail(>list, _policy_rules);
+   }
+   if (entries[i].action == APPRAISE)
+   temp_ima_appraise |= ima_appraise_flag(entries[i].func);
+   if (entries[i].func == POLICY_CHECK)
+   temp_ima_appraise |= IMA_APPRAISE_POLICY;
+   }
+}
+
 /**
  * ima_init_policy - initialize the default measure rules.
  *
@@ -481,28 +509,23 @@ static int ima_appraise_flag(enum ima_hooks func)
  */
 void __init ima_init_policy(void)
 {
-   int i, measure_entries, appraise_entries, secure_boot_entries;
-
-   /* if !ima_policy set entries = 0 so we load NO default rules */
-   measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
-   appraise_entries = ima_use_appraise_tcb ?
-ARRAY_SIZE(default_appraise_rules) : 0;
-   secure_boot_entries = ima_use_secure_boot ?
-   ARRAY_SIZE(secure_boot_rules) : 0;
+   int build_appraise_entries;
 
-   for (i = 0; i < measure_entries; i++)
-   list_add_tail(_measure_rules[i].list, _default_rules);
+   /* if !ima_policy, we load NO default rules */
+   if (ima_policy)
+   add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules),
+ IMA_DEFAULT_POLICY);
 
switch (ima_policy) {
case ORIGINAL_TCB:
-   for (i = 0; i < ARRAY_SIZE(original_measurement_rules); i++)
-   list_add_tail(_measurement_rules[i].list,
- _default_rules);
+   add_rules(original_measurement_rules,
+ ARRAY_SIZE(original_measurement_rules),
+ IMA_DEFAULT_POLICY);
break;
case DEFAULT_TCB:
-   for (i = 0; i < ARRAY_SIZE(default_measurement_rules); i++)
-   list_add_tail(_measurement_rules[i].list,
- _default_rules);
+   add_rules(default_measurement_rules,
+ ARRAY_SIZE(default_measurement_rules),
+ IMA_DEFAULT_POLICY);
default:
break;
}
@@ -511,38 +534,30 @@ void __init ima_init_policy(void)
 * Insert the builtin "secure_boot" policy rules requiring file
 * signatures, prior to any other appraise rules.
 */
-   for (i = 0; i < secure_boot_entries; i++) {
-   list_add_tail(_boot_rules[i].list, _default_rules);
-   temp_ima_appraise |=
-   ima_appraise_flag(secure_boot_rules[i].func);
-   }
+   if (ima_use_secure_boot)
+   add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules),
+ IMA_DEFAULT_POLICY);
 
/*
 * Insert the build time appraise rules requiring file signatures
 * for both the initial and custom policies, prior to other appraise
-* rules.
+* rules. As the secure boot rules includes all of the build time
+* rules, include either one or the other set of rules, but not both.
 */
-   for (i = 0; i < ARRAY_SIZE(build_appraise_rules); i++) {
-   struct ima_rule_entry *entry;
-
-   if (!secure_boot_entries

[PATCH v5 5/5] x86/ima: define arch_get_ima_policy() for x86

2018-10-05 Thread Nayna Jain
From: Eric Richter 

On x86, there are two methods of verifying a kexec'ed kernel image
signature being loaded via the kexec_file_load syscall - an architecture
specific implementaton or a IMA KEXEC_KERNEL_CHECK appraisal rule. Neither
of these methods verify the kexec'ed kernel image signature being loaded
via the kexec_load syscall.

Secure boot enabled systems require kexec images to be signed. Therefore,
this patch loads an IMA KEXEC_KERNEL_CHECK policy rule on secure boot
enabled systems not configured with CONFIG_KEXEC_VERIFY_SIG enabled.

When IMA_APPRAISE_BOOTPARAM is configured, different IMA appraise modes
(eg. fix, log) can be specified on the boot command line, allowing unsigned
or invalidly signed kernel images to be kexec'ed. This patch permits
enabling IMA_APPRAISE_BOOTPARAM or IMA_ARCH_POLICY, but not both.

Signed-off-by: Eric Richter 
- Removed the policy KEXEC_ORIG_KERNEL_CHECK which was defined to
  disable the kexec_load syscall.
- arch_get_ima_policy() uses arch_ima_get_secureboot() to get secureboot
  state
Signed-off-by: Nayna Jain 
---
 arch/x86/kernel/ima_arch.c | 18 ++
 include/linux/ima.h|  4 
 security/integrity/ima/Kconfig | 10 +-
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/ima_arch.c b/arch/x86/kernel/ima_arch.c
index bb5a88d2b271..245976e49a55 100644
--- a/arch/x86/kernel/ima_arch.c
+++ b/arch/x86/kernel/ima_arch.c
@@ -15,3 +15,21 @@ bool arch_ima_get_secureboot(void)
else
return false;
 }
+
+/* arch rules for audit and user mode */
+static const char * const sb_arch_rules[] = {
+#ifndef CONFIG_KEXEC_VERIFY_SIG
+   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig",
+#endif /* CONFIG_KEXEC_VERIFY_SIG */
+   "measure func=KEXEC_KERNEL_CHECK",
+   NULL
+};
+
+#ifdef CONFIG_IMA_ARCH_POLICY
+const char * const *arch_get_ima_policy(void)
+{
+   if (arch_ima_get_secureboot())
+   return sb_arch_rules;
+   return NULL;
+}
+#endif
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 350fa957f8a6..dabd3abdf671 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -39,10 +39,14 @@ static inline bool arch_ima_get_secureboot(void)
 }
 #endif
 
+#if defined(CONFIG_X86) && defined(CONFIG_IMA_ARCH_POLICY)
+extern const char * const *arch_get_ima_policy(void);
+#else
 static inline const char * const *arch_get_ima_policy(void)
 {
return NULL;
 }
+#endif
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 13b446328dda..a18f8c6d13b5 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -157,6 +157,14 @@ config IMA_APPRAISE
  <http://linux-ima.sourceforge.net>
  If unsure, say N.
 
+config IMA_ARCH_POLICY
+bool "Enable loading an IMA architecture specific policy"
+depends on KEXEC_VERIFY_SIG || IMA_APPRAISE && 
INTEGRITY_ASYMMETRIC_KEYS
+default n
+help
+  This option enables loading an IMA architecture specific policy
+  based on run time secure boot flags.
+
 config IMA_APPRAISE_BUILD_POLICY
bool "IMA build time configured policy rules"
depends on IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS
@@ -217,7 +225,7 @@ config IMA_APPRAISE_REQUIRE_POLICY_SIGS
 
 config IMA_APPRAISE_BOOTPARAM
bool "ima_appraise boot parameter"
-   depends on IMA_APPRAISE
+   depends on IMA_APPRAISE && !IMA_ARCH_POLICY
default y
help
  This option enables the different "ima_appraise=" modes
-- 
2.13.6



[PATCH v5 1/5] x86/ima: define arch_ima_get_secureboot

2018-10-05 Thread Nayna Jain
From: Nayna Jain 

Distros are concerned about totally disabling the kexec_load syscall.
As a compromise, the kexec_load syscall will only be disabled when
CONFIG_KEXEC_VERIFY_SIG is configured and the system is booted with
secureboot enabled.

This patch defines the new arch specific function called
arch_ima_get_secureboot() to retrieve the secureboot state of the system.

Signed-off-by: Nayna Jain 
Suggested-by: Seth Forshee 
---
 arch/x86/kernel/Makefile   |  2 ++
 arch/x86/kernel/ima_arch.c | 17 +
 include/linux/ima.h|  9 +
 3 files changed, 28 insertions(+)
 create mode 100644 arch/x86/kernel/ima_arch.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 02d6f5cf4e70..f32406e51424 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -149,3 +149,5 @@ ifeq ($(CONFIG_X86_64),y)
obj-$(CONFIG_MMCONF_FAM10H) += mmconf-fam10h_64.o
obj-y   += vsmp_64.o
 endif
+
+obj-$(CONFIG_IMA)  += ima_arch.o
diff --git a/arch/x86/kernel/ima_arch.c b/arch/x86/kernel/ima_arch.c
new file mode 100644
index ..bb5a88d2b271
--- /dev/null
+++ b/arch/x86/kernel/ima_arch.c
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 IBM Corporation
+ */
+#include 
+#include 
+
+extern struct boot_params boot_params;
+
+bool arch_ima_get_secureboot(void)
+{
+   if (efi_enabled(EFI_BOOT) &&
+   (boot_params.secure_boot == efi_secureboot_mode_enabled))
+   return true;
+   else
+   return false;
+}
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 84806b54b50a..4852255aa4f4 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -30,6 +30,15 @@ extern void ima_post_path_mknod(struct dentry *dentry);
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
 
+#ifdef CONFIG_X86
+extern bool arch_ima_get_secureboot(void);
+#else
+static inline bool arch_ima_get_secureboot(void)
+{
+   return false;
+}
+#endif
+
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
 {
-- 
2.13.6



[PATCH v5 0/6] Add support for architecture specific IMA policies

2018-10-05 Thread Nayna Jain
From: Nayna Jain 

The architecture specific policy, introduced in this patch set, permits
different architectures to define IMA policy rules based on kernel
configuration and system runtime information.

For example, on x86, there are two methods of verifying the kexec'ed kernel
image signature - CONFIG_KEXEC_VERIFY_SIG and IMA appraisal policy
KEXEC_KERNEL_CHECK. CONFIG_KEXEC_VERIFY_SIG enforces the kexec_file_load
syscall to verify file signatures, but does not prevent the kexec_load
syscall. The IMA KEXEC_KERNEL_CHECK policy rule verifies the kexec'ed
kernel image, loaded via the kexec_file_load syscall, is validly signed and
prevents loading a kernel image via the kexec_load syscall. When secure
boot is enabled, the kexec'ed kernel image needs to be signed and the
signature verified. In this environment, either method of verifying the
kexec'ed kernel image is acceptable, as long as the kexec_load syscall is
disabled.

The previous version of this patchset introduced a new IMA policy rule to
disable the kexec_load syscall, when CONFIG_KEXEC_VERIFY_SIG was enabled,
however that is removed from this version by introducing a different
mechanism, as described below.

The patchset defines an arch_ima_get_secureboot() function to retrieve the
secureboot state of the system. If secureboot is enabled and
CONFIG_KEXEC_VERIFY_SIG is configured, it denies permission to kexec_load
syscall.

To support architecture specific policies, a new function
arch_get_ima_policy() is defined. This patch set defines IMA
KERNEL_KEXEC_POLICY rules for x86 *only* if CONFIG_KEXEC_VERIFY_SIG is
disabled and secure boot is enabled.

This patch set includes a patch, which refactors ima_init_policy() to
remove code duplication.

Changelog:

v5:

* ima: refactor ima_init_policy()
- Includes Mimi's feedback - updated patch description, and
code fixes. 
* ima: add support for arch specific policies
- Includes Mimi's feedback - updated comment.
* ima: add support for external setting of ima_appraise
- Includes Mimi's feedback - This patch is deleted. This is
handled by enabling IMA_APPRAISE_BOOTPARAM only if IMA_ARCH_POLICY
is not enabled. The change is done in the Patch 5/5.

v4:
* ima: refactor ima_init_policy()
- Fixed the issue reported by Dan Carpenter. Replaced logical
operator (&&) with bitwise operator (&).

v3:
* x86/ima: define arch_ima_get_secureboot
- Edited subject line, added x86.

* x86/ima: define arch_get_ima_policy() for x86
- Fixed the error reported by kbuild test robot. The error was
appearing when CONFIG_X86 is enabled, but CONFIG_IMA_ARCH_POLICY
is disabled.

v2:
* ima: define arch_ima_get_secureboot
- New Patch - to retrieve secureboot state of the system
* ima: prevent kexec_load syscall based on runtime secureboot flag
- New Patch - disables kexec_load if KEXEC_VERIFY_SIG is
  configured and secureboot is enabled
* ima: refactor ima_init_policy()
- New Patch - cleans up the code duplication in
  ima_init_policy(), adds new function add_rules()
* ima: add support for arch specific policies
- modified ima_init_arch_policy() and ima_init_policy() to
  use add_rules() from previous patch.
* ima: add support for external setting of ima_appraise
- sets ima_appraise flag explicitly for arch_specific setting
* ima: add support for KEXEC_ORIG_KERNEL_CHECK
- deleted the patch based on Seth's feedback
* x86/ima: define arch_get_ima_policy() for x86
- removes the policy KEXEC_ORIG_KERNEL_CHECK based on
  Seth's feedback.

Eric Richter (1):
  x86/ima: define arch_get_ima_policy() for x86

Nayna Jain (4):
  x86/ima: define arch_ima_get_secureboot
  ima: prevent kexec_load syscall based on runtime secureboot flag
  ima: refactor ima_init_policy()
  ima: add support for arch specific policies

 arch/x86/kernel/Makefile|   2 +
 arch/x86/kernel/ima_arch.c  |  35 
 include/linux/ima.h |  18 
 security/integrity/ima/Kconfig  |  10 ++-
 security/integrity/ima/ima_main.c   |  17 ++--
 security/integrity/ima/ima_policy.c | 166 +++-
 6 files changed, 199 insertions(+), 49 deletions(-)
 create mode 100644 arch/x86/kernel/ima_arch.c

-- 
2.13.6



[PATCH v5 2/5] ima: prevent kexec_load syscall based on runtime secureboot flag

2018-10-05 Thread Nayna Jain
From: Nayna Jain 

When CONFIG_KEXEC_VERIFY_SIG is enabled, the kexec_file_load syscall
requires the kexec'd kernel image to be signed. Distros are concerned
about totally disabling the kexec_load syscall. As a compromise, the
kexec_load syscall will only be disabled when CONFIG_KEXEC_VERIFY_SIG
is configured and the system is booted with secureboot enabled.

This patch disables the kexec_load syscall only for systems booted with
secureboot enabled.

Signed-off-by: Nayna Jain 
---
 security/integrity/ima/ima_main.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index dce0a8a217bb..bdb6e5563d05 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -505,20 +505,24 @@ int ima_post_read_file(struct file *file, void *buf, 
loff_t size,
  */
 int ima_load_data(enum kernel_load_data_id id)
 {
-   bool sig_enforce;
+   bool ima_enforce, sig_enforce;
 
-   if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE)
-   return 0;
+   ima_enforce =
+   (ima_appraise & IMA_APPRAISE_ENFORCE) == IMA_APPRAISE_ENFORCE;
 
switch (id) {
case LOADING_KEXEC_IMAGE:
-   if (ima_appraise & IMA_APPRAISE_KEXEC) {
+#ifdef CONFIG_KEXEC_VERIFY_SIG
+   if (arch_ima_get_secureboot())
+   return -EACCES;
+#endif
+   if (ima_enforce && (ima_appraise & IMA_APPRAISE_KEXEC)) {
pr_err("impossible to appraise a kernel image without a 
file descriptor; try using kexec_file_load syscall.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
break;
case LOADING_FIRMWARE:
-   if (ima_appraise & IMA_APPRAISE_FIRMWARE) {
+   if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE)) {
pr_err("Prevent firmware sysfs fallback loading.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
@@ -526,7 +530,8 @@ int ima_load_data(enum kernel_load_data_id id)
case LOADING_MODULE:
sig_enforce = is_module_sig_enforced();
 
-   if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) {
+   if (ima_enforce && (!sig_enforce
+   && (ima_appraise & IMA_APPRAISE_MODULES))) {
pr_err("impossible to appraise a module without a file 
descriptor. sig_enforce kernel parameter might help\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
-- 
2.13.6



[PATCH v4 4/6] ima: add support for arch specific policies

2018-09-26 Thread Nayna Jain
Builtin IMA policies can be enabled on the boot command line, and replaced
with a custom policy, normally during early boot in the initramfs. Build
time IMA policy rules were recently added. These rules are automatically
enabled on boot and persist after loading a custom policy.

There is a need for yet another type of policy, an architecture specific
policy, which is derived at runtime during kernel boot, based on the
runtime secure boot flags.  Like the build time policy rules, these rules
persist after loading a custom policy.

This patch adds support for loading an architecture specific IMA policy.

Signed-off-by: Nayna Jain 
- Defined function to convert the arch policy strings to an array of
ima_entry_rules.  The memory can then be freed after loading a custom
policy.
- Rename ima_get_arch_policy to arch_get_ima_policy.
Signed-off-by: Mimi Zohar 
- Modified ima_init_arch_policy() and ima_init_policy() to use add_rules()
from previous patch.
Signed-off-by: Nayna Jain 
---
 include/linux/ima.h |  5 +++
 security/integrity/ima/ima_policy.c | 70 +++--
 2 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 4852255aa4f4..350fa957f8a6 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -39,6 +39,11 @@ static inline bool arch_ima_get_secureboot(void)
 }
 #endif
 
+static inline const char * const *arch_get_ima_policy(void)
+{
+   return NULL;
+}
+
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
 {
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index d5b327320d3a..5fb4b0c123a3 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ima.h"
 
@@ -195,6 +196,9 @@ static struct ima_rule_entry secure_boot_rules[] 
__ro_after_init = {
 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
 };
 
+/* An array of architecture specific rules */
+struct ima_rule_entry *arch_policy_entry __ro_after_init;
+
 static LIST_HEAD(ima_default_rules);
 static LIST_HEAD(ima_policy_rules);
 static LIST_HEAD(ima_temp_rules);
@@ -492,7 +496,6 @@ static void add_rules(struct ima_rule_entry *entries, int 
count,
if (!entry)
continue;
 
-   INIT_LIST_HEAD(>list);
list_add_tail(>list, _policy_rules);
}
if (entries[i].action == APPRAISE)
@@ -502,6 +505,48 @@ static void add_rules(struct ima_rule_entry *entries, int 
count,
}
 }
 
+static int ima_parse_rule(char *rule, struct ima_rule_entry *entry);
+
+static int __init ima_init_arch_policy(void)
+{
+   const char * const *arch_rules;
+   const char * const *rules;
+   int arch_entries = 0;
+   int i = 0;
+
+   arch_rules = arch_get_ima_policy();
+   if (!arch_rules)
+   return arch_entries;
+
+   /* Get number of rules */
+   for (rules = arch_rules; *rules != NULL; rules++)
+   arch_entries++;
+
+   arch_policy_entry = kcalloc(arch_entries + 1,
+   sizeof(*arch_policy_entry), GFP_KERNEL);
+   if (!arch_policy_entry)
+   return 0;
+
+   /* Convert each policy string rules to struct ima_rule_entry format */
+   for (rules = arch_rules, i = 0; *rules != NULL; rules++) {
+   char rule[255];
+   int result;
+
+   result = strlcpy(rule, *rules, sizeof(rule));
+
+   INIT_LIST_HEAD(_policy_entry[i].list);
+   result = ima_parse_rule(rule, _policy_entry[i]);
+   if (result) {
+   pr_warn("Skipping unknown architecture policy rule: 
%s\n", rule);
+   memset(_policy_entry[i], 0,
+  sizeof(*arch_policy_entry));
+   continue;
+   }
+   i++;
+   }
+   return i;
+}
+
 /**
  * ima_init_policy - initialize the default measure rules.
  *
@@ -510,7 +555,7 @@ static void add_rules(struct ima_rule_entry *entries, int 
count,
  */
 void __init ima_init_policy(void)
 {
-   int build_appraise_entries;
+   int build_appraise_entries, arch_entries;
 
/* if !ima_policy, we load NO default rules */
if (ima_policy)
@@ -532,6 +577,19 @@ void __init ima_init_policy(void)
}
 
/*
+* Based on runtime secure boot flags, insert arch specific measurement
+* and appraise rules requiring file signatures for both the initial
+* and custom policies, prior to other appraise rules.
+* (Highest priority)
+*/
+   arch_entries = ima_init_arch_policy();
+   if (!arch_entries)
+   pr_info("No architecture policies found\n");
+   else
+   add_r

[PATCH v4 6/6] x86/ima: define arch_get_ima_policy() for x86

2018-09-26 Thread Nayna Jain
From: Eric Richter 

This patch implements an example arch-specific IMA policy for x86 to
enable measurement and appraisal of any kernel image loaded for kexec,
when CONFIG_KEXEC_VERIFY_SIG is not enabled.

For systems with CONFIG_KEXEC_VERIFY_SIG enabled, only the measurement
rule is enabled, not the IMA-appraisal rule.

Signed-off-by: Eric Richter 
- Removed the policy KEXEC_ORIG_KERNEL_CHECK which was defined to
  disable the kexec_load syscall.
- arch_get_ima_policy() uses arch_ima_get_secureboot() to get secureboot
  state
Signed-off-by: Nayna Jain 
---
 arch/x86/kernel/ima_arch.c | 18 ++
 include/linux/ima.h|  4 
 security/integrity/ima/Kconfig |  8 
 3 files changed, 30 insertions(+)

diff --git a/arch/x86/kernel/ima_arch.c b/arch/x86/kernel/ima_arch.c
index bb5a88d2b271..245976e49a55 100644
--- a/arch/x86/kernel/ima_arch.c
+++ b/arch/x86/kernel/ima_arch.c
@@ -15,3 +15,21 @@ bool arch_ima_get_secureboot(void)
else
return false;
 }
+
+/* arch rules for audit and user mode */
+static const char * const sb_arch_rules[] = {
+#ifndef CONFIG_KEXEC_VERIFY_SIG
+   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig",
+#endif /* CONFIG_KEXEC_VERIFY_SIG */
+   "measure func=KEXEC_KERNEL_CHECK",
+   NULL
+};
+
+#ifdef CONFIG_IMA_ARCH_POLICY
+const char * const *arch_get_ima_policy(void)
+{
+   if (arch_ima_get_secureboot())
+   return sb_arch_rules;
+   return NULL;
+}
+#endif
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 350fa957f8a6..dabd3abdf671 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -39,10 +39,14 @@ static inline bool arch_ima_get_secureboot(void)
 }
 #endif
 
+#if defined(CONFIG_X86) && defined(CONFIG_IMA_ARCH_POLICY)
+extern const char * const *arch_get_ima_policy(void);
+#else
 static inline const char * const *arch_get_ima_policy(void)
 {
return NULL;
 }
+#endif
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 13b446328dda..97609a76aa14 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -157,6 +157,14 @@ config IMA_APPRAISE
  <http://linux-ima.sourceforge.net>
  If unsure, say N.
 
+config IMA_ARCH_POLICY
+bool "Enable loading an IMA architecture specific policy"
+depends on KEXEC_VERIFY_SIG || IMA_APPRAISE && 
INTEGRITY_ASYMMETRIC_KEYS
+default n
+help
+  This option enables loading an IMA architecture specific policy
+  based on run time secure boot flags.
+
 config IMA_APPRAISE_BUILD_POLICY
bool "IMA build time configured policy rules"
depends on IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS
-- 
2.13.6



[PATCH v4 5/6] ima: add support for external setting of ima_appraise

2018-09-26 Thread Nayna Jain
The "ima_appraise" mode defaults to enforcing, unless configured to allow
the boot command line "ima_appraise" option. This patch explicitly sets the
"ima_appraise" mode for the arch specific policy setting.

Signed-off-by: Nayna Jain 
---
 security/integrity/ima/ima.h  |  5 +
 security/integrity/ima/ima_appraise.c | 11 +--
 security/integrity/ima/ima_policy.c   |  5 -
 3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 588e4813370c..6e5fa7c42809 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -248,6 +248,7 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data 
*xattr_value,
 int xattr_len);
 int ima_read_xattr(struct dentry *dentry,
   struct evm_ima_xattr_data **xattr_value);
+void set_ima_appraise(char *str);
 
 #else
 static inline int ima_appraise_measurement(enum ima_hooks func,
@@ -290,6 +291,10 @@ static inline int ima_read_xattr(struct dentry *dentry,
return 0;
 }
 
+static inline void set_ima_appraise(char *str)
+{
+}
+
 #endif /* CONFIG_IMA_APPRAISE */
 
 /* LSM based policy rules require audit */
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 8bd7a0733e51..e061613bcb87 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -18,15 +18,22 @@
 
 #include "ima.h"
 
-static int __init default_appraise_setup(char *str)
+void set_ima_appraise(char *str)
 {
-#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
if (strncmp(str, "off", 3) == 0)
ima_appraise = 0;
else if (strncmp(str, "log", 3) == 0)
ima_appraise = IMA_APPRAISE_LOG;
else if (strncmp(str, "fix", 3) == 0)
ima_appraise = IMA_APPRAISE_FIX;
+   else if (strncmp(str, "enforce", 7) == 0)
+   ima_appraise = IMA_APPRAISE_ENFORCE;
+}
+
+static int __init default_appraise_setup(char *str)
+{
+#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
+   set_ima_appraise(str);
 #endif
return 1;
 }
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 5fb4b0c123a3..410fee31b162 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -585,9 +585,12 @@ void __init ima_init_policy(void)
arch_entries = ima_init_arch_policy();
if (!arch_entries)
pr_info("No architecture policies found\n");
-   else
+   else {
add_rules(arch_policy_entry, arch_entries,
  IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
+   if (temp_ima_appraise)
+   set_ima_appraise("enforce");
+   }
 
/*
 * Insert the builtin "secure_boot" policy rules requiring file
-- 
2.13.6



[PATCH v4 1/6] x86/ima: define arch_ima_get_secureboot

2018-09-26 Thread Nayna Jain
Distros are concerned about totally disabling the kexec_load syscall.
As a compromise, the kexec_load syscall will only be disabled when
CONFIG_KEXEC_VERIFY_SIG is configured and the system is booted with
secureboot enabled.

This patch defines the new arch specific function called
arch_ima_get_secureboot() to retrieve the secureboot state of the system.

Signed-off-by: Nayna Jain 
Suggested-by: Seth Forshee 
---
 arch/x86/kernel/Makefile   |  2 ++
 arch/x86/kernel/ima_arch.c | 17 +
 include/linux/ima.h|  9 +
 3 files changed, 28 insertions(+)
 create mode 100644 arch/x86/kernel/ima_arch.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 02d6f5cf4e70..f32406e51424 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -149,3 +149,5 @@ ifeq ($(CONFIG_X86_64),y)
obj-$(CONFIG_MMCONF_FAM10H) += mmconf-fam10h_64.o
obj-y   += vsmp_64.o
 endif
+
+obj-$(CONFIG_IMA)  += ima_arch.o
diff --git a/arch/x86/kernel/ima_arch.c b/arch/x86/kernel/ima_arch.c
new file mode 100644
index ..bb5a88d2b271
--- /dev/null
+++ b/arch/x86/kernel/ima_arch.c
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 IBM Corporation
+ */
+#include 
+#include 
+
+extern struct boot_params boot_params;
+
+bool arch_ima_get_secureboot(void)
+{
+   if (efi_enabled(EFI_BOOT) &&
+   (boot_params.secure_boot == efi_secureboot_mode_enabled))
+   return true;
+   else
+   return false;
+}
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 84806b54b50a..4852255aa4f4 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -30,6 +30,15 @@ extern void ima_post_path_mknod(struct dentry *dentry);
 extern void ima_add_kexec_buffer(struct kimage *image);
 #endif
 
+#ifdef CONFIG_X86
+extern bool arch_ima_get_secureboot(void);
+#else
+static inline bool arch_ima_get_secureboot(void)
+{
+   return false;
+}
+#endif
+
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
 {
-- 
2.13.6



[PATCH v4 3/6] ima: refactor ima_init_policy()

2018-09-26 Thread Nayna Jain
This patch removes the code duplication in ima_init_policy() by defining
a new function named add_rules().

Signed-off-by: Nayna Jain 
---
 security/integrity/ima/ima_policy.c | 98 +
 1 file changed, 57 insertions(+), 41 deletions(-)

diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 8c9499867c91..d5b327320d3a 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -58,6 +58,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, 
LSM_OBJ_TYPE,
 
 enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
 
+enum policy_rule_list { IMA_DEFAULT_POLICY = 1, IMA_CUSTOM_POLICY };
+
 struct ima_rule_entry {
struct list_head list;
int action;
@@ -473,6 +475,33 @@ static int ima_appraise_flag(enum ima_hooks func)
return 0;
 }
 
+static void add_rules(struct ima_rule_entry *entries, int count,
+ enum policy_rule_list file)
+{
+   int i = 0;
+
+   for (i = 0; i < count; i++) {
+   struct ima_rule_entry *entry;
+
+   if (file & IMA_DEFAULT_POLICY)
+   list_add_tail([i].list, _default_rules);
+
+   if (file & IMA_CUSTOM_POLICY) {
+   entry = kmemdup([i], sizeof(*entry),
+   GFP_KERNEL);
+   if (!entry)
+   continue;
+
+   INIT_LIST_HEAD(>list);
+   list_add_tail(>list, _policy_rules);
+   }
+   if (entries[i].action == APPRAISE)
+   temp_ima_appraise |= ima_appraise_flag(entries[i].func);
+   if (entries[i].func == POLICY_CHECK)
+   temp_ima_appraise |= IMA_APPRAISE_POLICY;
+   }
+}
+
 /**
  * ima_init_policy - initialize the default measure rules.
  *
@@ -481,28 +510,23 @@ static int ima_appraise_flag(enum ima_hooks func)
  */
 void __init ima_init_policy(void)
 {
-   int i, measure_entries, appraise_entries, secure_boot_entries;
-
-   /* if !ima_policy set entries = 0 so we load NO default rules */
-   measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
-   appraise_entries = ima_use_appraise_tcb ?
-ARRAY_SIZE(default_appraise_rules) : 0;
-   secure_boot_entries = ima_use_secure_boot ?
-   ARRAY_SIZE(secure_boot_rules) : 0;
+   int build_appraise_entries;
 
-   for (i = 0; i < measure_entries; i++)
-   list_add_tail(_measure_rules[i].list, _default_rules);
+   /* if !ima_policy, we load NO default rules */
+   if (ima_policy)
+   add_rules(dont_measure_rules, ARRAY_SIZE(dont_measure_rules),
+ IMA_DEFAULT_POLICY);
 
switch (ima_policy) {
case ORIGINAL_TCB:
-   for (i = 0; i < ARRAY_SIZE(original_measurement_rules); i++)
-   list_add_tail(_measurement_rules[i].list,
- _default_rules);
+   add_rules(original_measurement_rules,
+ ARRAY_SIZE(original_measurement_rules),
+ IMA_DEFAULT_POLICY);
break;
case DEFAULT_TCB:
-   for (i = 0; i < ARRAY_SIZE(default_measurement_rules); i++)
-   list_add_tail(_measurement_rules[i].list,
- _default_rules);
+   add_rules(default_measurement_rules,
+ ARRAY_SIZE(default_measurement_rules),
+ IMA_DEFAULT_POLICY);
default:
break;
}
@@ -511,38 +535,30 @@ void __init ima_init_policy(void)
 * Insert the builtin "secure_boot" policy rules requiring file
 * signatures, prior to any other appraise rules.
 */
-   for (i = 0; i < secure_boot_entries; i++) {
-   list_add_tail(_boot_rules[i].list, _default_rules);
-   temp_ima_appraise |=
-   ima_appraise_flag(secure_boot_rules[i].func);
-   }
+   if (ima_use_secure_boot)
+   add_rules(secure_boot_rules, ARRAY_SIZE(secure_boot_rules),
+ IMA_DEFAULT_POLICY);
 
/*
 * Insert the build time appraise rules requiring file signatures
 * for both the initial and custom policies, prior to other appraise
-* rules.
+* rules. As the secure boot rules includes all of the build time
+* rules, include either one or the other set of rules, but not both.
 */
-   for (i = 0; i < ARRAY_SIZE(build_appraise_rules); i++) {
-   struct ima_rule_entry *entry;
-
-   if (!secure_boot_entries)
-   list_add_tail(_appraise_rules[i].list,
- _default_rules);
-
-   entry =

[PATCH v4 2/6] ima: prevent kexec_load syscall based on runtime secureboot flag

2018-09-26 Thread Nayna Jain
When CONFIG_KEXEC_VERIFY_SIG is enabled, the kexec_file_load syscall
requires the kexec'd kernel image to be signed. Distros are concerned
about totally disabling the kexec_load syscall. As a compromise, the
kexec_load syscall will only be disabled when CONFIG_KEXEC_VERIFY_SIG
is configured and the system is booted with secureboot enabled.

This patch disables the kexec_load syscall only for systems booted with
secureboot enabled.

Signed-off-by: Nayna Jain 
---
 security/integrity/ima/ima_main.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index dce0a8a217bb..bdb6e5563d05 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -505,20 +505,24 @@ int ima_post_read_file(struct file *file, void *buf, 
loff_t size,
  */
 int ima_load_data(enum kernel_load_data_id id)
 {
-   bool sig_enforce;
+   bool ima_enforce, sig_enforce;
 
-   if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE)
-   return 0;
+   ima_enforce =
+   (ima_appraise & IMA_APPRAISE_ENFORCE) == IMA_APPRAISE_ENFORCE;
 
switch (id) {
case LOADING_KEXEC_IMAGE:
-   if (ima_appraise & IMA_APPRAISE_KEXEC) {
+#ifdef CONFIG_KEXEC_VERIFY_SIG
+   if (arch_ima_get_secureboot())
+   return -EACCES;
+#endif
+   if (ima_enforce && (ima_appraise & IMA_APPRAISE_KEXEC)) {
pr_err("impossible to appraise a kernel image without a 
file descriptor; try using kexec_file_load syscall.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
break;
case LOADING_FIRMWARE:
-   if (ima_appraise & IMA_APPRAISE_FIRMWARE) {
+   if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE)) {
pr_err("Prevent firmware sysfs fallback loading.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
@@ -526,7 +530,8 @@ int ima_load_data(enum kernel_load_data_id id)
case LOADING_MODULE:
sig_enforce = is_module_sig_enforced();
 
-   if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) {
+   if (ima_enforce && (!sig_enforce
+   && (ima_appraise & IMA_APPRAISE_MODULES))) {
pr_err("impossible to appraise a module without a file 
descriptor. sig_enforce kernel parameter might help\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
-- 
2.13.6



[PATCH v4 0/6] Add support for architecture specific IMA policies

2018-09-26 Thread Nayna Jain
The architecture specific policy, introduced in this patch set, permits
different architectures to define IMA policy rules based on kernel
configuration and system runtime information.

For example, on x86, there are two methods of verifying the kexec'ed kernel
image signature - CONFIG_KEXEC_VERIFY_SIG and IMA appraisal policy
KEXEC_KERNEL_CHECK. CONFIG_KEXEC_VERIFY_SIG enforces the kexec_file_load
syscall to verify file signatures, but does not prevent the kexec_load
syscall. The IMA KEXEC_KERNEL_CHECK policy rule verifies the kexec'ed
kernel image, loaded via the kexec_file_load syscall, is validly signed and
prevents loading a kernel image via the kexec_load syscall. When secure
boot is enabled, the kexec'ed kernel image needs to be signed and the
signature verified. In this environment, either method of verifying the
kexec'ed kernel image is acceptable, as long as the kexec_load syscall is
disabled.

The previous version of this patchset introduced a new IMA policy rule to
disable the kexec_load syscall, when CONFIG_KEXEC_VERIFY_SIG was enabled,
however that is removed from this version by introducing a different
mechanism.

The patchset defines an arch_ima_get_secureboot() function to retrieve the
secureboot state of the system. If secureboot is enabled and
CONFIG_KEXEC_VERIFY_SIG is configured, it denies permission to kexec_load
syscall.

To support architecture specific policies, a new function
arch_get_ima_policy() is defined. This patch set defines IMA
KERNEL_KEXEC_POLICY rules for x86 only if CONFIG_KEXEC_VERIFY_SIG is
disabled and secure boot is enabled.

This patch set includes a patch, which refactors ima_init_policy() to
remove code duplication.

Changelog:

v4:
* ima: refactor ima_init_policy()
- Fixed the issue reported by Dan Carpenter. Replaced logical
operator (&&) with bitwise operator (&).

v3:
* x86/ima: define arch_ima_get_secureboot
- Edited subject line, added x86.

* x86/ima: define arch_get_ima_policy() for x86
- Fixed the error reported by kbuild test robot. The error was
appearing when CONFIG_X86 is enabled, but CONFIG_IMA_ARCH_POLICY
is disabled.

v2:
* ima: define arch_ima_get_secureboot
- New Patch - to retrieve secureboot state of the system
* ima: prevent kexec_load syscall based on runtime secureboot flag
- New Patch - disables kexec_load if KEXEC_VERIFY_SIG is
  configured and secureboot is enabled
* ima: refactor ima_init_policy()
- New Patch - cleans up the code duplication in
  ima_init_policy(), adds new function add_rules()
* ima: add support for arch specific policies
- modified ima_init_arch_policy() and ima_init_policy() to
  use add_rules() from previous patch.
* ima: add support for external setting of ima_appraise
- sets ima_appraise flag explicitly for arch_specific setting
* ima: add support for KEXEC_ORIG_KERNEL_CHECK
- deleted the patch based on Seth's feedback
* x86/ima: define arch_get_ima_policy() for x86
- removes the policy KEXEC_ORIG_KERNEL_CHECK based on
  Seth's feedback.

Eric Richter (1):
  x86/ima: define arch_get_ima_policy() for x86

Nayna Jain (5):
  x86/ima: define arch_ima_get_secureboot
  ima: prevent kexec_load syscall based on runtime secureboot flag
  ima: refactor ima_init_policy()
  ima: add support for arch specific policies
  ima: add support for external setting of ima_appraise

 arch/x86/kernel/Makefile  |   2 +
 arch/x86/kernel/ima_arch.c|  35 +++
 include/linux/ima.h   |  18 
 security/integrity/ima/Kconfig|   8 ++
 security/integrity/ima/ima.h  |   5 +
 security/integrity/ima/ima_appraise.c |  11 ++-
 security/integrity/ima/ima_main.c |  17 ++--
 security/integrity/ima/ima_policy.c   | 167 +-
 8 files changed, 214 insertions(+), 49 deletions(-)
 create mode 100644 arch/x86/kernel/ima_arch.c

-- 
2.13.6



Re: [PATCH v3 3/6] ima: refactor ima_init_policy()

2018-09-24 Thread Nayna Jain




On 09/21/2018 02:04 PM, Dan Carpenter wrote:

Hi Nayna,

Thank you for the patch! Perhaps something to improve:

url:
https://github.com/0day-ci/linux/commits/Nayna-Jain/Add-support-for-architecture-specific-IMA-policies/20180920-035110

smatch warnings:
security/integrity/ima/ima_policy.c:489 add_rules() warn: should this be a 
bitwise op?

# 
https://github.com/0day-ci/linux/commit/84a2e186f940ebc6c34e6d276e55f665167a5bb8
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout 84a2e186f940ebc6c34e6d276e55f665167a5bb8
vim +489 security/integrity/ima/ima_policy.c

6f0911a6 Mimi Zohar 2018-04-12  477
84a2e186 Nayna Jain 2018-09-19  478  static void add_rules(struct 
ima_rule_entry *entries, int count,
84a2e186 Nayna Jain 2018-09-19  479   enum policy_rule_list 
file)
84a2e186 Nayna Jain 2018-09-19  480  {
84a2e186 Nayna Jain 2018-09-19  481 int i = 0;
84a2e186 Nayna Jain 2018-09-19  482
84a2e186 Nayna Jain 2018-09-19  483 for (i = 0; i < count; i++) {
84a2e186 Nayna Jain 2018-09-19  484 struct ima_rule_entry *entry;
84a2e186 Nayna Jain 2018-09-19  485
84a2e186 Nayna Jain 2018-09-19  486 if (file && IMA_DEFAULT_POLICY)
 ^^
84a2e186 Nayna Jain 2018-09-19  487 
list_add_tail([i].list, _default_rules);
84a2e186 Nayna Jain 2018-09-19  488
84a2e186 Nayna Jain 2018-09-19 @489 if (file && IMA_CUSTOM_POLICY) {
 ^

It does look like it should be "if (file & IMA_CUSTOM_POLICY) {" but I
haven't looked at the context besides what's here in this email.

Thanks Dan for noticing this. Yes, I will fix it and post the v4 version.

Thanks & Regards,
    - Nayna




84a2e186 Nayna Jain 2018-09-19  490 entry = 
kmemdup([i], sizeof(*entry),
84a2e186 Nayna Jain 2018-09-19  491     
GFP_KERNEL);
84a2e186 Nayna Jain 2018-09-19  492     if (!entry)
84a2e186 Nayna Jain 2018-09-19  493     continue;
84a2e186 Nayna Jain 2018-09-19  494
84a2e186 Nayna Jain 2018-09-19  495 
INIT_LIST_HEAD(>list);
84a2e186 Nayna Jain 2018-09-19  496 list_add_tail(>list, 
_policy_rules);
84a2e186 Nayna Jain 2018-09-19  497 }
84a2e186 Nayna Jain 2018-09-19  498 if (entries[i].action == 
APPRAISE)
84a2e186 Nayna Jain 2018-09-19  499 temp_ima_appraise |= 
ima_appraise_flag(entries[i].func);
84a2e186 Nayna Jain 2018-09-19  500 if (entries[i].func == 
POLICY_CHECK)
84a2e186 Nayna Jain 2018-09-19  501 temp_ima_appraise |= 
IMA_APPRAISE_POLICY;
84a2e186 Nayna Jain 2018-09-19  502 }
84a2e186 Nayna Jain 2018-09-19  503  }
84a2e186 Nayna Jain 2018-09-19  504

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation





[PATCH v3 6/6] x86/ima: define arch_get_ima_policy() for x86

2018-09-19 Thread Nayna Jain
From: Eric Richter 

This patch implements an example arch-specific IMA policy for x86 to
enable measurement and appraisal of any kernel image loaded for kexec,
when CONFIG_KEXEC_VERIFY_SIG is not enabled.

For systems with CONFIG_KEXEC_VERIFY_SIG enabled, only the measurement
rule is enabled, not the IMA-appraisal rule.

Signed-off-by: Eric Richter 
- Removed the policy KEXEC_ORIG_KERNEL_CHECK which was defined to
  disable the kexec_load syscall.
- arch_get_ima_policy() uses arch_ima_get_secureboot() to get secureboot
  state
Signed-off-by: Nayna Jain 
---
 arch/x86/kernel/ima_arch.c | 18 ++
 include/linux/ima.h|  4 
 security/integrity/ima/Kconfig |  8 
 3 files changed, 30 insertions(+)

diff --git a/arch/x86/kernel/ima_arch.c b/arch/x86/kernel/ima_arch.c
index bb5a88d2b271..245976e49a55 100644
--- a/arch/x86/kernel/ima_arch.c
+++ b/arch/x86/kernel/ima_arch.c
@@ -15,3 +15,21 @@ bool arch_ima_get_secureboot(void)
else
return false;
 }
+
+/* arch rules for audit and user mode */
+static const char * const sb_arch_rules[] = {
+#ifndef CONFIG_KEXEC_VERIFY_SIG
+   "appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig",
+#endif /* CONFIG_KEXEC_VERIFY_SIG */
+   "measure func=KEXEC_KERNEL_CHECK",
+   NULL
+};
+
+#ifdef CONFIG_IMA_ARCH_POLICY
+const char * const *arch_get_ima_policy(void)
+{
+   if (arch_ima_get_secureboot())
+   return sb_arch_rules;
+   return NULL;
+}
+#endif
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 350fa957f8a6..dabd3abdf671 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -39,10 +39,14 @@ static inline bool arch_ima_get_secureboot(void)
 }
 #endif
 
+#if defined(CONFIG_X86) && defined(CONFIG_IMA_ARCH_POLICY)
+extern const char * const *arch_get_ima_policy(void);
+#else
 static inline const char * const *arch_get_ima_policy(void)
 {
return NULL;
 }
+#endif
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 13b446328dda..97609a76aa14 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -157,6 +157,14 @@ config IMA_APPRAISE
  <http://linux-ima.sourceforge.net>
  If unsure, say N.
 
+config IMA_ARCH_POLICY
+bool "Enable loading an IMA architecture specific policy"
+depends on KEXEC_VERIFY_SIG || IMA_APPRAISE && 
INTEGRITY_ASYMMETRIC_KEYS
+default n
+help
+  This option enables loading an IMA architecture specific policy
+  based on run time secure boot flags.
+
 config IMA_APPRAISE_BUILD_POLICY
bool "IMA build time configured policy rules"
depends on IMA_APPRAISE && INTEGRITY_ASYMMETRIC_KEYS
-- 
2.13.6



[PATCH v3 5/6] ima: add support for external setting of ima_appraise

2018-09-19 Thread Nayna Jain
The "ima_appraise" mode defaults to enforcing, unless configured to allow
the boot command line "ima_appraise" option. This patch explicitly sets the
"ima_appraise" mode for the arch specific policy setting.

Signed-off-by: Nayna Jain 
---
 security/integrity/ima/ima.h  |  5 +
 security/integrity/ima/ima_appraise.c | 11 +--
 security/integrity/ima/ima_policy.c   |  5 -
 3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 588e4813370c..6e5fa7c42809 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -248,6 +248,7 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data 
*xattr_value,
 int xattr_len);
 int ima_read_xattr(struct dentry *dentry,
   struct evm_ima_xattr_data **xattr_value);
+void set_ima_appraise(char *str);
 
 #else
 static inline int ima_appraise_measurement(enum ima_hooks func,
@@ -290,6 +291,10 @@ static inline int ima_read_xattr(struct dentry *dentry,
return 0;
 }
 
+static inline void set_ima_appraise(char *str)
+{
+}
+
 #endif /* CONFIG_IMA_APPRAISE */
 
 /* LSM based policy rules require audit */
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 8bd7a0733e51..e061613bcb87 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -18,15 +18,22 @@
 
 #include "ima.h"
 
-static int __init default_appraise_setup(char *str)
+void set_ima_appraise(char *str)
 {
-#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
if (strncmp(str, "off", 3) == 0)
ima_appraise = 0;
else if (strncmp(str, "log", 3) == 0)
ima_appraise = IMA_APPRAISE_LOG;
else if (strncmp(str, "fix", 3) == 0)
ima_appraise = IMA_APPRAISE_FIX;
+   else if (strncmp(str, "enforce", 7) == 0)
+   ima_appraise = IMA_APPRAISE_ENFORCE;
+}
+
+static int __init default_appraise_setup(char *str)
+{
+#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
+   set_ima_appraise(str);
 #endif
return 1;
 }
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 23f3aa214016..c574841bcc9a 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -585,9 +585,12 @@ void __init ima_init_policy(void)
arch_entries = ima_init_arch_policy();
if (!arch_entries)
pr_info("No architecture policies found\n");
-   else
+   else {
add_rules(arch_policy_entry, arch_entries,
  IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY);
+   if (temp_ima_appraise)
+   set_ima_appraise("enforce");
+   }
 
/*
 * Insert the builtin "secure_boot" policy rules requiring file
-- 
2.13.6



[PATCH v3 2/6] ima: prevent kexec_load syscall based on runtime secureboot flag

2018-09-19 Thread Nayna Jain
When CONFIG_KEXEC_VERIFY_SIG is enabled, the kexec_file_load syscall
requires the kexec'd kernel image to be signed. Distros are concerned
about totally disabling the kexec_load syscall. As a compromise, the
kexec_load syscall will only be disabled when CONFIG_KEXEC_VERIFY_SIG
is configured and the system is booted with secureboot enabled.

This patch disables the kexec_load syscall only for systems booted with
secureboot enabled.

Signed-off-by: Nayna Jain 
---
 security/integrity/ima/ima_main.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index dce0a8a217bb..bdb6e5563d05 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -505,20 +505,24 @@ int ima_post_read_file(struct file *file, void *buf, 
loff_t size,
  */
 int ima_load_data(enum kernel_load_data_id id)
 {
-   bool sig_enforce;
+   bool ima_enforce, sig_enforce;
 
-   if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE)
-   return 0;
+   ima_enforce =
+   (ima_appraise & IMA_APPRAISE_ENFORCE) == IMA_APPRAISE_ENFORCE;
 
switch (id) {
case LOADING_KEXEC_IMAGE:
-   if (ima_appraise & IMA_APPRAISE_KEXEC) {
+#ifdef CONFIG_KEXEC_VERIFY_SIG
+   if (arch_ima_get_secureboot())
+   return -EACCES;
+#endif
+   if (ima_enforce && (ima_appraise & IMA_APPRAISE_KEXEC)) {
pr_err("impossible to appraise a kernel image without a 
file descriptor; try using kexec_file_load syscall.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
break;
case LOADING_FIRMWARE:
-   if (ima_appraise & IMA_APPRAISE_FIRMWARE) {
+   if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE)) {
pr_err("Prevent firmware sysfs fallback loading.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
@@ -526,7 +530,8 @@ int ima_load_data(enum kernel_load_data_id id)
case LOADING_MODULE:
sig_enforce = is_module_sig_enforced();
 
-   if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) {
+   if (ima_enforce && (!sig_enforce
+   && (ima_appraise & IMA_APPRAISE_MODULES))) {
pr_err("impossible to appraise a module without a file 
descriptor. sig_enforce kernel parameter might help\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
-- 
2.13.6



  1   2   >