All of lore.kernel.org
 help / color / mirror / Atom feed
From: Roberto Sassu <roberto.sassu@huaweicloud.com>
To: dhowells@redhat.com, dwmw2@infradead.org,
	herbert@gondor.apana.org.au, davem@davemloft.net,
	jarkko@kernel.org, song@kernel.org, jolsa@kernel.org,
	ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org,
	martin.lau@linux.dev, yhs@fb.com, john.fastabend@gmail.com,
	kpsingh@kernel.org, sdf@google.com, haoluo@google.com,
	rostedt@goodmis.org, mhiramat@kernel.org, mykolal@fb.com,
	shuah@kernel.org
Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org,
	linux-crypto@vger.kernel.org, bpf@vger.kernel.org,
	linux-trace-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, pbrobinson@gmail.com,
	zbyszek@in.waw.pl, zohar@linux.ibm.com,
	linux-integrity@vger.kernel.org, paul@paul-moore.com,
	linux-security-module@vger.kernel.org, wiktor@metacode.biz,
	devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org,
	ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name,
	antony@vennard.ch, konstantin@linuxfoundation.org,
	James.Bottomley@HansenPartnership.com,
	Roberto Sassu <roberto.sassu@huawei.com>
Subject: [RFC][PATCH 03/10] KEYS: asymmetric: Introduce a parser for user asymmetric keys and sigs
Date: Thu,  6 Jul 2023 16:42:16 +0200	[thread overview]
Message-ID: <20230706144225.1046544-4-roberto.sassu@huaweicloud.com> (raw)
In-Reply-To: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com>

From: Roberto Sassu <roberto.sassu@huawei.com>

Introduce the common parser for user asymmetric keys and signatures. The
data format is TLV-based, and consists of a header and the data.

Key and signature blobs can be parsed with the new function uasym_parse().
Each caller of that function should provide a callback function,
responsible to parse their fields, and an opaque data pointer to be used by
the callback function to store the parsed data.

The same data format will be used to store both keys and signatures, albeit
with different fields.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 crypto/asymmetric_keys/Kconfig        |  12 ++
 crypto/asymmetric_keys/Makefile       |   7 +
 crypto/asymmetric_keys/uasym_parser.c | 201 ++++++++++++++++++++++++++
 crypto/asymmetric_keys/uasym_parser.h |  30 ++++
 include/uapi/linux/uasym_parser.h     |  91 ++++++++++++
 5 files changed, 341 insertions(+)
 create mode 100644 crypto/asymmetric_keys/uasym_parser.c
 create mode 100644 crypto/asymmetric_keys/uasym_parser.h
 create mode 100644 include/uapi/linux/uasym_parser.h

diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 1ef3b46d6f6..4f86fe78efd 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -85,4 +85,16 @@ config FIPS_SIGNATURE_SELFTEST
 	depends on ASYMMETRIC_KEY_TYPE
 	depends on PKCS7_MESSAGE_PARSER=X509_CERTIFICATE_PARSER
 
+config UASYM_KEYS_SIGS
+	tristate "User asymmetric keys and signatures"
+	depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+	help
+	  This option enables user asymmetric keys and signatures. They are
+	  keys and signatures converted in user space from their native
+	  format (e.g. PGP), to the TLV format (Type-Length-Value) understood
+	  by the kernel.
+
+	  Key and signature-specific fields are defined in the UAPI interface,
+	  so that user space converters can reference them.
+
 endif # ASYMMETRIC_KEY_TYPE
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index 0d1fa1b692c..ac3955d834f 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -76,3 +76,10 @@ verify_signed_pefile-y := \
 
 $(obj)/mscode_parser.o: $(obj)/mscode.asn1.h $(obj)/mscode.asn1.h
 $(obj)/mscode.asn1.o: $(obj)/mscode.asn1.c $(obj)/mscode.asn1.h
+
+#
+# User asymmetric keys and signatures
+#
+obj-$(CONFIG_UASYM_KEYS_SIGS) += uasym_keys_sigs.o
+uasym_keys_sigs-y := \
+	uasym_parser.o
diff --git a/crypto/asymmetric_keys/uasym_parser.c b/crypto/asymmetric_keys/uasym_parser.c
new file mode 100644
index 00000000000..e207f350c40
--- /dev/null
+++ b/crypto/asymmetric_keys/uasym_parser.c
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Roberto Sassu <roberto.sassu@huawei.com>
+ *
+ * Implement the user asymmetric keys and signature parser.
+ */
+
+#define pr_fmt(fmt) "UASYM PARSER: "fmt
+
+#include "uasym_parser.h"
+
+const char *data_types_str[] = {
+	FOR_EACH_DATA_TYPE(GENERATE_STRING)
+};
+
+const char *fields_str[] = {
+	FOR_EACH_FIELD(GENERATE_STRING)
+};
+
+/**
+ * uasym_parse_hdr - Parse a user asymmetric key or signature header
+ * @data: Data to parse (updated)
+ * @data_len: Length of @data (updated)
+ * @data_type: Data type (updated)
+ * @num_fields: Data fields (updated)
+ * @total_len: Length of key or signature, excluding the header (updated)
+ *
+ * Parse the header of a user asymmetric key or signature, update the data
+ * pointer and length, and provide the data type, number of fields and the
+ * length of that element.
+ *
+ * Return: Zero on success, a negative value on error.
+ */
+int uasym_parse_hdr(const u8 **data, size_t *data_len, u8 *data_type,
+		    u16 *num_fields, u64 *total_len)
+{
+	struct uasym_hdr *hdr;
+
+	if (*data_len < sizeof(*hdr)) {
+		pr_debug("Data blob too short, %lu bytes, expected %lu\n",
+			 *data_len, sizeof(*hdr));
+		return -EBADMSG;
+	}
+
+	hdr = (struct uasym_hdr *)*data;
+
+	*data += sizeof(*hdr);
+	*data_len -= sizeof(*hdr);
+
+	*data_type = hdr->data_type;
+	if (*data_type >= TYPE__LAST) {
+		pr_debug("Invalid data type %u\n", *data_type);
+		return -EBADMSG;
+	}
+
+	if (hdr->_reserved0 != 0) {
+		pr_debug("_reserved0 must be zero\n");
+		return -EBADMSG;
+	}
+
+	*num_fields = be16_to_cpu(hdr->num_fields);
+	if (*num_fields >= FIELD__LAST) {
+		pr_debug("Too many fields %u, max: %u\n", *num_fields,
+			 FIELD__LAST);
+		return -EBADMSG;
+	}
+
+	if (hdr->_reserved1 != 0) {
+		pr_debug("_reserved1 must be zero\n");
+		return -EBADMSG;
+	}
+
+	*total_len = be64_to_cpu(hdr->total_len);
+	if (*total_len > *data_len) {
+		pr_debug("Invalid total length %llu, expected: %lu\n",
+			 *total_len, *data_len);
+		return -EBADMSG;
+	}
+
+	pr_debug("Header: type: %s, num fields: %d, total len: %lld\n",
+		 data_types_str[hdr->data_type], *num_fields, *total_len);
+
+	return 0;
+}
+
+/**
+ * uasym_parse_data - Parse a user asymmetric key or signature data
+ * @callback: Callback function to call to parse the fields
+ * @callback_data: Opaque data to supply to the callback function
+ * @num_fields: Data fields
+ * @data: Data to parse
+ * @data_len: Length of @data
+ *
+ * Parse the data part of a user asymmetric key or signature and call the
+ * supplied callback function for each data field, passing also the opaque
+ * data pointer.
+ *
+ * Return: Zero on success, a negative value on error.
+ */
+int uasym_parse_data(parse_callback callback, void *callback_data,
+		     u16 num_fields, const u8 *data, size_t data_len)
+{
+	const u8 *data_ptr = data;
+	struct uasym_entry *entry;
+	u16 field;
+	u32 len;
+	int ret, i;
+
+	for (i = 0; i < num_fields; i++) {
+		if (data_len < sizeof(*entry))
+			return -EBADMSG;
+
+		entry = (struct uasym_entry *)data_ptr;
+		data_ptr += sizeof(*entry);
+		data_len -= sizeof(*entry);
+
+		field = be16_to_cpu(entry->field);
+		len = be32_to_cpu(entry->length);
+
+		if (data_len < len)
+			return -EBADMSG;
+
+		pr_debug("Data: field: %s, len: %d\n", fields_str[field], len);
+
+		if (!len)
+			continue;
+
+		ret = callback(callback_data, field, data_ptr, len);
+		if (ret < 0) {
+			pr_debug("Parsing of field %s failed, ret: %d\n",
+				 fields_str[field], ret);
+			return -EBADMSG;
+		}
+
+		data_ptr += len;
+		data_len -= len;
+	}
+
+	if (data_len) {
+		pr_debug("Excess data: %ld bytes\n", data_len);
+		return -EBADMSG;
+	}
+
+	return 0;
+}
+
+/**
+ * uasym_parse - Parse a user asymmetric key or signature
+ * @expected_data_type: Desired data type
+ * @callback: Callback function to call to parse the fields
+ * @callback_data: Opaque data to supply to the callback function
+ * @data: Data to parse
+ * @data_len: Length of @data
+ *
+ * Parse a user asymmetric key or signature and call the supplied callback
+ * function for each data field, passing also the opaque data pointer.
+ *
+ * Return: Zero on success, a negative value on error.
+ */
+int uasym_parse(enum data_types expected_data_type, parse_callback callback,
+		void *callback_data, const u8 *data, size_t data_len)
+{
+	u8 data_type;
+	u16 num_fields;
+	u64 total_len;
+	int ret = 0;
+
+	pr_debug("Start parsing data blob, size: %ld, expected data type: %s\n",
+		 data_len, data_types_str[expected_data_type]);
+
+	while (data_len) {
+		ret = uasym_parse_hdr(&data, &data_len, &data_type, &num_fields,
+				      &total_len);
+		if (ret < 0)
+			goto out;
+
+		if (data_type == expected_data_type)
+			break;
+
+		/*
+		 * uasym_parse_hdr() already checked that total_len <= data_len.
+		 */
+		data += total_len;
+		data_len -= total_len;
+	}
+
+	if (!data_len) {
+		pr_debug("Data type %s not found\n",
+			 data_types_str[expected_data_type]);
+		ret = -ENOENT;
+		goto out;
+	}
+
+	ret = uasym_parse_data(callback, callback_data, num_fields, data,
+			       total_len);
+out:
+	pr_debug("End of parsing data blob, ret: %d\n", ret);
+	return ret;
+}
diff --git a/crypto/asymmetric_keys/uasym_parser.h b/crypto/asymmetric_keys/uasym_parser.h
new file mode 100644
index 00000000000..985dda6aad3
--- /dev/null
+++ b/crypto/asymmetric_keys/uasym_parser.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Roberto Sassu <roberto.sassu@huawei.com>
+ *
+ * Header file of user asymmetric keys and signatures.
+ */
+
+#include <keys/asymmetric-subtype.h>
+#include <keys/asymmetric-parser.h>
+
+#include <uapi/linux/uasym_parser.h>
+
+#define kenter(FMT, ...) \
+	pr_debug("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
+#define kleave(FMT, ...) \
+	pr_debug("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
+
+typedef int (*parse_callback)(void *, enum fields, const u8 *, u32);
+
+extern const char *data_types_str[];
+extern const char *fields_str[];
+
+int uasym_parse_hdr(const u8 **data, size_t *data_len, u8 *data_type,
+		    u16 *num_fields, u64 *total_len);
+int uasym_parse_data(parse_callback callback, void *callback_data,
+		     u16 num_fields, const u8 *data, size_t data_len);
+int uasym_parse(enum data_types expected_data_type, parse_callback callback,
+		void *callback_data, const u8 *data, size_t data_len);
diff --git a/include/uapi/linux/uasym_parser.h b/include/uapi/linux/uasym_parser.h
new file mode 100644
index 00000000000..8f0bc235492
--- /dev/null
+++ b/include/uapi/linux/uasym_parser.h
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Roberto Sassu <roberto.sassu@huawei.com>
+ *
+ * Implement the user space interface for user asymmetric keys and signatures.
+ */
+
+#ifndef _UAPI_LINUX_UASYM_PARSER_H
+#define _UAPI_LINUX_UASYM_PARSER_H
+
+#include <linux/types.h>
+#include <linux/pub_key_info.h>
+
+/*
+ * User asymmmetric key and signature format:
+ *
+ * +----------------+-----------------+-----------------+
+ * | data type (u8) | num fields (u16)| total len (u64) |
+ * +--------------+-+----------+------+-----------+-----+
+ * | field1 (u16) | len1 (u32) | value1 (u8 len1) |
+ * +--------------+------------+------------------+
+ * |     ...      |    ...     |        ...       |
+ * +--------------+------------+------------------+
+ * | fieldN (u16) | lenN (u32) | valueN (u8 lenN) |
+ * +--------------+------------+------------------+
+ */
+
+/**
+ * struct uasym_hdr - Header of user asymmetric keys and signatures
+ * @data_type: Type of data to parse
+ * @_reserved0: Reserved for future use
+ * @num_fields: Number of fields provided
+ * @_reserved1: Reserved for future use
+ * @total_len: Total length of the data blob, excluding the header
+ *
+ * This structure represents the header of the user asymmetric keys and
+ * signatures format.
+ */
+struct uasym_hdr {
+	__u8 data_type;
+	__u8 _reserved0;
+	__u16 num_fields;
+	__u32 _reserved1;
+	__u64 total_len;
+} __packed;
+
+/**
+ * struct uasym_entry - Data entry of user asymmetric keys and signatures
+ * @field: Data field identifier
+ * @length: Data length
+ * @data: Data
+ *
+ * This structure represents a TLV entry of the data part of the user
+ * asymmetric keys and signatures format.
+ */
+struct uasym_entry {
+	__u16 field;
+	__u32 length;
+	__u8 data[];
+} __packed;
+
+#define FOR_EACH_DATA_TYPE(DATA_TYPE) \
+	DATA_TYPE(TYPE__LAST)
+
+#define FOR_EACH_FIELD(FIELD) \
+	FIELD(FIELD__LAST)
+
+#define GENERATE_ENUM(ENUM) ENUM,
+#define GENERATE_STRING(STRING) #STRING,
+
+/**
+ * enum data_types - Type of data to parse
+ *
+ * Enumerates the type of data to parse.
+ */
+enum data_types {
+	FOR_EACH_DATA_TYPE(GENERATE_ENUM)
+};
+
+/**
+ * enum fields - Data fields
+ *
+ * Enumerates the data fields. Some belongs to keys, some to signatures.
+ */
+enum fields {
+	FOR_EACH_FIELD(GENERATE_ENUM)
+};
+
+#endif /* _UAPI_LINUX_UASYM_PARSER_H */
-- 
2.34.1


  parent reply	other threads:[~2023-07-06 14:46 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-06 14:42 [RFC][PATCH 00/10] KEYS: Introduce user asymmetric keys and signatures Roberto Sassu
2023-07-06 14:42 ` [RFC][PATCH 01/10] crypto: Export public key algorithm information Roberto Sassu
2023-07-06 14:42 ` [RFC][PATCH 02/10] crypto: Export signature encoding information Roberto Sassu
2023-07-06 14:42 ` Roberto Sassu [this message]
2023-07-06 14:42 ` [RFC][PATCH 04/10] KEYS: asymmetric: Introduce the user asymmetric key parser Roberto Sassu
2023-07-06 14:42 ` [RFC][PATCH 05/10] KEYS: asymmetric: Introduce the user asymmetric key signature parser Roberto Sassu
2023-07-06 14:42 ` [RFC][PATCH 06/10] verification: Add verify_uasym_signature() and verify_uasym_sig_message() Roberto Sassu
2023-07-06 14:42 ` [RFC][PATCH 07/10] KEYS: asymmetric: Preload user asymmetric keys from a keyring blob Roberto Sassu
2023-07-06 14:42 ` [RFC][PATCH 08/10] KEYS: Introduce load_uasym_keyring() Roberto Sassu
2023-07-06 14:42 ` [RFC][PATCH 09/10] bpf: Introduce bpf_verify_uasym_signature() kfunc Roberto Sassu
2023-07-06 14:42 ` [RFC][PATCH 10/10] selftests/bpf: Prepare a test for user asymmetric key signatures Roberto Sassu
2023-07-06 14:42 ` [RFC][GNUPG][PATCH 1/2] Convert PGP keys to the user asymmetric keys format Roberto Sassu
2023-07-06 14:42 ` [RFC][GNUPG][PATCH 2/2] Convert PGP signatures to the user asymmetric key signatures format Roberto Sassu
2023-07-06 23:27 ` [RFC][PATCH 00/10] KEYS: Introduce user asymmetric keys and signatures Alexei Starovoitov
2023-07-07  7:03   ` Roberto Sassu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230706144225.1046544-4-roberto.sassu@huaweicloud.com \
    --to=roberto.sassu@huaweicloud.com \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=Jason@zx2c4.com \
    --cc=andrii@kernel.org \
    --cc=antony@vennard.ch \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=devel@lists.sequoia-pgp.org \
    --cc=dhowells@redhat.com \
    --cc=dwmw2@infradead.org \
    --cc=ebiggers@kernel.org \
    --cc=gnupg-devel@gnupg.org \
    --cc=haoluo@google.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=jarkko@kernel.org \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=keyrings@vger.kernel.org \
    --cc=konstantin@linuxfoundation.org \
    --cc=kpsingh@kernel.org \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=mail@maciej.szmigiero.name \
    --cc=martin.lau@linux.dev \
    --cc=mhiramat@kernel.org \
    --cc=mykolal@fb.com \
    --cc=paul@paul-moore.com \
    --cc=pbrobinson@gmail.com \
    --cc=roberto.sassu@huawei.com \
    --cc=rostedt@goodmis.org \
    --cc=sdf@google.com \
    --cc=shuah@kernel.org \
    --cc=song@kernel.org \
    --cc=wiktor@metacode.biz \
    --cc=yhs@fb.com \
    --cc=zbyszek@in.waw.pl \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.