[RFC,3/6] verification: Introduce verify_umd_signature() and verify_umd_message_sig()

Message ID 20230425173557.724688-4-roberto.sassu@huaweicloud.com
State New
Headers
Series KEYS: Introduce user mode key and signature parsers |

Commit Message

Roberto Sassu April 25, 2023, 5:35 p.m. UTC
  From: Roberto Sassu <roberto.sassu@huawei.com>

Introduce verify_umd_signature() and verify_umd_message_sig(), to verify
UMD-parsed signatures from detached data. It aims to be used by kernel
subsystems wishing to verify the authenticity of system data, with
system-defined keyrings as trust anchor.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 certs/system_keyring.c       | 125 +++++++++++++++++++++++++++++++++++
 include/linux/verification.h |  48 ++++++++++++++
 2 files changed, 173 insertions(+)
  

Comments

Jarkko Sakkinen April 26, 2023, 12:28 a.m. UTC | #1
On Tue Apr 25, 2023 at 8:35 PM EEST, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
>
> Introduce verify_umd_signature() and verify_umd_message_sig(), to verify
> UMD-parsed signatures from detached data. It aims to be used by kernel
> subsystems wishing to verify the authenticity of system data, with
> system-defined keyrings as trust anchor.

UMD is not generic knowledge. It is a term coined up in this patch set
so please open code it to each patch.

One discussion points should be what these handlers should be called.
Right now the patch set is misleads the reader to think as this was
some kind of "official" term and set to stone.

BR, Jarkko
  
Roberto Sassu April 26, 2023, 11:42 a.m. UTC | #2
On Wed, 2023-04-26 at 03:28 +0300, Jarkko Sakkinen wrote:
> On Tue Apr 25, 2023 at 8:35 PM EEST, Roberto Sassu wrote:
> > From: Roberto Sassu <roberto.sassu@huawei.com>
> > 
> > Introduce verify_umd_signature() and verify_umd_message_sig(), to verify
> > UMD-parsed signatures from detached data. It aims to be used by kernel
> > subsystems wishing to verify the authenticity of system data, with
> > system-defined keyrings as trust anchor.
> 
> UMD is not generic knowledge. It is a term coined up in this patch set
> so please open code it to each patch.

Yes, Linus also commented on this:

https://lwn.net/ml/linux-kernel/CAHk-=wihqhksXHkcjuTrYmC-vajeRcNh3s6eeoJNxS7wp77dFQ@mail.gmail.com/

I will check if the full name is mentioned at least once. So far, it
seems that using umd for function names should be ok.

> One discussion points should be what these handlers should be called.
> Right now the patch set is misleads the reader to think as this was
> some kind of "official" term and set to stone.

I proposed some naming here (dependency of this patch set):

https://lore.kernel.org/bpf/20230317145240.363908-6-roberto.sassu@huaweicloud.com/

Please let me know if it sounds reasonable to you.

Thanks

Roberto
  
Jarkko Sakkinen April 26, 2023, 6:25 p.m. UTC | #3
On Wed, 2023-04-26 at 13:42 +0200, Roberto Sassu wrote:
> On Wed, 2023-04-26 at 03:28 +0300, Jarkko Sakkinen wrote:
> > On Tue Apr 25, 2023 at 8:35 PM EEST, Roberto Sassu wrote:
> > > From: Roberto Sassu <roberto.sassu@huawei.com>
> > > 
> > > Introduce verify_umd_signature() and verify_umd_message_sig(), to verify
> > > UMD-parsed signatures from detached data. It aims to be used by kernel
> > > subsystems wishing to verify the authenticity of system data, with
> > > system-defined keyrings as trust anchor.
> > 
> > UMD is not generic knowledge. It is a term coined up in this patch set
> > so please open code it to each patch.
> 
> Yes, Linus also commented on this:
> 
> https://lwn.net/ml/linux-kernel/CAHk-=wihqhksXHkcjuTrYmC-vajeRcNh3s6eeoJNxS7wp77dFQ@mail.gmail.com/
> 
> I will check if the full name is mentioned at least once. So far, it
> seems that using umd for function names should be ok.

Also: "UMD-based parser for the asymmetric key type"

It is a tautology:

UMD is based on parser which based on UMD.

I.e. makes no sense.

Everyone hates three letter acronyms so I would consider not
inventing a new one out of the void.

So the corrective step would be to rename Kconfig flags as
USER_ASYMMETRIC_KEY_PARSER and USER_ASYMMETRIC_SIGNATURE_PARSER.

BR, Jarkko
  
Jarkko Sakkinen April 26, 2023, 6:27 p.m. UTC | #4
On Wed, 2023-04-26 at 21:25 +0300, Jarkko Sakkinen wrote:
> On Wed, 2023-04-26 at 13:42 +0200, Roberto Sassu wrote:
> > On Wed, 2023-04-26 at 03:28 +0300, Jarkko Sakkinen wrote:
> > > On Tue Apr 25, 2023 at 8:35 PM EEST, Roberto Sassu wrote:
> > > > From: Roberto Sassu <roberto.sassu@huawei.com>
> > > > 
> > > > Introduce verify_umd_signature() and verify_umd_message_sig(), to verify
> > > > UMD-parsed signatures from detached data. It aims to be used by kernel
> > > > subsystems wishing to verify the authenticity of system data, with
> > > > system-defined keyrings as trust anchor.
> > > 
> > > UMD is not generic knowledge. It is a term coined up in this patch set
> > > so please open code it to each patch.
> > 
> > Yes, Linus also commented on this:
> > 
> > https://lwn.net/ml/linux-kernel/CAHk-=wihqhksXHkcjuTrYmC-vajeRcNh3s6eeoJNxS7wp77dFQ@mail.gmail.com/
> > 
> > I will check if the full name is mentioned at least once. So far, it
> > seems that using umd for function names should be ok.
> 
> Also: "UMD-based parser for the asymmetric key type"
> 
> It is a tautology:
> 
> UMD is based on parser which based on UMD.
> 
> I.e. makes no sense.
> 
> Everyone hates three letter acronyms so I would consider not
> inventing a new one out of the void.
> 
> So the corrective step would be to rename Kconfig flags as
> USER_ASYMMETRIC_KEY_PARSER and USER_ASYMMETRIC_SIGNATURE_PARSER.

(or along the lines)

BR, Jarkko
  

Patch

diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index a7a49b17ceb..d4c0de4dceb 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -16,6 +16,7 @@ 
 #include <keys/asymmetric-type.h>
 #include <keys/system_keyring.h>
 #include <crypto/pkcs7.h>
+#include <crypto/umd_sig.h>
 
 static struct key *builtin_trusted_keys;
 #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
@@ -339,6 +340,130 @@  int verify_pkcs7_signature(const void *data, size_t len,
 }
 EXPORT_SYMBOL_GPL(verify_pkcs7_signature);
 
+#ifdef CONFIG_UMD_SIG_PARSER
+/**
+ * verify_umd_message_sig - Verify a UMD-parsed signature on system data.
+ * @data: The data to be verified (must be provided)
+ * @len: Size of @data
+ * @umd_sig: The UMD-parsed signature
+ * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
+ *					(void *)1UL for all trusted keys)
+ *					(void *)2UL for platform keys)
+ * @usage: The use to which the key is being put
+ * @view_content: Callback to gain access to content
+ * @ctx: Context for callback
+ *
+ * Verify the UMD-parsed signature of the supplied system data, against a
+ * key (if found) in the supplied trusted keyring.
+ *
+ * Return: Zero on successful verification, a negative value otherwise.
+ */
+int verify_umd_message_sig(const void *data, size_t len,
+			   struct umd_sig_message *umd_sig,
+			   struct key *trusted_keys,
+			   enum key_being_used_for usage,
+			   int (*view_content)(void *ctx,
+					       const void *data, size_t len,
+					       size_t asn1hdrlen),
+			   void *ctx)
+{
+	int ret;
+
+	/* The data should be detached - so we need to supply it. */
+	if (data && umd_sig_supply_detached_data(umd_sig, data, len)) {
+		pr_err("Failed to supply data for UMD-parsed signature\n");
+		ret = -EBADMSG;
+		goto error;
+	}
+
+	if (!trusted_keys) {
+		trusted_keys = builtin_trusted_keys;
+	} else if (trusted_keys == VERIFY_USE_SECONDARY_KEYRING) {
+#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
+		trusted_keys = secondary_trusted_keys;
+#else
+		trusted_keys = builtin_trusted_keys;
+#endif
+	} else if (trusted_keys == VERIFY_USE_PLATFORM_KEYRING) {
+#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
+		trusted_keys = platform_trusted_keys;
+#else
+		trusted_keys = NULL;
+#endif
+		if (!trusted_keys) {
+			ret = -ENOKEY;
+			pr_devel("Platform keyring is not available\n");
+			goto error;
+		}
+	}
+
+	ret = umd_sig_verify_message(umd_sig, trusted_keys);
+	if (ret < 0)
+		goto error;
+
+	if (view_content) {
+		size_t sig_data_len;
+
+		ret = umd_sig_get_content_data(umd_sig, &data, &len,
+					       &sig_data_len);
+		if (ret < 0) {
+			if (ret == -ENODATA)
+				pr_devel("UMD-parsed signature does not contain data\n");
+			goto error;
+		}
+
+		ret = view_content(ctx, data, len, sig_data_len);
+		kfree(data);
+	}
+error:
+	pr_devel("<==%s() = %d\n", __func__, ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(verify_umd_message_sig);
+
+/**
+ * verify_umd_signature - Verify a UMD-parsed signature on system data.
+ * @data: The data to be verified (must be provided)
+ * @len: Size of @data
+ * @raw_umd_sig: The raw signature to be parsed with UMD
+ * @raw_umd_sig_len: The size of @raw_umd_sig
+ * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
+ *					(void *)1UL for all trusted keys)
+ *					(void *)2UL for platform keys)
+ * @usage: The use to which the key is being put
+ * @view_content: Callback to gain access to content
+ * @ctx: Context for callback
+ *
+ * Verify the UMD-parsed signature of the supplied system data, against a
+ * key (if found) in the supplied trusted keyring.
+ *
+ * Return: Zero on successful verification, a negative value otherwise.
+ */
+int verify_umd_signature(const void *data, size_t len,
+			 const void *raw_umd_sig, size_t raw_umd_sig_len,
+			 struct key *trusted_keys,
+			 enum key_being_used_for usage,
+			 int (*view_content)(void *ctx,
+					     const void *data, size_t len,
+					     size_t asn1hdrlen),
+			 void *ctx)
+{
+	struct umd_sig_message *umd_sig;
+	int ret;
+
+	umd_sig = umd_sig_parse_message(raw_umd_sig, raw_umd_sig_len);
+	if (IS_ERR(umd_sig))
+		return PTR_ERR(umd_sig);
+
+	ret = verify_umd_message_sig(data, len, umd_sig, trusted_keys, usage,
+				     view_content, ctx);
+
+	umd_sig_free_message(umd_sig);
+	pr_devel("<==%s() = %d\n", __func__, ret);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(verify_umd_signature);
+#endif /* CONFIG_UMD_SIG_PARSER */
 #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
 
 #ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING
diff --git a/include/linux/verification.h b/include/linux/verification.h
index f34e50ebcf6..2e44ea17f23 100644
--- a/include/linux/verification.h
+++ b/include/linux/verification.h
@@ -43,6 +43,7 @@  extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
 
 struct key;
 struct pkcs7_message;
+struct umd_sig_message;
 
 extern int verify_pkcs7_signature(const void *data, size_t len,
 				  const void *raw_pkcs7, size_t pkcs7_len,
@@ -62,6 +63,53 @@  extern int verify_pkcs7_message_sig(const void *data, size_t len,
 							size_t asn1hdrlen),
 				    void *ctx);
 
+#ifdef CONFIG_UMD_SIG_PARSER
+extern int verify_umd_message_sig(const void *data, size_t len,
+				  struct umd_sig_message *umd_sig,
+				  struct key *trusted_keys,
+				  enum key_being_used_for usage,
+				  int (*view_content)(void *ctx,
+						      const void *data,
+						      size_t len,
+						      size_t asn1hdrlen),
+				  void *ctx);
+extern int verify_umd_signature(const void *data, size_t len,
+				const void *raw_pgp, size_t pgp_len,
+				struct key *trusted_keys,
+				enum key_being_used_for usage,
+				int (*view_content)(void *ctx,
+						const void *data, size_t len,
+						size_t asn1hdrlen),
+				void *ctx);
+#else
+static inline int verify_umd_message_sig(const void *data, size_t len,
+					 struct umd_sig_message *umd_sig,
+					 struct key *trusted_keys,
+					 enum key_being_used_for usage,
+					 int (*view_content)(void *ctx,
+							     const void *data,
+							     size_t len,
+							     size_t asn1hdrlen),
+					 void *ctx)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int verify_umd_signature(const void *data, size_t len,
+				       const void *raw_umd_sig,
+				       size_t raw_umd_sig_len,
+				       struct key *trusted_keys,
+				       enum key_being_used_for usage,
+				       int (*view_content)(void *ctx,
+							   const void *data,
+							   size_t len,
+							   size_t asn1hdrlen),
+				       void *ctx)
+{
+	return -EOPNOTSUPP;
+}
+#endif /* CONFIG_UMD_SIG_PARSER */
+
 #ifdef CONFIG_SIGNED_PE_FILE_VERIFICATION
 extern int verify_pefile_signature(const void *pebuf, unsigned pelen,
 				   struct key *trusted_keys,