KEYS: trusted: Introduce support for NXP CAAM-based trusted keys

Started by Ahmad Fatoum on Jun 22, 2021 · 18 messages from 5 authors · Last reply Jul 21, 2021

Series

5 patches, 13 files

+509 −27

Subsystems (10)

Show 7 more

Maintainers (16)

Show 12 more
STALE1936d SUPERSEDED

Status: Superseded by v10 (posted 2022-05-13). [go to v10]

Revision v2 (9 revisions archived).

Revisions (9)
  1. v1 re-posted go to this post
  2. v2 current [diff against previous]
  3. v4 [diff against previous]
  4. v5 [diff against previous]
  5. v6 [diff against previous]
  6. v7 [diff against previous]
  7. v8 [diff against previous]
  8. v9 [diff against previous]
  9. v10 [diff against previous]

open the first message on its own page

  1. [PATCH v2 1/6] KEYS: trusted: allow use of TEE as backend without TCG_TPM support
    Revisions and related patches
    Revisions (9)
    1. v1 re-posted go to this post
    2. v2 current [diff against previous]
    3. v4 [diff against previous]
    4. v5 [diff against previous]
    5. v6 [diff against previous]
    6. v7 [diff against previous]
    7. v8 [diff against previous]
    8. v9 [diff against previous]
    9. v10 [diff against previous]
  2. [PATCH v2 3/6] KEYS: trusted: allow users to use kernel RNG for key material
    Revisions and related patches
    Revisions (9)
    1. v1 re-posted go to this post
    2. v2 current [diff against previous]
    3. v4 [diff against previous]
    4. v5 [diff against previous]
    5. v6 [diff against previous]
    6. v7 [diff against previous]
    7. v8 [diff against previous]
    8. v9 [diff against previous]
    9. v10 [diff against previous]
  3. [PATCH v2 4/6] KEYS: trusted: allow trust sources to use kernel RNG for key material
    Revisions and related patches
    Revisions (9)
  4. [PATCH v2 5/6] crypto: caam - add in-kernel interface for blob generator
    Revisions and related patches
    Revisions (7)
    1. v2 current
    2. v4 [diff against previous]
    3. v5 [diff against previous]
    4. v7 [diff against previous]
    5. v8 [diff against previous]
    6. v9 [diff against previous]
    7. v10 [diff against previous]
  5. [PATCH v2 6/6] KEYS: trusted: Introduce support for NXP CAAM-based trusted keys
    Revisions and related patches
    Revisions (5)
    1. v2 current
    2. v7 [diff against previous]
    3. v8 [diff against previous]
    4. v9 [diff against previous]
    5. v10 [diff against previous]
Message details and related content
The first three patches are new and are applicable regardless of this
series, but the rest won't apply cleanly without them. I chose to
include them this time, but I can split them up for v3 if that's
preferred.

v1 -> v2:
 - Added new commit to make trusted key Kconfig option independent
   of TPM and added new Kconfig file and symbols for trusted keys
 - Add new commit for importing existing key material (Jan)
 - Allow users to force use of kernel RNG (Jarkko)
 - Enforce maximum keymod size (Horia)
 - Use append_seq_(in|out)_ptr_intlen instead of append_seq_(in|out)_ptr
   (Horia)
 - Make blobifier handle private to CAAM glue code file (Horia)
 - Extend trusted keys documentation for CAAM
 - Rebased on v5.12-rc7 and updated cover letter:

The Cryptographic Acceleration and Assurance Module (CAAM) is an IP core
built into many newer i.MX and QorIQ SoCs by NXP.

Its blob mechanism can AES encrypt/decrypt user data using a unique
never-disclosed device-specific key.

There has been multiple discussions on how to represent this within the kernel:

The Cryptographic Acceleration and Assurance Module (CAAM) is an IP core
built into many newer i.MX and QorIQ SoCs by NXP.

Its blob mechanism can AES encrypt/decrypt user data using a unique
never-disclosed device-specific key. There has been multiple
discussions on how to represent this within the kernel:

 - [RFC] crypto: caam - add red blobifier
   Steffen implemented[1] a PoC sysfs driver to start a discussion on how to
   best integrate the blob mechanism.
   Mimi suggested that it could be used to implement trusted keys.
   Trusted keys back then were a TPM-only feature.

 - security/keys/secure_key: Adds the secure key support based on CAAM.
   Udit added[2] a new "secure" key type with the CAAM as backend. The key

93 more lines

[PATCH v2 1/6] KEYS: trusted: allow use of TEE as backend without TCG_TPM support

Message details and related content
With recent rework, trusted keys are no longer limited to TPM as trust
source. The Kconfig symbol is unchanged however leading to a few issues:

 - TCG_TPM is required, even if only TEE is to be used
 - Enabling TCG_TPM, but excluding it from available trusted sources
   is not possible
 - TEE=m && TRUSTED_KEYS=y will lead to TEE support being silently
   dropped, which is not the best user experience

Remedy these issues by introducing two new Kconfig symbols:
TRUSTED_KEYS_TPM and TRUSTED_KEYS_TEE with the appropriate
dependencies.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
To: James Bottomley <redacted>
To: Jarkko Sakkinen <jarkko@kernel.org>
To: Mimi Zohar <zohar@linux.ibm.com>
To: David Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: "Horia Geantă" <horia.geanta@nxp.com>
Cc: Aymen Sghaier <redacted>
Cc: Udit Agarwal <redacted>
Cc: Jan Luebbe <redacted>
Cc: David Gstir <david@sigma-star.at>
Cc: Richard Weinberger <richard@nod.at>
Cc: Franck LENORMAND <redacted>
Cc: Sumit Garg <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
---
 security/keys/Kconfig                     | 14 ++++++-------
 security/keys/trusted-keys/Kconfig        | 25 ++++++++++++++++++++++++-
 security/keys/trusted-keys/Makefile       |  8 +++++---
 security/keys/trusted-keys/trusted_core.c |  4 ++--

3 more lines

diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index 64b81abd087e..6fdb953b319f 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -70,23 +70,23 @@ config BIG_KEYS
 
 config TRUSTED_KEYS
 	tristate "TRUSTED KEYS"
-	depends on KEYS && TCG_TPM
+	depends on KEYS
 	select CRYPTO
 	select CRYPTO_HMAC
 	select CRYPTO_SHA1
 	select CRYPTO_HASH_INFO
-	select ASN1_ENCODER
-	select OID_REGISTRY
-	select ASN1
 	help
 	  This option provides support for creating, sealing, and unsealing
 	  keys in the kernel. Trusted keys are random number symmetric keys,
-	  generated and RSA-sealed by the TPM. The TPM only unseals the keys,
-	  if the boot PCRs and other criteria match.  Userspace will only ever
-	  see encrypted blobs.
+	  generated and sealed by a trust source selected at kernel boot-time.
+	  Userspace will only ever see encrypted blobs.
 
 	  If you are unsure as to whether this is required, answer N.
 
+if TRUSTED_KEYS
+source "security/keys/trusted-keys/Kconfig"
+endif
+
 config ENCRYPTED_KEYS
 	tristate "ENCRYPTED KEYS"
 	depends on KEYS
diff --git a/security/keys/trusted-keys/Kconfig b/security/keys/trusted-keys/Kconfig
new file mode 100644
index 000000000000..24af4aaceebf
--- /dev/null
+++ b/security/keys/trusted-keys/Kconfig
@@ -0,0 +1,25 @@
+config TRUSTED_KEYS_TPM
+	bool "TPM-based trusted keys"
+	depends on TCG_TPM >= TRUSTED_KEYS
+	default y
+ 	select ASN1_ENCODER
+	select OID_REGISTRY
+	select ASN1
+	help
+	  Enable use of the Trusted Platform Module (TPM) as trusted key
+	  backend. Trusted keys are are random number symmetric keys,
+	  which will be generated and RSA-sealed by the TPM.
+	  The TPM only unseals the keys, if the boot PCRs and other
+	  criteria match.
+
+config TRUSTED_KEYS_TEE
+	bool "TEE-based trusted keys"
+	depends on TEE >= TRUSTED_KEYS
+	default y
+	help
+	  Enable use of the Trusted Execution Environment (TEE) as trusted
+	  key backend.
+
+if !TRUSTED_KEYS_TPM && !TRUSTED_KEYS_TEE
+comment "No trust source selected!"
+endif
diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-keys/Makefile
index feb8b6c3cc79..96fc6c377398 100644
--- a/security/keys/trusted-keys/Makefile
+++ b/security/keys/trusted-keys/Makefile
@@ -5,10 +5,12 @@
 
 obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
 trusted-y += trusted_core.o
-trusted-y += trusted_tpm1.o
+trusted-$(CONFIG_TRUSTED_KEYS_TPM) += trusted_tpm1.o
 
 $(obj)/trusted_tpm2.o: $(obj)/tpm2key.asn1.h
-trusted-y += trusted_tpm2.o
-trusted-y += tpm2key.asn1.o
+trusted-$(CONFIG_TRUSTED_KEYS_TPM) += trusted_tpm2.o
+trusted-$(CONFIG_TRUSTED_KEYS_TPM) += tpm2key.asn1.o
+
+trusted-$(CONFIG_TRUSTED_KEYS_TEE) += trusted_tee.o
 
 trusted-$(CONFIG_TEE) += trusted_tee.o
diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c
index d5c891d8d353..8cab69e5d0da 100644
--- a/security/keys/trusted-keys/trusted_core.c
+++ b/security/keys/trusted-keys/trusted_core.c
@@ -27,10 +27,10 @@ module_param_named(source, trusted_key_source, charp, 0);
 MODULE_PARM_DESC(source, "Select trusted keys source (tpm or tee)");
 
 static const struct trusted_key_source trusted_key_sources[] = {
-#if defined(CONFIG_TCG_TPM)
+#if defined(CONFIG_TRUSTED_KEYS_TPM)
 	{ "tpm", &trusted_key_tpm_ops },
 #endif
-#if defined(CONFIG_TEE)
+#if defined(CONFIG_TRUSTED_KEYS_TEE)
 	{ "tee", &trusted_key_tee_ops },
 #endif
 };
-- 
git-series 0.9.1

[PATCH v2 3/6] KEYS: trusted: allow users to use kernel RNG for key material

Message details and related content
The two existing trusted key sources don't make use of the kernel RNG,
but instead let the hardware doing the sealing/unsealing also
generate the random key material. However, Users may want to place
less trust into the quality of the trust source's random number
generator and instead use the kernel entropy pool, which can be
seeded from multiple entropy sources.

Make this possible by adding a new trusted.kernel_rng parameter,
that will force use of the kernel RNG. In its absence, it's up
to the trust source to decide, which random numbers to use,
maintaining the existing behavior.

Suggested-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
To: James Bottomley <redacted>
To: Jarkko Sakkinen <jarkko@kernel.org>
To: Mimi Zohar <zohar@linux.ibm.com>
To: David Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: "Horia Geantă" <horia.geanta@nxp.com>
Cc: Aymen Sghaier <redacted>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Udit Agarwal <redacted>
Cc: Jan Luebbe <redacted>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: David Gstir <david@sigma-star.at>
Cc: Richard Weinberger <richard@nod.at>
Cc: Franck LENORMAND <redacted>
Cc: Sumit Garg <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
---
 Documentation/admin-guide/kernel-parameters.txt   |  7 ++++++-
 Documentation/security/keys/trusted-encrypted.rst | 20 +++++++++-------

3 more lines

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index cb89dbdedc46..f8bdc898c354 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -5644,6 +5644,13 @@
 			first trust source as a backend which is initialized
 			successfully during iteration.
 
+	trusted.kernel_rng =	[KEYS]
+			Format: <bool>
+			When set to true (1), the kernel random number pool
+			is used to generate key material for trusted keys.
+			The default is to leave the RNG's choice to each
+			individual trust source.
+
 	tsc=		Disable clocksource stability checks for TSC.
 			Format: <string>
 			[x86] reliable: mark tsc clocksource as reliable, this
diff --git a/Documentation/security/keys/trusted-encrypted.rst b/Documentation/security/keys/trusted-encrypted.rst
index cc2e677b3bb6..3fb5562ee937 100644
--- a/Documentation/security/keys/trusted-encrypted.rst
+++ b/Documentation/security/keys/trusted-encrypted.rst
@@ -87,22 +87,26 @@ Key Generation
 Trusted Keys
 ------------
 
-New keys are created from random numbers generated in the trust source. They
-are encrypted/decrypted using a child key in the storage key hierarchy.
-Encryption and decryption of the child key must be protected by a strong
-access control policy within the trust source.
+New keys are created from random numbers. They are encrypted/decrypted using
+a child key in the storage key hierarchy. Encryption and decryption of the
+child key must be protected by a strong access control policy within the
+trust source. The random number generator in use differs according to the
+selected trust source:
 
-  *  TPM (hardware device) based RNG
+  *  TPM: hardware device based RNG
 
-     Strength of random numbers may vary from one device manufacturer to
-     another.
+     Keys are generated within the TPM. Strength of random numbers may vary
+     from one device manufacturer to another.
 
-  *  TEE (OP-TEE based on Arm TrustZone) based RNG
+  *  TEE: OP-TEE based on Arm TrustZone based RNG
 
      RNG is customizable as per platform needs. It can either be direct output
      from platform specific hardware RNG or a software based Fortuna CSPRNG
      which can be seeded via multiple entropy sources.
 
+Optionally, users may specify ``trusted.kernel_rng=1`` on the kernel
+command-line to override the used RNG with the kernel's random number pool.
+
 Encrypted Keys
 --------------
 
diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c
index 2223e11c8bb5..2eeb7117e86b 100644
--- a/security/keys/trusted-keys/trusted_core.c
+++ b/security/keys/trusted-keys/trusted_core.c
@@ -16,12 +16,17 @@
 #include <linux/key-type.h>
 #include <linux/module.h>
 #include <linux/parser.h>
+#include <linux/random.h>
 #include <linux/rcupdate.h>
 #include <linux/slab.h>
 #include <linux/static_call.h>
 #include <linux/string.h>
 #include <linux/uaccess.h>
 
+static bool trusted_kernel_rng;
+module_param_named(kernel_rng, trusted_kernel_rng, bool, 0);
+MODULE_PARM_DESC(kernel_rng, "Generate key material from kernel RNG");
+
 static char *trusted_key_source;
 module_param_named(source, trusted_key_source, charp, 0);
 MODULE_PARM_DESC(source, "Select trusted keys source (tpm or tee)");
@@ -329,8 +334,14 @@ struct key_type key_type_trusted = {
 };
 EXPORT_SYMBOL_GPL(key_type_trusted);
 
+static int kernel_get_random(unsigned char *key, size_t key_len)
+{
+	return get_random_bytes_wait(key, key_len) ?: key_len;
+}
+
 static int __init init_trusted(void)
 {
+	int (*get_random)(unsigned char *key, size_t key_len);
 	int i, ret = 0;
 
 	for (i = 0; i < ARRAY_SIZE(trusted_key_sources); i++) {
@@ -339,6 +350,10 @@ static int __init init_trusted(void)
 			    strlen(trusted_key_sources[i].name)))
 			continue;
 
+		get_random = trusted_key_sources[i].ops->get_random;
+		if (trusted_kernel_rng)
+			get_random = kernel_get_random;
+
 		static_call_update(trusted_key_init,
 				   trusted_key_sources[i].ops->init);
 		static_call_update(trusted_key_seal,
@@ -346,7 +361,7 @@ static int __init init_trusted(void)
 		static_call_update(trusted_key_unseal,
 				   trusted_key_sources[i].ops->unseal);
 		static_call_update(trusted_key_get_random,
-				   trusted_key_sources[i].ops->get_random);
+				   get_random);
 		static_call_update(trusted_key_exit,
 				   trusted_key_sources[i].ops->exit);
 		migratable = trusted_key_sources[i].ops->migratable;
-- 
git-series 0.9.1

[PATCH v2 4/6] KEYS: trusted: allow trust sources to use kernel RNG for key material

Message details and related content
The two existing trusted key sources don't make use of the kernel RNG,
but instead let the hardware that does the sealing/unsealing also
generate the random key material. While a previous change offers users
the choice to use the kernel RNG instead for both, new trust sources
may want to unconditionally use the kernel RNG for generating key
material, like it's done elsewhere in the kernel.

This is especially prudent for hardware that has proven-in-production
HWRNG drivers implemented, as otherwise code would have to be duplicated
only to arrive at a possibly worse result.

Make this possible by turning struct trusted_key_ops::get_random
into an optional member. If a driver leaves it NULL, kernel RNG
will be used instead.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
To: James Bottomley <redacted>
To: Jarkko Sakkinen <jarkko@kernel.org>
To: Mimi Zohar <zohar@linux.ibm.com>
To: David Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: "Horia Geantă" <horia.geanta@nxp.com>
Cc: Aymen Sghaier <redacted>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Udit Agarwal <redacted>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: Jan Luebbe <redacted>
Cc: David Gstir <david@sigma-star.at>
Cc: Richard Weinberger <richard@nod.at>
Cc: Franck LENORMAND <redacted>
Cc: Sumit Garg <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
---

4 more lines

diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
index d89fa2579ac0..4eb64548a74f 100644
--- a/include/keys/trusted-type.h
+++ b/include/keys/trusted-type.h
@@ -64,7 +64,7 @@ struct trusted_key_ops {
 	/* Unseal a key. */
 	int (*unseal)(struct trusted_key_payload *p, char *datablob);
 
-	/* Get a randomized key. */
+	/* Optional: Get a randomized key. */
 	int (*get_random)(unsigned char *key, size_t key_len);
 
 	/* Exit key interface. */
diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c
index 2eeb7117e86b..8d829e6866ca 100644
--- a/security/keys/trusted-keys/trusted_core.c
+++ b/security/keys/trusted-keys/trusted_core.c
@@ -351,7 +351,7 @@ static int __init init_trusted(void)
 			continue;
 
 		get_random = trusted_key_sources[i].ops->get_random;
-		if (trusted_kernel_rng)
+		if (trusted_kernel_rng || !get_random)
 			get_random = kernel_get_random;
 
 		static_call_update(trusted_key_init,
-- 
git-series 0.9.1

[PATCH v2 5/6] crypto: caam - add in-kernel interface for blob generator

Message details and related content
The CAAM can be used to protect user-defined data across system reboot:

  - When the system is fused and boots into secure state, the master
    key is a unique never-disclosed device-specific key
  - random key is encrypted by key derived from master key
  - data is encrypted using the random key
  - encrypted data and its encrypted random key are stored alongside
  - This blob can now be safely stored in non-volatile memory

On next power-on:
  - blob is loaded into CAAM
  - CAAM writes decrypted data either into memory or key register

Add functions to realize encrypting and decrypting into memory alongside
the CAAM driver.

They will be used in a later commit as a source for the trusted key
seal/unseal mechanism.

Signed-off-by: Steffen Trumtrar <redacted>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
To: "Horia Geantă" <horia.geanta@nxp.com>
To: Aymen Sghaier <redacted>
To: Herbert Xu <herbert@gondor.apana.org.au>
To: "David S. Miller" <davem@davemloft.net>
Cc: James Bottomley <redacted>
Cc: Jarkko Sakkinen <jarkko@kernel.org>
Cc: Mimi Zohar <zohar@linux.ibm.com>
Cc: David Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Udit Agarwal <redacted>
Cc: Jan Luebbe <redacted>
Cc: David Gstir <david@sigma-star.at>
Cc: Richard Weinberger <richard@nod.at>
Cc: Franck LENORMAND <redacted>
Cc: Sumit Garg <redacted>
Cc: <redacted>

13 more lines

diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 84ea7cba5ee5..ea9f8b1ae981 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -151,6 +151,9 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API
 	  Selecting this will register the SEC4 hardware rng to
 	  the hw_random API for supplying the kernel entropy pool.
 
+config CRYPTO_DEV_FSL_CAAM_BLOB_GEN
+	bool
+
 endif # CRYPTO_DEV_FSL_CAAM_JR
 
 endif # CRYPTO_DEV_FSL_CAAM
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 3570286eb9ce..25f7ae5a4642 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -21,6 +21,7 @@ caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
 caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o
+caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_BLOB_GEN) += blob_gen.o
 
 caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += qi.o
 ifneq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI),)
diff --git a/drivers/crypto/caam/blob_gen.c b/drivers/crypto/caam/blob_gen.c
new file mode 100644
index 000000000000..513d3f90e438
--- /dev/null
+++ b/drivers/crypto/caam/blob_gen.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2015 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de>
+ * Copyright (C) 2021 Pengutronix, Ahmad Fatoum <kernel@pengutronix.de>
+ */
+
+#include <linux/device.h>
+#include <soc/fsl/caam-blob.h>
+
+#include "compat.h"
+#include "desc_constr.h"
+#include "desc.h"
+#include "error.h"
+#include "intern.h"
+#include "jr.h"
+#include "regs.h"
+
+struct caam_blob_priv {
+	struct device jrdev;
+};
+
+struct caam_blob_job_result {
+	int err;
+	struct completion completion;
+};
+
+static void caam_blob_job_done(struct device *dev, u32 *desc, u32 err, void *context)
+{
+	struct caam_blob_job_result *res = context;
+	int ecode = 0;
+
+	dev_dbg(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+
+	if (err)
+		ecode = caam_jr_strstatus(dev, err);
+
+	res->err = ecode;
+
+	/*
+	 * Upon completion, desc points to a buffer containing a CAAM job
+	 * descriptor which encapsulates data into an externally-storable
+	 * blob.
+	 */
+	complete(&res->completion);
+}
+
+static u32 *caam_blob_alloc_desc(size_t keymod_len)
+{
+	size_t len;
+
+	/* header + (key mod immediate) + 2x pointers + op */
+	len = 4 + (4 + ALIGN(keymod_len, 4)) + 2*(4 + 4 + CAAM_PTR_SZ_MAX) + 4;
+
+	if (len > CAAM_DESC_BYTES_MAX)
+		return NULL;
+
+	return kzalloc(len, GFP_KERNEL | GFP_DMA);
+}
+
+int caam_encap_blob(struct caam_blob_priv *priv, const char *keymod,
+		    void *input, void *output, size_t length)
+{
+	u32 *desc;
+	struct device *jrdev = &priv->jrdev;
+	dma_addr_t dma_in, dma_out;
+	struct caam_blob_job_result testres;
+	size_t keymod_len = strlen(keymod);
+	int ret;
+
+	if (length <= CAAM_BLOB_OVERHEAD || keymod_len > CAAM_BLOB_KEYMOD_LENGTH)
+		return -EINVAL;
+
+	desc = caam_blob_alloc_desc(keymod_len);
+	if (!desc) {
+		dev_err(jrdev, "unable to allocate desc\n");
+		return -ENOMEM;
+	}
+
+	dma_in = dma_map_single(jrdev, input, length - CAAM_BLOB_OVERHEAD, DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, dma_in)) {
+		dev_err(jrdev, "unable to map input DMA buffer\n");
+		ret = -ENOMEM;
+		goto out_free;
+	}
+
+	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);
+	append_key_as_imm(desc, keymod, keymod_len, keymod_len,
+			  CLASS_2 | KEY_DEST_CLASS_REG);
+	append_seq_in_ptr_intlen(desc, dma_in, length - CAAM_BLOB_OVERHEAD, 0);
+	append_seq_out_ptr_intlen(desc, dma_out, length, 0);
+	append_operation(desc, OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB);
+
+	print_hex_dump_debug("data@"__stringify(__LINE__)": ",
+			     DUMP_PREFIX_ADDRESS, 16, 1, input,
+			     length - CAAM_BLOB_OVERHEAD, false);
+	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
+			     DUMP_PREFIX_ADDRESS, 16, 1, desc,
+			     desc_bytes(desc), false);
+
+	testres.err = 0;
+	init_completion(&testres.completion);
+
+	ret = caam_jr_enqueue(jrdev, desc, caam_blob_job_done, &testres);
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&testres.completion);
+		ret = testres.err;
+		print_hex_dump_debug("output@"__stringify(__LINE__)": ",
+				     DUMP_PREFIX_ADDRESS, 16, 1, output,
+				     length, false);
+	}
+
+	dma_unmap_single(jrdev, dma_out, length, DMA_FROM_DEVICE);
+out_unmap_in:
+	dma_unmap_single(jrdev, dma_in, length - CAAM_BLOB_OVERHEAD, DMA_TO_DEVICE);
+out_free:
+	kfree(desc);
+
+	return ret;
+}
+EXPORT_SYMBOL(caam_encap_blob);
+
+int caam_decap_blob(struct caam_blob_priv *priv, const char *keymod,
+		    void *input, void *output, size_t length)
+{
+	u32 *desc;
+	struct device *jrdev = &priv->jrdev;
+	dma_addr_t dma_in, dma_out;
+	struct caam_blob_job_result testres;
+	size_t keymod_len = strlen(keymod);
+	int ret;
+
+	if (length <= CAAM_BLOB_OVERHEAD || keymod_len > CAAM_BLOB_KEYMOD_LENGTH)
+		return -EINVAL;
+
+	desc = caam_blob_alloc_desc(keymod_len);
+	if (!desc) {
+		dev_err(jrdev, "unable to allocate desc\n");
+		return -ENOMEM;
+	}
+
+	dma_in = dma_map_single(jrdev, input, length, DMA_TO_DEVICE);
+	if (dma_mapping_error(jrdev, dma_in)) {
+		dev_err(jrdev, "unable to map input DMA buffer\n");
+		ret = -ENOMEM;
+		goto out_free;
+	}
+
+	dma_out = dma_map_single(jrdev, output, length - CAAM_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);
+	append_key_as_imm(desc, keymod, keymod_len, keymod_len,
+			  CLASS_2 | KEY_DEST_CLASS_REG);
+	append_seq_in_ptr(desc, dma_in, length, 0);
+	append_seq_out_ptr(desc, dma_out, length - CAAM_BLOB_OVERHEAD, 0);
+	append_operation(desc, OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB);
+
+	print_hex_dump_debug("data@"__stringify(__LINE__)": ",
+			     DUMP_PREFIX_ADDRESS, 16, 1, input,
+			     length, false);
+	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
+			     DUMP_PREFIX_ADDRESS, 16, 1, desc,
+			     desc_bytes(desc), false);
+
+	testres.err = 0;
+	init_completion(&testres.completion);
+
+	ret = caam_jr_enqueue(jrdev, desc, caam_blob_job_done, &testres);
+	if (ret == -EINPROGRESS) {
+		wait_for_completion(&testres.completion);
+		ret = testres.err;
+		print_hex_dump_debug("output@"__stringify(__LINE__)": ",
+				     DUMP_PREFIX_ADDRESS, 16, 1, output,
+				     length - CAAM_BLOB_OVERHEAD, false);
+	}
+
+	dma_unmap_single(jrdev, dma_out, length - CAAM_BLOB_OVERHEAD, DMA_FROM_DEVICE);
+out_unmap_in:
+	dma_unmap_single(jrdev, dma_in, length, DMA_TO_DEVICE);
+out_free:
+	kfree(desc);
+
+	return ret;
+}
+EXPORT_SYMBOL(caam_decap_blob);
+
+struct caam_blob_priv *caam_blob_gen_init(void)
+{
+	struct device *jrdev;
+
+	jrdev = caam_jr_alloc();
+	if (IS_ERR(jrdev))
+		return ERR_CAST(jrdev);
+
+	return container_of(jrdev, struct caam_blob_priv, jrdev);
+}
+EXPORT_SYMBOL(caam_blob_gen_init);
+
+void caam_blob_gen_exit(struct caam_blob_priv *priv)
+{
+	caam_jr_free(&priv->jrdev);
+}
+EXPORT_SYMBOL(caam_blob_gen_exit);
diff --git a/include/soc/fsl/caam-blob.h b/include/soc/fsl/caam-blob.h
new file mode 100644
index 000000000000..aebbc9335f64
--- /dev/null
+++ b/include/soc/fsl/caam-blob.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 Pengutronix, Ahmad Fatoum <kernel@pengutronix.de>
+ */
+
+#ifndef __CAAM_BLOB_GEN
+#define __CAAM_BLOB_GEN
+
+#include <linux/types.h>
+
+#define CAAM_BLOB_KEYMOD_LENGTH		16
+#define CAAM_BLOB_OVERHEAD		(32 + 16)
+#define CAAM_BLOB_MAX_LEN		4096
+
+struct caam_blob_priv;
+
+/** caam_blob_gen_init - initialize blob generation
+ *
+ * returns either pointer to new caam_blob_priv instance
+ * or error pointer
+ */
+struct caam_blob_priv *caam_blob_gen_init(void);
+
+/** caam_blob_gen_init - free blob generation resources
+ *
+ * @priv: instance returned by caam_blob_gen_init
+ */
+void caam_blob_gen_exit(struct caam_blob_priv *priv);
+
+/** caam_encap_blob - encapsulate blob
+ *
+ * @priv:   instance returned by caam_blob_gen_init
+ * @keymod: string to use as key modifier for blob encapsulation
+ *	    can't be longer than CAAM_BLOB_KEYMOD_LENGTH
+ * @input:  buffer which CAAM will DMA from
+ * @output: buffer which CAAM will DMA to
+ * @length: buffer length including blob overhead
+ *          CAAM_BLOB_OVERHEAD < length <= CAAM_BLOB_MAX_LEN
+ */
+int caam_encap_blob(struct caam_blob_priv *priv, const char *keymod,
+		    void *input, void *output, size_t length);
+
+/** caam_decap_blob - decapsulate blob
+ *
+ * @priv:   instance returned by caam_blob_gen_init
+ * @keymod: string to use as key modifier for blob decapsulation
+ *	    can't be longer than CAAM_BLOB_KEYMOD_LENGTH
+ * @input:  buffer which CAAM will DMA from
+ * @output: buffer which CAAM will DMA to
+ * @length: buffer length including blob overhead
+ *          CAAM_BLOB_OVERHEAD < length <= CAAM_BLOB_MAX_LEN
+ */
+int caam_decap_blob(struct caam_blob_priv *priv, const char *keymod,
+		    void *input, void *output, size_t length);
+
+#endif
-- 
git-series 0.9.1

[PATCH v2 6/6] KEYS: trusted: Introduce support for NXP CAAM-based trusted keys

Message details and related content
The Cryptographic Acceleration and Assurance Module (CAAM) is an IP core
built into many newer i.MX and QorIQ SoCs by NXP.

The CAAM does crypto acceleration, hardware number generation and
has a blob mechanism for encapsulation/decapsulation of sensitive material.

This blob mechanism depends on a device specific random 256-bit One Time
Programmable Master Key that is fused in each SoC at manufacturing
time. This key is unreadable and can only be used by the CAAM for AES
encryption/decryption of user data.

This makes it a suitable backend (source) for kernel trusted keys.

Previous commits generalized trusted keys to support multiple backends
and added an API to access the CAAM blob mechanism. Based on these,
provide the necessary glue to use the CAAM for trusted keys.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
To: Jonathan Corbet <corbet@lwn.net>
To: David Howells <dhowells@redhat.com>
To: Jarkko Sakkinen <jarkko@kernel.org>
To: James Bottomley <redacted>
To: Mimi Zohar <zohar@linux.ibm.com>
Cc: James Morris <jmorris@namei.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: "Horia Geantă" <horia.geanta@nxp.com>
Cc: Aymen Sghaier <redacted>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Udit Agarwal <redacted>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: Jan Luebbe <redacted>
Cc: David Gstir <david@sigma-star.at>
Cc: Richard Weinberger <richard@nod.at>
Cc: Franck LENORMAND <redacted>
Cc: Sumit Garg <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>

15 more lines

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index f8bdc898c354..4a95369c2bc7 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -5639,6 +5639,7 @@
 			sources:
 			- "tpm"
 			- "tee"
+			- "caam"
 			If not specified then it defaults to iterating through
 			the trust source list starting with TPM and assigns the
 			first trust source as a backend which is initialized
diff --git a/Documentation/security/keys/trusted-encrypted.rst b/Documentation/security/keys/trusted-encrypted.rst
index 3fb5562ee937..3461746b1fbd 100644
--- a/Documentation/security/keys/trusted-encrypted.rst
+++ b/Documentation/security/keys/trusted-encrypted.rst
@@ -35,6 +35,13 @@ safe.
          Rooted to Hardware Unique Key (HUK) which is generally burnt in on-chip
          fuses and is accessible to TEE only.
 
+     (3) CAAM (Cryptographic Acceleration and Assurance Module: IP on NXP SoCs)
+
+         When High Assurance Boot (HAB) is enabled and the CAAM is in secure
+         mode, trust is rooted to the OTPMK, a never-disclosed 256-bit key
+         randomly generated and fused into each SoC at manufacturing time.
+         Otherwise, a common fixed test key is used instead.
+
   *  Execution isolation
 
      (1) TPM
@@ -46,6 +53,10 @@ safe.
          Customizable set of operations running in isolated execution
          environment verified via Secure/Trusted boot process.
 
+     (3) CAAM
+
+         Fixed set of operations running in isolated execution environment.
+
   * Optional binding to platform integrity state
 
      (1) TPM
@@ -63,6 +74,11 @@ safe.
          Relies on Secure/Trusted boot process for platform integrity. It can
          be extended with TEE based measured boot process.
 
+     (3) CAAM
+
+         Relies on the High Assurance Boot (HAB) mechanism of NXP SoCs
+         for platform integrity.
+
   *  Interfaces and APIs
 
      (1) TPM
@@ -74,10 +90,13 @@ safe.
          TEEs have well-documented, standardized client interface and APIs. For
          more details refer to ``Documentation/staging/tee.rst``.
 
+     (3) CAAM
+
+         Interface is specific to silicon vendor.
 
   *  Threat model
 
-     The strength and appropriateness of a particular TPM or TEE for a given
+     The strength and appropriateness of a particular trust source for a given
      purpose must be assessed when using them to protect security-relevant data.
 
 
@@ -104,8 +123,14 @@ selected trust source:
      from platform specific hardware RNG or a software based Fortuna CSPRNG
      which can be seeded via multiple entropy sources.
 
+  *  CAAM: Kernel RNG
+
+     The normal kernel random number generator is used. To seed it from the
+     CAAM HWRNG, enable CRYPTO_DEV_FSL_CAAM_RNG_API and ensure the device
+     can be probed.
+
 Optionally, users may specify ``trusted.kernel_rng=1`` on the kernel
-command-line to override the used RNG with the kernel's random number pool.
+command-line to force use of the kernel's random number pool.
 
 Encrypted Keys
 --------------
@@ -192,6 +217,19 @@ Usage::
 specific to TEE device implementation.  The key length for new keys is always
 in bytes. Trusted Keys can be 32 - 128 bytes (256 - 1024 bits).
 
+Trusted Keys usage: CAAM
+------------------------
+
+Usage::
+
+    keyctl add trusted name "new keylen" ring
+    keyctl add trusted name "load hex_blob" ring
+    keyctl print keyid
+
+"keyctl print" returns an ASCII hex copy of the sealed key, which is in format
+specific to CAAM device implementation.  The key length for new keys is always
+in bytes. Trusted Keys can be 32 - 128 bytes (256 - 1024 bits).
+
 Trusted Keys: import plain-text key for development
 ---------------------------------------------------
 
diff --git a/include/keys/trusted_caam.h b/include/keys/trusted_caam.h
new file mode 100644
index 000000000000..2fba0996b0b0
--- /dev/null
+++ b/include/keys/trusted_caam.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2021 Pengutronix, Ahmad Fatoum <kernel@pengutronix.de>
+ */
+
+#ifndef __CAAM_TRUSTED_KEY_H
+#define __CAAM_TRUSTED_KEY_H
+
+extern struct trusted_key_ops caam_trusted_key_ops;
+
+#endif
diff --git a/security/keys/trusted-keys/Kconfig b/security/keys/trusted-keys/Kconfig
index 8bd69b252bf9..641bed8923ec 100644
--- a/security/keys/trusted-keys/Kconfig
+++ b/security/keys/trusted-keys/Kconfig
@@ -20,7 +20,16 @@ config TRUSTED_KEYS_TEE
 	  Enable use of the Trusted Execution Environment (TEE) as trusted
 	  key backend.
 
-if !TRUSTED_KEYS_TPM && !TRUSTED_KEYS_TEE
+config TRUSTED_KEYS_CAAM
+	bool "CAAM-based trusted keys"
+	depends on CRYPTO_DEV_FSL_CAAM_JR >= TRUSTED_KEYS
+	select CRYPTO_DEV_FSL_CAAM_BLOB_GEN
+	default y
+	help
+	  Enable use of NXP's Cryptographic Accelerator and Assurance Module
+	  (CAAM) as trusted key backend.
+
+if !TRUSTED_KEYS_TPM && !TRUSTED_KEYS_TEE && !TRUSTED_KEYS_CAAM
 comment "No trust source selected!"
 endif
 
diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-keys/Makefile
index 96fc6c377398..5788bc07a2ab 100644
--- a/security/keys/trusted-keys/Makefile
+++ b/security/keys/trusted-keys/Makefile
@@ -14,3 +14,5 @@ trusted-$(CONFIG_TRUSTED_KEYS_TPM) += tpm2key.asn1.o
 trusted-$(CONFIG_TRUSTED_KEYS_TEE) += trusted_tee.o
 
 trusted-$(CONFIG_TEE) += trusted_tee.o
+
+trusted-$(CONFIG_TRUSTED_KEYS_CAAM) += trusted_caam.o
diff --git a/security/keys/trusted-keys/trusted_caam.c b/security/keys/trusted-keys/trusted_caam.c
new file mode 100644
index 000000000000..01adfd18adda
--- /dev/null
+++ b/security/keys/trusted-keys/trusted_caam.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 Pengutronix, Ahmad Fatoum <kernel@pengutronix.de>
+ */
+
+#include <keys/trusted_caam.h>
+#include <keys/trusted-type.h>
+#include <linux/build_bug.h>
+#include <linux/key-type.h>
+#include <soc/fsl/caam-blob.h>
+
+static struct caam_blob_priv *blobifier;
+
+#define KEYMOD "kernel:trusted"
+
+static_assert(MAX_KEY_SIZE + CAAM_BLOB_OVERHEAD <= CAAM_BLOB_MAX_LEN);
+static_assert(MAX_BLOB_SIZE <= CAAM_BLOB_MAX_LEN);
+
+static int trusted_caam_seal(struct trusted_key_payload *p, char *datablob)
+{
+	int length = p->key_len + CAAM_BLOB_OVERHEAD;
+	int ret;
+
+	ret = caam_encap_blob(blobifier, KEYMOD, p->key, p->blob, length);
+	if (ret)
+		return ret;
+
+	p->blob_len = length;
+	return 0;
+}
+
+static int trusted_caam_unseal(struct trusted_key_payload *p, char *datablob)
+{
+	int length = p->blob_len;
+	int ret;
+
+	ret = caam_decap_blob(blobifier, KEYMOD, p->blob, p->key, length);
+	if (ret)
+		return ret;
+
+	p->key_len = length - CAAM_BLOB_OVERHEAD;
+	return 0;
+}
+
+static int trusted_caam_init(void)
+{
+	int ret;
+
+	blobifier = caam_blob_gen_init();
+	if (IS_ERR(blobifier)) {
+		pr_err("Job Ring Device allocation for transform failed\n");
+		return PTR_ERR(blobifier);
+	}
+
+	ret = register_key_type(&key_type_trusted);
+	if (ret)
+		caam_blob_gen_exit(blobifier);
+
+	return ret;
+}
+
+static void trusted_caam_exit(void)
+{
+	unregister_key_type(&key_type_trusted);
+	caam_blob_gen_exit(blobifier);
+}
+
+struct trusted_key_ops caam_trusted_key_ops = {
+	.migratable = 0, /* non-migratable */
+	.init = trusted_caam_init,
+	.seal = trusted_caam_seal,
+	.unseal = trusted_caam_unseal,
+	.exit = trusted_caam_exit,
+};
diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c
index 8d829e6866ca..21997a5debde 100644
--- a/security/keys/trusted-keys/trusted_core.c
+++ b/security/keys/trusted-keys/trusted_core.c
@@ -9,6 +9,7 @@
 #include <keys/user-type.h>
 #include <keys/trusted-type.h>
 #include <keys/trusted_tee.h>
+#include <keys/trusted_caam.h>
 #include <keys/trusted_tpm.h>
 #include <linux/capability.h>
 #include <linux/err.h>
@@ -29,7 +30,7 @@ MODULE_PARM_DESC(kernel_rng, "Generate key material from kernel RNG");
 
 static char *trusted_key_source;
 module_param_named(source, trusted_key_source, charp, 0);
-MODULE_PARM_DESC(source, "Select trusted keys source (tpm or tee)");
+MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee or caam)");
 
 static const struct trusted_key_source trusted_key_sources[] = {
 #if defined(CONFIG_TRUSTED_KEYS_TPM)
@@ -38,6 +39,9 @@ static const struct trusted_key_source trusted_key_sources[] = {
 #if defined(CONFIG_TRUSTED_KEYS_TEE)
 	{ "tee", &trusted_key_tee_ops },
 #endif
+#if defined(CONFIG_TRUSTED_KEYS_CAAM)
+	{ "caam", &caam_trusted_key_ops },
+#endif
 };
 
 DEFINE_STATIC_CALL_NULL(trusted_key_init, *trusted_key_sources[0].ops->init);
-- 
git-series 0.9.1

Re: [PATCH v2 6/6] KEYS: trusted: Introduce support for NXP CAAM-based trusted keys

Message details and related content
Ahmad,

----- Ursprüngliche Mail -----
Von: "Ahmad Fatoum" [off-list ref]
+static struct caam_blob_priv *blobifier;
+
+#define KEYMOD "kernel:trusted"
I'm still think that hard coding the key modifier is not wise.
As I said[0], there are folks out there that want to provide their own modifier,
so it is not only about being binary compatible with other CAAM blob patches in the wild.

I'll happily implement that feature after your patches got merged but IMHO we should first agree on an interface.
How about allowing another optional parameter to Opt_new and Opt_load and having a key modifier
per struct trusted_key_payload instance?

Thanks,
//richard

[0]
https://patchwork.kernel.org/project/linux-crypto/patch/319e558e1bd19b80ad6447c167a2c3942bdafea2.1615914058.git-series.a.fatoum@pengutronix.de/#24085397

Re: [PATCH v2 6/6] KEYS: trusted: Introduce support for NXP CAAM-based trusted keys

Message details and related content
Hello Richard,

On 01.07.21 22:42, Richard Weinberger wrote:
Ahmad,

----- Ursprüngliche Mail -----
quoted
Von: "Ahmad Fatoum" [off-list ref]
+static struct caam_blob_priv *blobifier;
+
+#define KEYMOD "kernel:trusted"
I'm still think that hard coding the key modifier is not wise.
As I said[0], there are folks out there that want to provide their own modifier,
so it is not only about being binary compatible with other CAAM blob patches in the wild.
I don't think the characterization as a salt is accurate. AFAIU it's more
of a namespace, so blobs being loaded are "type-checked" against the modifier.
I'll happily implement that feature after your patches got merged but IMHO we should first agree on an interface.
How about allowing another optional parameter to Opt_new and Opt_load
Sound good to me. pcrlock for TPM trusted keys has the same interface.

I'd prefer the new option to accept strings, not hex though.

and having a key modifier per struct trusted_key_payload instance?
Ye, possibly a void *backend_data, which other trust sources could leverage
as well. But that should be separate discussion.


Cheers,
Ahmad
Thanks,
//richard

[0]
https://patchwork.kernel.org/project/linux-crypto/patch/319e558e1bd19b80ad6447c167a2c3942bdafea2.1615914058.git-series.a.fatoum@pengutronix.de/#24085397
-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

Re: [PATCH v2 5/6] crypto: caam - add in-kernel interface for blob generator

Message details and related content
Hello Horia,
Hello Aymen,

On 22.06.21 14:37, Ahmad Fatoum wrote:
The CAAM can be used to protect user-defined data across system reboot:

  - When the system is fused and boots into secure state, the master
    key is a unique never-disclosed device-specific key
  - random key is encrypted by key derived from master key
  - data is encrypted using the random key
  - encrypted data and its encrypted random key are stored alongside
  - This blob can now be safely stored in non-volatile memory

On next power-on:
  - blob is loaded into CAAM
  - CAAM writes decrypted data either into memory or key register

Add functions to realize encrypting and decrypting into memory alongside
the CAAM driver.

They will be used in a later commit as a source for the trusted key
seal/unseal mechanism.
Are you ok with this patch and security/keys/trusted-keys/trusted_caam.c
introduced in the follow-up commit?

Cheers,
Ahmad
quoted hunk
Signed-off-by: Steffen Trumtrar <redacted>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
To: "Horia Geantă" <horia.geanta@nxp.com>
To: Aymen Sghaier <redacted>
To: Herbert Xu <herbert@gondor.apana.org.au>
To: "David S. Miller" <davem@davemloft.net>
Cc: James Bottomley <redacted>
Cc: Jarkko Sakkinen <jarkko@kernel.org>
Cc: Mimi Zohar <zohar@linux.ibm.com>
Cc: David Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Udit Agarwal <redacted>
Cc: Jan Luebbe <redacted>
Cc: David Gstir <david@sigma-star.at>
Cc: Richard Weinberger <richard@nod.at>
Cc: Franck LENORMAND <redacted>
Cc: Sumit Garg <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
---
 drivers/crypto/caam/Kconfig    |   3 +-
 drivers/crypto/caam/Makefile   |   1 +-
 drivers/crypto/caam/blob_gen.c | 230 ++++++++++++++++++++++++++++++++++-
 include/soc/fsl/caam-blob.h    |  56 ++++++++-
 4 files changed, 290 insertions(+)
 create mode 100644 drivers/crypto/caam/blob_gen.c
 create mode 100644 include/soc/fsl/caam-blob.h
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 84ea7cba5ee5..ea9f8b1ae981 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -151,6 +151,9 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API

320 more quoted lines

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

Re: [PATCH v2 6/6] KEYS: trusted: Introduce support for NXP CAAM-based trusted keys

Message details and related content
Ahmad,

----- Ursprüngliche Mail -----
Von: "Ahmad Fatoum" [off-list ref]
quoted
I'm still think that hard coding the key modifier is not wise.
As I said[0], there are folks out there that want to provide their own modifier,
so it is not only about being binary compatible with other CAAM blob patches in
the wild.
I don't think the characterization as a salt is accurate. AFAIU it's more
of a namespace, so blobs being loaded are "type-checked" against the modifier.
Well, the CAAM programmer's reference manual states that the blob key is a 128 bit modifier
and has two purposes:
1. It can be used as tag to provide separation between blobs to detect accidental replacement of blobs.
2. But it can also be treated as secret to provide additional protection. Because the blob encryption
key derivation includes the key modifier.

While you have case 1 in mind, I care about case 2. :-)
 
quoted
I'll happily implement that feature after your patches got merged but IMHO we
should first agree on an interface.
How about allowing another optional parameter to Opt_new and Opt_load
Sound good to me. pcrlock for TPM trusted keys has the same interface.

I'd prefer the new option to accept strings, not hex though.
Both is possible. If the string starts with "0x" it needs to be decoded to a
128 bit key. Otherwise it has to be a up to 16 byte string.

Thanks,
//richard

Re: [PATCH v2 6/6] KEYS: trusted: Introduce support for NXP CAAM-based trusted keys

Message details and related content
On 02.07.21 12:53, Richard Weinberger wrote:
Ahmad,

----- Ursprüngliche Mail -----
quoted
Von: "Ahmad Fatoum" [off-list ref]
quoted
I'm still think that hard coding the key modifier is not wise.
As I said[0], there are folks out there that want to provide their own modifier,
so it is not only about being binary compatible with other CAAM blob patches in
the wild.
I don't think the characterization as a salt is accurate. AFAIU it's more
of a namespace, so blobs being loaded are "type-checked" against the modifier.
Well, the CAAM programmer's reference manual states that the blob key is a 128 bit modifier
and has two purposes:
1. It can be used as tag to provide separation between blobs to detect accidental replacement of blobs.
2. But it can also be treated as secret to provide additional protection. Because the blob encryption
key derivation includes the key modifier.

While you have case 1 in mind, I care about case 2. :-)
Ah, using the key modifier as a passphrase didn't occur to me.
quoted
quoted
I'll happily implement that feature after your patches got merged but IMHO we
should first agree on an interface.
How about allowing another optional parameter to Opt_new and Opt_load
Sound good to me. pcrlock for TPM trusted keys has the same interface.

I'd prefer the new option to accept strings, not hex though.
Both is possible. If the string starts with "0x" it needs to be decoded to a
128 bit key. Otherwise it has to be a up to 16 byte string.
Fine by me. Looking forward to your patches. :-)


Cheers,
Ahmad
Thanks,
//richard
-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
Message details and related content
Dear Trusted Keys and CAAM maintainers/reviewers,

On 22.06.21 14:37, Ahmad Fatoum wrote:
The first three patches are new and are applicable regardless of this
series, but the rest won't apply cleanly without them. I chose to
include them this time, but I can split them up for v3 if that's
preferred.

v1 -> v2:
 - Added new commit to make trusted key Kconfig option independent
   of TPM and added new Kconfig file and symbols for trusted keys
 - Add new commit for importing existing key material (Jan)
 - Allow users to force use of kernel RNG (Jarkko)
 - Enforce maximum keymod size (Horia)
 - Use append_seq_(in|out)_ptr_intlen instead of append_seq_(in|out)_ptr
   (Horia)
 - Make blobifier handle private to CAAM glue code file (Horia)
 - Extend trusted keys documentation for CAAM
 - Rebased on v5.12-rc7 and updated cover letter:

The Cryptographic Acceleration and Assurance Module (CAAM) is an IP core
built into many newer i.MX and QorIQ SoCs by NXP.

Its blob mechanism can AES encrypt/decrypt user data using a unique
never-disclosed device-specific key.

There has been multiple discussions on how to represent this within the kernel:

The Cryptographic Acceleration and Assurance Module (CAAM) is an IP core
built into many newer i.MX and QorIQ SoCs by NXP.

Its blob mechanism can AES encrypt/decrypt user data using a unique
never-disclosed device-specific key. There has been multiple
discussions on how to represent this within the kernel:

 - [RFC] crypto: caam - add red blobifier
   Steffen implemented[1] a PoC sysfs driver to start a discussion on how to
   best integrate the blob mechanism.
   Mimi suggested that it could be used to implement trusted keys.
   Trusted keys back then were a TPM-only feature.

 - security/keys/secure_key: Adds the secure key support based on CAAM.
   Udit added[2] a new "secure" key type with the CAAM as backend. The key

27 more quoted lines

Gentle Ping.
Cheers,
Ahmad

 [1]: https://lore.kernel.org/linux-crypto/1447082306-19946-2-git-send-email-s.trumtrar@pengutronix.de/
 [2]: https://lore.kernel.org/linux-integrity/20180723111432.26830-1-udit.agarwal@nxp.com/
 [3]: https://lore.kernel.org/lkml/1551456599-10603-2-git-send-email-franck.lenormand@nxp.com/
 [4]: https://lore.kernel.org/lkml/1604419306-26105-1-git-send-email-sumit.garg@linaro.org/
 [5]: https://lore.kernel.org/linux-integrity/20210122084321.24012-2-a.fatoum@pengutronix.de/

---
To: Jarkko Sakkinen <jarkko@kernel.org>
To: "Horia Geantă" <horia.geanta@nxp.com>
To: Mimi Zohar <zohar@linux.ibm.com>
To: Aymen Sghaier <redacted>
To: Herbert Xu <herbert@gondor.apana.org.au>
To: "David S. Miller" <davem@davemloft.net>
To: James Bottomley <redacted>
Cc: David Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Steffen Trumtrar <redacted>
Cc: Udit Agarwal <redacted>
Cc: Jan Luebbe <redacted>
Cc: David Gstir <david@sigma-star.at>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: Richard Weinberger <richard@nod.at>
Cc: Franck LENORMAND <redacted>
Cc: Sumit Garg <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>

Ahmad Fatoum (6):
  KEYS: trusted: allow use of TEE as backend without TCG_TPM support
  KEYS: trusted: Allow import from existing key material for development
  KEYS: trusted: allow users to use kernel RNG for key material
  KEYS: trusted: allow trust sources to use kernel RNG for key material
  crypto: caam - add in-kernel interface for blob generator

24 more quoted lines


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

Re: [PATCH v2 1/6] KEYS: trusted: allow use of TEE as backend without TCG_TPM support

Message details and related content
Hi Ahmad,

On Tue, 22 Jun 2021 at 18:08, Ahmad Fatoum [off-list ref] wrote:
With recent rework, trusted keys are no longer limited to TPM as trust
source. The Kconfig symbol is unchanged however leading to a few issues:

 - TCG_TPM is required, even if only TEE is to be used
 - Enabling TCG_TPM, but excluding it from available trusted sources
   is not possible
 - TEE=m && TRUSTED_KEYS=y will lead to TEE support being silently
   dropped, which is not the best user experience

Remedy these issues by introducing two new Kconfig symbols:
TRUSTED_KEYS_TPM and TRUSTED_KEYS_TEE with the appropriate
dependencies.
This should include a fixes tag to the rework commit.
quoted hunk
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
To: James Bottomley <redacted>
To: Jarkko Sakkinen <jarkko@kernel.org>
To: Mimi Zohar <zohar@linux.ibm.com>
To: David Howells <dhowells@redhat.com>
Cc: James Morris <jmorris@namei.org>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: "Horia Geantă" <horia.geanta@nxp.com>
Cc: Aymen Sghaier <redacted>
Cc: Udit Agarwal <redacted>
Cc: Jan Luebbe <redacted>
Cc: David Gstir <david@sigma-star.at>
Cc: Richard Weinberger <richard@nod.at>
Cc: Franck LENORMAND <redacted>
Cc: Sumit Garg <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
Cc: <redacted>
---
 security/keys/Kconfig                     | 14 ++++++-------
 security/keys/trusted-keys/Kconfig        | 25 ++++++++++++++++++++++++-
 security/keys/trusted-keys/Makefile       |  8 +++++---
 security/keys/trusted-keys/trusted_core.c |  4 ++--
 4 files changed, 39 insertions(+), 12 deletions(-)
 create mode 100644 security/keys/trusted-keys/Kconfig
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index 64b81abd087e..6fdb953b319f 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -70,23 +70,23 @@ config BIG_KEYS

 config TRUSTED_KEYS
        tristate "TRUSTED KEYS"
-       depends on KEYS && TCG_TPM
+       depends on KEYS
        select CRYPTO
        select CRYPTO_HMAC
        select CRYPTO_SHA1
        select CRYPTO_HASH_INFO
Should move these as well to TRUSTED_KEYS_TPM as the core code doesn't
mandate their need.
quoted hunk
-       select ASN1_ENCODER
-       select OID_REGISTRY
-       select ASN1
        help
          This option provides support for creating, sealing, and unsealing
          keys in the kernel. Trusted keys are random number symmetric keys,
-         generated and RSA-sealed by the TPM. The TPM only unseals the keys,
-         if the boot PCRs and other criteria match.  Userspace will only ever
-         see encrypted blobs.
+         generated and sealed by a trust source selected at kernel boot-time.
+         Userspace will only ever see encrypted blobs.

          If you are unsure as to whether this is required, answer N.

+if TRUSTED_KEYS
+source "security/keys/trusted-keys/Kconfig"
+endif
+
 config ENCRYPTED_KEYS
        tristate "ENCRYPTED KEYS"
        depends on KEYS
diff --git a/security/keys/trusted-keys/Kconfig b/security/keys/trusted-keys/Kconfig
new file mode 100644
index 000000000000..24af4aaceebf
--- /dev/null
+++ b/security/keys/trusted-keys/Kconfig
@@ -0,0 +1,25 @@
+config TRUSTED_KEYS_TPM
+       bool "TPM-based trusted keys"
+       depends on TCG_TPM >= TRUSTED_KEYS
+       default y
+       select ASN1_ENCODER
+       select OID_REGISTRY
+       select ASN1
+       help
+         Enable use of the Trusted Platform Module (TPM) as trusted key
+         backend. Trusted keys are are random number symmetric keys,
+         which will be generated and RSA-sealed by the TPM.
+         The TPM only unseals the keys, if the boot PCRs and other
+         criteria match.

32 more quoted lines

This should be dropped.

-Sumit
quoted hunk
diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c
index d5c891d8d353..8cab69e5d0da 100644
--- a/security/keys/trusted-keys/trusted_core.c
+++ b/security/keys/trusted-keys/trusted_core.c
@@ -27,10 +27,10 @@ module_param_named(source, trusted_key_source, charp, 0);
 MODULE_PARM_DESC(source, "Select trusted keys source (tpm or tee)");

 static const struct trusted_key_source trusted_key_sources[] = {
-#if defined(CONFIG_TCG_TPM)
+#if defined(CONFIG_TRUSTED_KEYS_TPM)
        { "tpm", &trusted_key_tpm_ops },
 #endif
-#if defined(CONFIG_TEE)
+#if defined(CONFIG_TRUSTED_KEYS_TEE)
        { "tee", &trusted_key_tee_ops },
 #endif
 };
--
git-series 0.9.1

Re: [PATCH v2 1/6] KEYS: trusted: allow use of TEE as backend without TCG_TPM support

Message details and related content
Hello Sumit,

On 19.07.21 10:04, Sumit Garg wrote:
Hi Ahmad,

On Tue, 22 Jun 2021 at 18:08, Ahmad Fatoum [off-list ref] wrote:
quoted
With recent rework, trusted keys are no longer limited to TPM as trust
source. The Kconfig symbol is unchanged however leading to a few issues:

 - TCG_TPM is required, even if only TEE is to be used
 - Enabling TCG_TPM, but excluding it from available trusted sources
   is not possible
 - TEE=m && TRUSTED_KEYS=y will lead to TEE support being silently
   dropped, which is not the best user experience

Remedy these issues by introducing two new Kconfig symbols:
TRUSTED_KEYS_TPM and TRUSTED_KEYS_TEE with the appropriate
dependencies.
This should include a fixes tag to the rework commit.
Yes. I wasn't aware of the regression that Andreas (CC'd) recently
reported. Knowing, it now indeed warrants a backport. Will add in v2.
quoted
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index 64b81abd087e..6fdb953b319f 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -70,23 +70,23 @@ config BIG_KEYS

 config TRUSTED_KEYS
        tristate "TRUSTED KEYS"
-       depends on KEYS && TCG_TPM
+       depends on KEYS
quoted
        select CRYPTO
        select CRYPTO_HMAC
        select CRYPTO_SHA1
        select CRYPTO_HASH_INFO
Should move these as well to TRUSTED_KEYS_TPM as the core code doesn't
mandate their need.
Ok, will test and change appropriately.
quoted
-       select ASN1_ENCODER
-       select OID_REGISTRY
-       select ASN1
quoted
 $(obj)/trusted_tpm2.o: $(obj)/tpm2key.asn1.h
-trusted-y += trusted_tpm2.o
-trusted-y += tpm2key.asn1.o
+trusted-$(CONFIG_TRUSTED_KEYS_TPM) += trusted_tpm2.o
+trusted-$(CONFIG_TRUSTED_KEYS_TPM) += tpm2key.asn1.o
+
+trusted-$(CONFIG_TRUSTED_KEYS_TEE) += trusted_tee.o

 trusted-$(CONFIG_TEE) += trusted_tee.o
This should be dropped.
Right..

Thanks for the review. I'll isolate this patch for v2.

Cheers,
Ahmad


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

Re: [PATCH v2 6/6] KEYS: trusted: Introduce support for NXP CAAM-based trusted keys

Message details and related content
On Fri, Jul 2, 2021 at 2:37 PM Ahmad Fatoum [off-list ref] wrote:
quoted
Both is possible. If the string starts with "0x" it needs to be decoded to a
128 bit key. Otherwise it has to be a up to 16 byte string.
Fine by me. Looking forward to your patches. :-)
I'm not sure how to proceed.  Should I base my changes on this series
or do you plan to send an updated
version soon?
Maybe it makes also sense to base my DCP patch set on yours.

Trusted Keys maintainers, what do you prefer?

-- 
Thanks,
//richard

Re: [PATCH v2 6/6] KEYS: trusted: Introduce support for NXP CAAM-based trusted keys

Message details and related content
HI -

On Tue, 2021-07-20 at 21:19 +0200, Richard Weinberger wrote:
On Fri, Jul 2, 2021 at 2:37 PM Ahmad Fatoum [off-list ref] wrote:
quoted
quoted
Both is possible. If the string starts with "0x" it needs to be decoded to a
128 bit key. Otherwise it has to be a up to 16 byte string.
Fine by me. Looking forward to your patches. :-)
I'm not sure how to proceed.  Should I base my changes on this series
or do you plan to send an updated
version soon?
Maybe it makes also sense to base my DCP patch set on yours.

Trusted Keys maintainers, what do you prefer?
Jarkko sent an email saying he is on vacation for 2 weeks.   James was
on vacation as well.   If there is something that needs immediate
attention, please let me know.

thanks,

Mimi

Re: [PATCH v2 6/6] KEYS: trusted: Introduce support for NXP CAAM-based trusted keys

Message details and related content
On Tue, Jul 20, 2021 at 10:24 PM Mimi Zohar [off-list ref] wrote:
quoted
I'm not sure how to proceed.  Should I base my changes on this series
or do you plan to send an updated
version soon?
Maybe it makes also sense to base my DCP patch set on yours.

Trusted Keys maintainers, what do you prefer?
Jarkko sent an email saying he is on vacation for 2 weeks.   James was
on vacation as well.   If there is something that needs immediate
attention, please let me know.
Oh, let them enjoy their well deserved vacation.
There no need to hurry. :-)

-- 
Thanks,
//richard

Re: [PATCH v2 6/6] KEYS: trusted: Introduce support for NXP CAAM-based trusted keys

Message details and related content
Hi,

On 20.07.21 21:19, Richard Weinberger wrote:
On Fri, Jul 2, 2021 at 2:37 PM Ahmad Fatoum [off-list ref] wrote:
quoted
quoted
Both is possible. If the string starts with "0x" it needs to be decoded to a
128 bit key. Otherwise it has to be a up to 16 byte string.
Fine by me. Looking forward to your patches. :-)
I'm not sure how to proceed.  Should I base my changes on this series
or do you plan to send an updated
version soon?
Maybe it makes also sense to base my DCP patch set on yours.

Trusted Keys maintainers, what do you prefer?
I sent out v3 despite the name (of course forgot that git-send-email -vX is silently
dropped when sending patch files directly..):

https://lore.kernel.org/linux-integrity/cover.9fc9298fd9d63553491871d043a18affc2dbc8a8.1626885907.git-series.a.fatoum@pengutronix.de/T/#t

I'd advise you base your changes on the first two patches there as well as the Kconfig fix/enhancement
I sent out separately:
https://lore.kernel.org/linux-integrity/20210721160258.7024-1-a.fatoum@pengutronix.de/T/#u

Those are relevant for you as well and I assume they should be good to be merged even if the
CAAM series turns out to need some more love.

Cheers,
Ahmad


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help