All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization
@ 2015-11-09 15:18 Steffen Trumtrar
  2015-11-09 15:18 ` [RFC] crypto: caam - add red blobifier Steffen Trumtrar
  2015-11-09 20:29 ` [Linux-ima-user] [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization Mimi Zohar
  0 siblings, 2 replies; 6+ messages in thread
From: Steffen Trumtrar @ 2015-11-09 15:18 UTC (permalink / raw)
  To: linux-crypto
  Cc: linux-ima-devel, linux-ima-user, keyrings, David Howells, kernel,
	Steffen Trumtrar

Hi!

The RFC Patch attached after this cover letter is mostly for illustration
purposes, so please don't waste too much time reviewing the code ;-)

For context I'll try to describe the problem that this patch tries to solve.

I need to be able to boot an EVM signed (and dongled) rootfs. The CAAM on
the i.MX6 has support for an OTP key and can en/decrypt data.
It also has a feature for generating red blobs: basically a chunk of data,
that is encrypted with the OTP key, which can be saved on some medium as a
secret to decrypt the EVM HMAC secret for one specific device.

To open the rootfs, the secret is handed from the bootloader to the kernel
as a base64 encoded string via the cmdline to an initramfs.
In the initramfs the sysfs file "modifier" is set to something starting with
"kernel:evm" and the base64 string is written to the sysfs file "blob".
The CAAM than decodes the red blob and, in case of "kernel:evm", initializes
the EVM or otherwise writes the result to "payload" if the modifier starts
with "user:". Therefore a blob that was generated for EVM never leaves the
kernel on decryption.
Generation of blobs goes like: echoing "modifier" to something and echoing
the payload to "payload". The red blob can than be read from "blob".


So, the sysfs interface is not the best option, I guess. The question is:
What is the right approach for a setup like this?
I need to:
  - be able to encrypt the secret and store it somewhere
  - to load the stored secret and decrypt it later
  - initialize IMA/EVM with the secret

Would something like
  - security/keys/encrypted-keys/encrypted.c
be the correct approach?

Thanks,
Steffen


Steffen Trumtrar (1):
  crypto: caam - add red blobifier

 drivers/crypto/caam/Kconfig    |   9 +
 drivers/crypto/caam/Makefile   |   1 +
 drivers/crypto/caam/blob_gen.c | 528 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 538 insertions(+)
 create mode 100644 drivers/crypto/caam/blob_gen.c

-- 
2.6.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC] crypto: caam - add red blobifier
  2015-11-09 15:18 [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization Steffen Trumtrar
@ 2015-11-09 15:18 ` Steffen Trumtrar
  2015-11-09 20:29 ` [Linux-ima-user] [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization Mimi Zohar
  1 sibling, 0 replies; 6+ messages in thread
From: Steffen Trumtrar @ 2015-11-09 15:18 UTC (permalink / raw)
  To: linux-crypto
  Cc: linux-ima-devel, linux-ima-user, keyrings, David Howells, kernel,
	Steffen Trumtrar

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/crypto/caam/Kconfig    |   9 +
 drivers/crypto/caam/Makefile   |   1 +
 drivers/crypto/caam/blob_gen.c | 528 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 538 insertions(+)
 create mode 100644 drivers/crypto/caam/blob_gen.c

diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index e7555ff4cafd..329fab7ba4f7 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -99,6 +99,15 @@ config CRYPTO_DEV_FSL_CAAM_AHASH_API
 	  To compile this as a module, choose M here: the module
 	  will be called caamhash.
 
+config CRYPTO_DEV_FSL_CAAM_BLOB_GEN
+	tristate "CAAM Blob Generator (EXPERIMENTAL)"
+	depends on CRYPTO_DEV_FSL_CAAM
+	default n
+	help
+	  Selecting this will enable the CAAM red blob generator.
+          This module will take a chunk of data via sysfs and returns
+	  an encrypted red blob. The inverse is also possible.
+
 config CRYPTO_DEV_FSL_CAAM_RNG_API
 	tristate "Register caam device for hwrng API"
 	depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 550758a333e7..359ef3b97fdf 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_BLOB_GEN) += blob_gen.o
 
 caam-objs := ctrl.o
 caam_jr-objs := jr.o key_gen.o error.o
diff --git a/drivers/crypto/caam/blob_gen.c b/drivers/crypto/caam/blob_gen.c
new file mode 100644
index 000000000000..9c2a02c2882a
--- /dev/null
+++ b/drivers/crypto/caam/blob_gen.c
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C) 2015 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/evm.h>
+#include "compat.h"
+#include "intern.h"
+#include "desc.h"
+#include "desc_constr.h"
+#include "error.h"
+#include "jr.h"
+
+enum access_rights {
+	KERNEL,
+	KERNEL_EVM,
+	USERSPACE,
+};
+
+struct blob_priv {
+	struct device *jrdev;
+	struct device dev;
+	u32 *desc;
+	u8 __iomem *red_blob;
+	u8 __iomem *modifier;
+	u8 __iomem *output;
+	bool busy;
+	enum access_rights access;
+	unsigned int payload_size;
+	struct bin_attribute *blob;
+	struct bin_attribute *payload;
+	struct caam_drv_private *ctrlpriv;
+};
+
+struct blob_job_result {
+	int err;
+	struct completion completion;
+};
+
+static struct platform_device *pdev;
+
+static void blob_job_done(struct device *dev, u32 *desc, u32 err, void *context)
+{
+	struct blob_job_result *res = context;
+
+#ifdef DEBUG
+	dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+	if (err)
+		caam_jr_strstatus(dev, err);
+
+	res->err = err;
+
+	complete(&res->completion);
+}
+
+/*
+ * Upon completion, desc points to a buffer containing a CAAM job
+ * descriptor which encapsulates data into an externally-storable
+ * blob.
+ */
+#define INITIAL_DESCSZ		16
+#define BLOB_OVERHEAD		(32 + 16)
+#define KEYMOD_LENGTH		16
+#define RED_BLOB_LENGTH		64
+#define MAX_BLOB_LEN		4096
+
+/*
+ * Generate a blob with the following format:
+ * Format: Normal format (Test format only for testing)
+ * Contents: General data (aka red blob)
+ * Security State: Secure State (Non-Secure for testing)
+ * Memory Types: General memory
+ */
+static int blob_encap_blob(struct blob_priv *priv, u8 *keymod, u8 *input,
+				u8 *output, u16 length)
+{
+	u32 *desc;
+	struct device *jrdev = priv->jrdev;
+	dma_addr_t dma_keymod;
+	dma_addr_t dma_in;
+	dma_addr_t dma_out;
+	struct blob_job_result testres;
+	int ret;
+
+	desc = kmalloc(CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 5, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		dev_err(jrdev, "unable to allocate desc\n");
+		return -ENOMEM;
+	}
+
+	dma_keymod = dma_map_single(jrdev, keymod, KEYMOD_LENGTH, DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, dma_keymod)) {
+		dev_err(jrdev, "unable to map keymod buffer\n");
+		ret = -ENOMEM;
+		goto out_free;
+	}
+
+	dma_in = dma_map_single(jrdev, input, length - BLOB_OVERHEAD,
+					DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, dma_in)) {
+		dev_err(jrdev, "unable to map keymod buffer\n");
+		ret = -ENOMEM;
+		goto out_unmap_key;
+	}
+
+	dma_out = dma_map_single(jrdev, output, length,	DMA_FROM_DEVICE);
+	if (dma_mapping_error(jrdev, dma_out)) {
+		dev_err(jrdev, "unable to map output DMA buffer\n");
+		ret = -ENOMEM;
+		goto out_unmap_in;
+	}
+
+	/*
+	 * A data blob is encrypted using a blob key (BK); a random number.
+	 * The BK is used as an AES-CCM key. The initial block (B0) and the
+	 * initial counter (Ctr0) are generated automatically and stored in
+	 * Class 1 Context DWords 0+1+2+3. The random BK is stored in the	
+	 * Class 1 Key Register. Operation Mode is set to AES-CCM.
+	 */
+
+	init_job_desc(desc, 0);
+	/*
+	 * The key modifier can be used to differentiate specific data.
+	 * Or to prevent replay attacks.
+	 */
+	append_key(desc, dma_keymod, KEYMOD_LENGTH, CLASS_2 | KEY_DEST_CLASS_REG);
+	append_seq_in_ptr(desc, dma_in, length - BLOB_OVERHEAD, 0);
+	append_seq_out_ptr(desc, dma_out, length, 0);
+	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB);
+
+#ifdef DEBUG
+	printk("%s: keymod %s\n", __func__, keymod);
+	print_hex_dump(KERN_ERR, "data@"__stringify(__LINE__)": ",
+			DUMP_PREFIX_ADDRESS, 16, 1, input,
+			length - BLOB_OVERHEAD, false);
+	print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
+			DUMP_PREFIX_ADDRESS, 16, 1, desc,
+			desc_bytes(desc), false);
+#endif
+
+	testres.err = 0;
+	init_completion(&testres.completion);
+
+	ret = caam_jr_enqueue(jrdev, desc, blob_job_done, &testres);
+	if (!ret) {
+		wait_for_completion_interruptible(&testres.completion);
+		ret = testres.err;
+#ifdef DEBUG
+		print_hex_dump(KERN_ERR, "output@"__stringify(__LINE__)": ",
+			       DUMP_PREFIX_ADDRESS, 16, 1, output,
+			       length, false);
+#endif
+	}
+
+	dma_unmap_single(jrdev, dma_out, length,
+					DMA_FROM_DEVICE);
+out_unmap_in:
+	dma_unmap_single(jrdev, dma_keymod, KEYMOD_LENGTH, DMA_TO_DEVICE);
+out_unmap_key:
+	dma_unmap_single(jrdev, dma_in, length - BLOB_OVERHEAD, DMA_TO_DEVICE);
+out_free:
+	kfree(desc);
+
+	return ret;
+}
+
+static int blob_decap_blob(struct blob_priv *priv, u8 *keymod, u8 *input,
+				u8 *output, u16 length)
+{
+	u32 *desc;
+	struct device *jrdev = priv->jrdev;
+	dma_addr_t dma_keymod;
+	dma_addr_t dma_in;
+	dma_addr_t dma_out;
+	struct blob_job_result testres;
+	int ret;
+
+	desc = kzalloc(CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 5, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		dev_err(jrdev, "unable to allocate desc\n");
+		return -ENOMEM;
+	}
+
+	dma_keymod = dma_map_single(jrdev, keymod, KEYMOD_LENGTH, DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, dma_keymod)) {
+		dev_err(jrdev, "unable to map keymod buffer\n");
+		ret = -ENOMEM;
+		goto out_free;
+	}
+
+	dma_in = dma_map_single(jrdev, input, length, DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, dma_in)) {
+		dev_err(jrdev, "unable to map keymod buffer\n");
+		ret = -ENOMEM;
+		goto out_unmap_key;
+	}
+
+	dma_out = dma_map_single(jrdev, output, length - BLOB_OVERHEAD, DMA_FROM_DEVICE);
+	if (dma_mapping_error(jrdev, dma_out)) {
+		dev_err(jrdev, "unable to map output DMA buffer\n");
+		ret = -ENOMEM;
+		goto out_unmap_in;
+	}
+
+	/*
+	 * A data blob is encrypted using a blob key (BK); a random number.
+	 * The BK is used as an AES-CCM key. The initial block (B0) and the
+	 * initial counter (Ctr0) are generated automatically and stored in
+	 * Class 1 Context DWords 0+1+2+3. The random BK is stored in the	
+	 * Class 1 Key Register. Operation Mode is set to AES-CCM.
+	 */
+
+	init_job_desc(desc, 0);
+	/*
+	 * The key modifier can be used to differentiate specific data.
+	 * Or to prevent replay attacks.
+	 */
+	append_key(desc, dma_keymod, KEYMOD_LENGTH, CLASS_2 | KEY_DEST_CLASS_REG);
+	append_seq_in_ptr(desc, dma_in, length, 0);
+	append_seq_out_ptr(desc, dma_out, length - BLOB_OVERHEAD, 0);
+	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "data@"__stringify(__LINE__)": ",
+			DUMP_PREFIX_ADDRESS, 16, 1, input,
+			length, false);
+	print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
+			DUMP_PREFIX_ADDRESS, 16, 1, desc,
+			desc_bytes(desc), false);
+#endif
+
+	testres.err = 0;
+	init_completion(&testres.completion);
+
+	ret = caam_jr_enqueue(jrdev, desc, blob_job_done, &testres);
+	if (!ret) {
+		wait_for_completion_interruptible(&testres.completion);
+		ret = testres.err;
+#ifdef DEBUG
+		print_hex_dump(KERN_ERR, "output@"__stringify(__LINE__)": ",
+			       DUMP_PREFIX_ADDRESS, 16, 1, output,
+			       length - BLOB_OVERHEAD, false);
+#endif
+	}
+
+	dma_unmap_single(jrdev, dma_out, length - BLOB_OVERHEAD, DMA_FROM_DEVICE);
+out_unmap_in:
+	dma_unmap_single(jrdev, dma_keymod, KEYMOD_LENGTH, DMA_TO_DEVICE);
+out_unmap_key:
+	dma_unmap_single(jrdev, dma_in, length, DMA_TO_DEVICE);
+out_free:
+	kfree(desc);
+
+	return ret;
+}
+
+static void blob_gen_init_evm(struct blob_priv *priv)
+{
+	evm_init((const char *)priv->output, priv->payload_size);
+}
+
+static ssize_t
+blob_gen_blob_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,
+		char *buf, loff_t off, size_t size)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct blob_priv *priv = dev_get_drvdata(dev);
+	int length = min((int)size, (int) (priv->payload_size + BLOB_OVERHEAD - off));
+	int ret;
+
+	if (length > 0) {
+		priv->busy = true;
+
+		ret = blob_encap_blob(priv, priv->modifier, priv->output, priv->red_blob, length);
+		if (ret) {
+			priv->busy = false;
+			return -EINVAL;
+		}
+
+		memcpy(buf, priv->red_blob, length);
+
+		priv->busy = false;
+	}
+
+	return length;
+}
+
+static ssize_t
+blob_gen_blob_write(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *attr, char *buf, loff_t off, size_t size)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct blob_priv *priv = dev_get_drvdata(dev);
+	int ret;
+
+	if (size > 0) {
+		priv->busy = true;
+
+		memcpy(priv->red_blob, buf, size);
+
+		memset(priv->output, 0, MAX_BLOB_LEN - BLOB_OVERHEAD);
+
+		ret = blob_decap_blob(priv, priv->modifier, priv->red_blob,
+					priv->output, size);
+		if (ret) {
+			priv->busy = false;
+			return -EINVAL;
+		}
+
+		priv->payload_size = size - BLOB_OVERHEAD;
+
+		if (priv->access == KERNEL_EVM)
+			blob_gen_init_evm(priv);
+
+		priv->busy = false;
+	}
+
+	return size;
+}
+
+static ssize_t
+blob_gen_payload_read(struct file *filp, struct kobject *kobj,
+			struct bin_attribute *attr, char *buf, loff_t off,
+			size_t size)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct blob_priv *priv = dev_get_drvdata(dev);
+	int length = min((int) size, (int) (priv->payload_size - off));
+
+	if (priv->payload_size == 0)
+		return -EINVAL;
+
+	if (priv->access != USERSPACE)
+		return -EPERM;
+
+	memcpy(buf, priv->output + off, length);
+
+	return length;
+}
+
+static ssize_t
+blob_gen_payload_write(struct file *filp, struct kobject *kobj,
+			struct bin_attribute *attr, char *buf, loff_t off,
+			size_t size)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct blob_priv *priv = dev_get_drvdata(dev);
+
+	if (priv->busy)
+		return -EPERM;
+
+	memcpy(priv->output, buf, size);
+
+	priv->payload_size = size;
+
+	return size;
+}
+
+static ssize_t
+blob_gen_show_modifier(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct blob_priv *priv = dev_get_drvdata(dev);
+
+	memcpy(buf, priv->modifier, KEYMOD_LENGTH);
+
+	return KEYMOD_LENGTH;
+}
+
+static ssize_t
+blob_gen_set_modifier(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t n)
+{
+	struct blob_priv *priv = dev_get_drvdata(dev);
+	char *buf_ptr;
+
+	if (n > KEYMOD_LENGTH)
+		return -EINVAL;
+
+	if (priv->busy)
+		return -EPERM;
+
+	buf_ptr = (char *)buf;
+	if (!strncmp(buf_ptr, "kernel:evm", 10))
+		priv->access = KERNEL_EVM;
+	else if (!strncmp(buf_ptr, "kernel:", 7))
+		priv->access = KERNEL;
+	else if (!strncmp(buf_ptr, "user:", 5))
+		priv->access = USERSPACE;
+
+	memset(priv->output, 0, MAX_BLOB_LEN - BLOB_OVERHEAD);
+	memset(priv->red_blob, 0, MAX_BLOB_LEN);
+
+	memcpy(priv->modifier, buf, n);
+
+	return n;
+}
+static DEVICE_ATTR(modifier, S_IRUSR | S_IWUSR,
+		blob_gen_show_modifier, blob_gen_set_modifier);
+
+static struct attribute *blob_attrs[] = {
+	&dev_attr_modifier.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(blob);
+
+static int __init blob_gen_init(void)
+{
+	struct device_node *dev_node;
+	struct device *ctrldev;
+	struct caam_drv_private *ctrlpriv;
+	struct blob_priv *priv;
+	int ret;
+
+	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+	if (!dev_node) {
+		dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+		if (!dev_node)
+			return -ENODEV;
+	}
+
+	pdev = of_find_device_by_node(dev_node);
+	if (!pdev) {
+		of_node_put(dev_node);
+		return -ENODEV;
+	}
+
+	ctrldev = &pdev->dev;
+	ctrlpriv = dev_get_drvdata(ctrldev);
+
+	pdev = platform_device_alloc("blob_gen", -1);
+	if (!pdev)
+		return -ENOMEM;
+	pdev->dev.parent = ctrldev;
+	pdev->dev.groups = blob_groups;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	priv->blob = devm_kzalloc(&pdev->dev, sizeof(struct bin_attribute),
+					GFP_KERNEL);
+	priv->payload = devm_kzalloc(&pdev->dev, sizeof(struct bin_attribute),
+					GFP_KERNEL);
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto pdev_add_failed;
+
+	priv->modifier = devm_kzalloc(&pdev->dev, sizeof(*priv->modifier)*KEYMOD_LENGTH,
+			GFP_KERNEL | GFP_DMA);
+
+	priv->red_blob = devm_kzalloc(&pdev->dev, sizeof(*priv->red_blob)*
+					MAX_BLOB_LEN, GFP_KERNEL | GFP_DMA);
+
+	priv->output = devm_kzalloc(&pdev->dev, sizeof(*priv->output)*
+					MAX_BLOB_LEN - BLOB_OVERHEAD, GFP_KERNEL | GFP_DMA);
+
+	priv->desc = devm_kzalloc(&pdev->dev, sizeof(*priv->desc), GFP_KERNEL | GFP_DMA);
+	if (priv->desc == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(&pdev->dev, priv);
+
+	priv->busy = false;
+
+	priv->jrdev = &ctrlpriv->jrpdev[0]->dev;
+
+	priv->blob->attr.name = "blob";
+	priv->blob->attr.mode = S_IRUSR | S_IWUSR;
+
+	sysfs_bin_attr_init(priv->blob);
+	priv->blob->read = blob_gen_blob_read;
+	priv->blob->write = blob_gen_blob_write;
+
+	ret = sysfs_create_bin_file(&pdev->dev.kobj, priv->blob);
+	if (ret)
+		dev_err(&pdev->dev, "unable to create sysfs file %s\n",
+			priv->blob->attr.name);
+	else
+		dev_info(&pdev->dev, "added sysfs binary attribute\n");
+
+	priv->payload->attr.name = "payload";
+	priv->payload->attr.mode = S_IRUSR | S_IWUSR;
+
+	sysfs_bin_attr_init(priv->payload);
+	priv->payload->read = blob_gen_payload_read;
+	priv->payload->write = blob_gen_payload_write;
+
+	ret = sysfs_create_bin_file(&pdev->dev.kobj, priv->payload);
+	if (ret)
+		dev_err(&pdev->dev, "unable to create sysfs file %s\n",
+			priv->payload->attr.name);
+	else
+		dev_info(&pdev->dev, "added sysfs binary attribute\n");
+
+	return 0;
+
+pdev_add_failed:
+	platform_device_put(pdev);
+
+	return ret;
+}
+
+static void __exit blob_gen_exit(void)
+{
+	struct blob_priv *priv;
+
+	priv = dev_get_drvdata(&pdev->dev);
+	if (!priv)
+		return;
+
+	sysfs_remove_bin_file(&pdev->dev.kobj, priv->payload);
+	sysfs_remove_bin_file(&pdev->dev.kobj, priv->blob);
+
+	platform_device_unregister(pdev);
+}
+
+module_init(blob_gen_init);
+module_exit(blob_gen_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Blob Generator Example");
+MODULE_AUTHOR("Steffen Trumtrar <s.trumtrar@pengutronix.de>");
-- 
2.6.1

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Linux-ima-user] [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization
  2015-11-09 15:18 [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization Steffen Trumtrar
  2015-11-09 15:18 ` [RFC] crypto: caam - add red blobifier Steffen Trumtrar
@ 2015-11-09 20:29 ` Mimi Zohar
  2016-01-27 10:04   ` Steffen Trumtrar
  1 sibling, 1 reply; 6+ messages in thread
From: Mimi Zohar @ 2015-11-09 20:29 UTC (permalink / raw)
  To: Steffen Trumtrar
  Cc: linux-crypto, keyrings, linux-ima-user, David Howells, kernel,
	linux-ima-devel, Dmitry Kasatkin

On Mon, 2015-11-09 at 16:18 +0100, Steffen Trumtrar wrote:
> Hi!
> 
> The RFC Patch attached after this cover letter is mostly for illustration
> purposes, so please don't waste too much time reviewing the code ;-)
> 
> For context I'll try to describe the problem that this patch tries to solve.
> 
> I need to be able to boot an EVM signed (and dongled) rootfs. The CAAM on
> the i.MX6 has support for an OTP key and can en/decrypt data.
> It also has a feature for generating red blobs: basically a chunk of data,
> that is encrypted with the OTP key, which can be saved on some medium as a
> secret to decrypt the EVM HMAC secret for one specific device.
> 
> To open the rootfs, the secret is handed from the bootloader to the kernel
> as a base64 encoded string via the cmdline to an initramfs.
> In the initramfs the sysfs file "modifier" is set to something starting with
> "kernel:evm" and the base64 string is written to the sysfs file "blob".
> The CAAM than decodes the red blob and, in case of "kernel:evm", initializes
> the EVM or otherwise writes the result to "payload" if the modifier starts
> with "user:". Therefore a blob that was generated for EVM never leaves the
> kernel on decryption.
> Generation of blobs goes like: echoing "modifier" to something and echoing
> the payload to "payload". The red blob can than be read from "blob".
> 
> 
> So, the sysfs interface is not the best option, I guess. The question is:
> What is the right approach for a setup like this?
> I need to:
>   - be able to encrypt the secret and store it somewhere
>   - to load the stored secret and decrypt it later
>   - initialize IMA/EVM with the secret
> 
> Would something like
>   - security/keys/encrypted-keys/encrypted.c
> be the correct approach?

Instead of using the CAAM for OTP encrypting/decrypting, can it be used
to load the EVM key directly?  Dmitry's patches, which will be
upstreamed in 4.5
https://git.kernel.org/cgit/linux/kernel/git/zohar/linux-integrity.git/log/?h=for-next-4.5?   adds support for a crypto device to directly load the EVM key.

FYI, the EVM key is an encrypted key, which encrypts/decrypts either a
trusted or user type key.

Mimi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Linux-ima-user] [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization
  2015-11-09 20:29 ` [Linux-ima-user] [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization Mimi Zohar
@ 2016-01-27 10:04   ` Steffen Trumtrar
  2016-01-28 15:41     ` Mimi Zohar
  0 siblings, 1 reply; 6+ messages in thread
From: Steffen Trumtrar @ 2016-01-27 10:04 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: linux-crypto, keyrings, linux-ima-user, David Howells, kernel,
	linux-ima-devel, Dmitry Kasatkin


Hi!

Mimi Zohar writes:

> On Mon, 2015-11-09 at 16:18 +0100, Steffen Trumtrar wrote:
>> Hi!
>> 
>> The RFC Patch attached after this cover letter is mostly for illustration
>> purposes, so please don't waste too much time reviewing the code ;-)
>> 
>> For context I'll try to describe the problem that this patch tries to solve.
>> 
>> I need to be able to boot an EVM signed (and dongled) rootfs. The CAAM on
>> the i.MX6 has support for an OTP key and can en/decrypt data.
>> It also has a feature for generating red blobs: basically a chunk of data,
>> that is encrypted with the OTP key, which can be saved on some medium as a
>> secret to decrypt the EVM HMAC secret for one specific device.
>> 
>> To open the rootfs, the secret is handed from the bootloader to the kernel
>> as a base64 encoded string via the cmdline to an initramfs.
>> In the initramfs the sysfs file "modifier" is set to something starting with
>> "kernel:evm" and the base64 string is written to the sysfs file "blob".
>> The CAAM than decodes the red blob and, in case of "kernel:evm", initializes
>> the EVM or otherwise writes the result to "payload" if the modifier starts
>> with "user:". Therefore a blob that was generated for EVM never leaves the
>> kernel on decryption.
>> Generation of blobs goes like: echoing "modifier" to something and echoing
>> the payload to "payload". The red blob can than be read from "blob".
>> 
>> 
>> So, the sysfs interface is not the best option, I guess. The question is:
>> What is the right approach for a setup like this?
>> I need to:
>>   - be able to encrypt the secret and store it somewhere
>>   - to load the stored secret and decrypt it later
>>   - initialize IMA/EVM with the secret
>> 
>> Would something like
>>   - security/keys/encrypted-keys/encrypted.c
>> be the correct approach?
>
> Instead of using the CAAM for OTP encrypting/decrypting, can it be used
> to load the EVM key directly?  Dmitry's patches, which will be
> upstreamed in 4.5
> https://git.kernel.org/cgit/linux/kernel/git/zohar/linux-integrity.git/log/?h=for-next-4.5?   adds support for a crypto device to directly load the EVM key.
>

The patches look good and I use them for loading the EVM key from the
CAAM driver. But I still need the OTP decryption functionality.

The key data that I hand to evm_set_key must be device specific but I
don't want to use the fused OTP in the CAAM directly.
The OTP is used to protect multiple random keys. Therefore I need to
generate encrypted blobs that I can store on some unsecure memory
(EEPROM, NAND,...) and be able to hand that later back to the CAAM
module, to then get back an IMA/EVM, ecryptfs, $something key.

> FYI, the EVM key is an encrypted key, which encrypts/decrypts either a
> trusted or user type key.
>
So the normal approach would be to have a key in the kernel keyring
and decrypt it with the key loaded with evm_set_key?

Can I somehow use the keyring framework as an abstraction around my
blobbing/deblobbing functionality?
So that the "keyring" calls into the crypto driver to decrypt the data
and uses the crypto driver to encrypt the keys when I want to "dump"
them?


Thanks,
Steffen

-- 
Pengutronix e.K.                           | Steffen Trumtrar            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Linux-ima-user] [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization
  2016-01-27 10:04   ` Steffen Trumtrar
@ 2016-01-28 15:41     ` Mimi Zohar
  2016-01-28 16:27       ` Jan Lübbe
  0 siblings, 1 reply; 6+ messages in thread
From: Mimi Zohar @ 2016-01-28 15:41 UTC (permalink / raw)
  To: Steffen Trumtrar
  Cc: linux-crypto, keyrings, linux-ima-user, David Howells, kernel,
	linux-ima-devel, Dmitry Kasatkin, David Woodhouse

On Wed, 2016-01-27 at 11:04 +0100, Steffen Trumtrar wrote:
> Hi!
> 
> Mimi Zohar writes:
> 
> > On Mon, 2015-11-09 at 16:18 +0100, Steffen Trumtrar wrote:
> >> Hi!
> >> 
> >> The RFC Patch attached after this cover letter is mostly for illustration
> >> purposes, so please don't waste too much time reviewing the code ;-)
> >> 
> >> For context I'll try to describe the problem that this patch tries to solve.
> >> 
> >> I need to be able to boot an EVM signed (and dongled) rootfs. The CAAM on
> >> the i.MX6 has support for an OTP key and can en/decrypt data.
> >> It also has a feature for generating red blobs: basically a chunk of data,
> >> that is encrypted with the OTP key, which can be saved on some medium as a
> >> secret to decrypt the EVM HMAC secret for one specific device.
> >> 
> >> To open the rootfs, the secret is handed from the bootloader to the kernel
> >> as a base64 encoded string via the cmdline to an initramfs.
> >> In the initramfs the sysfs file "modifier" is set to something starting with
> >> "kernel:evm" and the base64 string is written to the sysfs file "blob".
> >> The CAAM than decodes the red blob and, in case of "kernel:evm", initializes
> >> the EVM or otherwise writes the result to "payload" if the modifier starts
> >> with "user:". Therefore a blob that was generated for EVM never leaves the
> >> kernel on decryption.
> >> Generation of blobs goes like: echoing "modifier" to something and echoing
> >> the payload to "payload". The red blob can than be read from "blob".
> >> 
> >> 
> >> So, the sysfs interface is not the best option, I guess. The question is:
> >> What is the right approach for a setup like this?
> >> I need to:
> >>   - be able to encrypt the secret and store it somewhere
> >>   - to load the stored secret and decrypt it later
> >>   - initialize IMA/EVM with the secret
> >> 
> >> Would something like
> >>   - security/keys/encrypted-keys/encrypted.c
> >> be the correct approach?
> >
> > Instead of using the CAAM for OTP encrypting/decrypting, can it be used
> > to load the EVM key directly?  Dmitry's patches, which will be
> > upstreamed in 4.5
> >
> https://git.kernel.org/cgit/linux/kernel/git/zohar/linux-integrity.git/log/?h=for-next-4.5?   adds support for a crypto device to directly load the EVM key.
> >
> 
> The patches look good and I use them for loading the EVM key from the
> CAAM driver. But I still need the OTP decryption functionality.

> The key data that I hand to evm_set_key must be device specific but I
> don't want to use the fused OTP in the CAAM directly.
> The OTP is used to protect multiple random keys. Therefore I need to
> generate encrypted blobs that I can store on some unsecure memory
> (EEPROM, NAND,...) and be able to hand that later back to the CAAM
> module, to then get back an IMA/EVM, ecryptfs, $something key.
> 
> > FYI, the EVM key is an encrypted key, which encrypts/decrypts either a
> > trusted or user type key.
> >
> So the normal approach would be to have a key in the kernel keyring
> and decrypt it with the key loaded with evm_set_key?

Sorry, I should have said the encrypted key is encrypted/decrypted using
the trusted or user type key.

> Can I somehow use the keyring framework as an abstraction around my
> blobbing/deblobbing functionality?
> So that the "keyring" calls into the crypto driver to decrypt the data
> and uses the crypto driver to encrypt the keys when I want to "dump"
> them?

Definitely.   It sounds like you want the equivalent functionality as
the TPM based trusted keys using OTP on the CAAM.

>From Documentation/security/keys-trusted-encrypted.txt:

"Trusted Keys use a TPM both to generate and to seal the keys.  Keys are
sealed
under a 2048 bit RSA key in the TPM, and optionally sealed to specified
PCR
(integrity measurement) values, and only unsealed by the TPM, if PCRs
and blob
integrity verifications match."

Mimi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Linux-ima-user] [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization
  2016-01-28 15:41     ` Mimi Zohar
@ 2016-01-28 16:27       ` Jan Lübbe
  0 siblings, 0 replies; 6+ messages in thread
From: Jan Lübbe @ 2016-01-28 16:27 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: Steffen Trumtrar, keyrings, linux-ima-user, Dmitry Kasatkin,
	David Howells, linux-crypto, kernel, linux-ima-devel,
	David Woodhouse

Hi!

On Do, 2016-01-28 at 10:41 -0500, Mimi Zohar wrote:
> On Wed, 2016-01-27 at 11:04 +0100, Steffen Trumtrar wrote:
> > Can I somehow use the keyring framework as an abstraction around my
> > blobbing/deblobbing functionality?
> > So that the "keyring" calls into the crypto driver to decrypt the data
> > and uses the crypto driver to encrypt the keys when I want to "dump"
> > them?
> 
> Definitely.   It sounds like you want the equivalent functionality as
> the TPM based trusted keys using OTP on the CAAM.
> 
> From Documentation/security/keys-trusted-encrypted.txt:
> 
> "Trusted Keys use a TPM both to generate and to seal the keys.  Keys are
> sealed under a 2048 bit RSA key in the TPM, and optionally sealed to specified
> PCR (integrity measurement) values, and only unsealed by the TPM, if PCRs
> and blob integrity verifications match."

OK. The implementation is in security/keys/trusted.c, right? This talks
directly to the TPM. Also the code in security/keys/encrypted-keys/
explicitly uses the interface in keys/trusted-type.h.

Now I'm not sure how to best allow using the CAAM as an alternative to a
TPM. Would we have different "backends" in the trusted keys
implementation so that for example encrypted keys don't need to know
about the difference?

Otherwise we would need to add another key type ("trusted-caam?"). Then
we'd need to add code to support trusted-caam keys wherever we already
support trusted(-tpm) keys?

Do you have a suggestion on how we should proceed?

Best regards,
Jan Lübbe
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-01-28 16:28 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-09 15:18 [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization Steffen Trumtrar
2015-11-09 15:18 ` [RFC] crypto: caam - add red blobifier Steffen Trumtrar
2015-11-09 20:29 ` [Linux-ima-user] [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization Mimi Zohar
2016-01-27 10:04   ` Steffen Trumtrar
2016-01-28 15:41     ` Mimi Zohar
2016-01-28 16:27       ` Jan Lübbe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.