From patchwork Thu Jul 20 15:32:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13320665 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C69D7EB64DD for ; Thu, 20 Jul 2023 15:34:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232608AbjGTPeu (ORCPT ); Thu, 20 Jul 2023 11:34:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40590 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232638AbjGTPet (ORCPT ); Thu, 20 Jul 2023 11:34:49 -0400 Received: from frasgout12.his.huawei.com (unknown [14.137.139.154]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A64F21B6; Thu, 20 Jul 2023 08:34:36 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4R6GcS4Zjwz9xGXS; Thu, 20 Jul 2023 23:21:28 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBHquXFU7lkGHDRBA--.21759S3; Thu, 20 Jul 2023 16:33:57 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, 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 Subject: [RFC][PATCH v3 1/9] lib: Add TLV parser Date: Thu, 20 Jul 2023 17:32:37 +0200 Message-Id: <20230720153247.3755856-2-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> References: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBHquXFU7lkGHDRBA--.21759S3 X-Coremail-Antispam: 1UD129KBjvAXoWfGw15XF1rKrWDArW7Jw18Xwb_yoW8JrWxCo ZI9r4Uur4rXr1j9a18Zw48Ar1UXry0gr43Aw1fGrW5ua4I9a45Kr45Kw43G3y5Aws8Kr45 t3sxX3y3Xw4DKrs3n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUYA7kC6x804xWl14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK 8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jr 4l82xGYIkIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Cr0_Gr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCF04k20xvY0x 0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E 7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_WrylIxkGc2Ij64vIr41lIxAIcV C0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UMIIF0xvE 42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6x kF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7IU1cdbUUUUUU== X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAEBF1jj4y-0gAAsS X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Add a parser of a generic TLV format: +-----------------+------------------+-----------------+ | data type (u64) | num fields (u64) | total len (u64) | # header +--------------+--+---------+--------+---------+-------+ | field1 (u64) | len1 (u64) | value1 (u8 len1) | +--------------+------------+------------------+ | ... | ... | ... | # data +--------------+------------+------------------+ | fieldN (u64) | lenN (u64) | valueN (u8 lenN) | +--------------+------------+------------------+ Each adopter can define its own data types and fields. The TLV parser does not need to be aware of those, and calls a callback function, supplied by the adopter, for every encountered field during parsing. The adopter can decide in the callback function how each defined field should be handled/parsed. Normally, calling tlv_parse() is sufficient for most of the use cases. In addition, tlv_parse_hdr() and tlv_parse_data() are also provided for more advanced use cases. Nesting TLVs is also possible, the parser of one field can call tlv_parse() to parse the inner structure. Signed-off-by: Roberto Sassu --- MAINTAINERS | 8 ++ include/linux/tlv_parser.h | 28 +++++ include/uapi/linux/tlv_parser.h | 59 ++++++++++ lib/Kconfig | 3 + lib/Makefile | 3 + lib/tlv_parser.c | 203 ++++++++++++++++++++++++++++++++ lib/tlv_parser.h | 17 +++ 7 files changed, 321 insertions(+) create mode 100644 include/linux/tlv_parser.h create mode 100644 include/uapi/linux/tlv_parser.h create mode 100644 lib/tlv_parser.c create mode 100644 lib/tlv_parser.h diff --git a/MAINTAINERS b/MAINTAINERS index aee340630ec..220463b2e51 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21456,6 +21456,14 @@ W: http://sourceforge.net/projects/tlan/ F: Documentation/networking/device_drivers/ethernet/ti/tlan.rst F: drivers/net/ethernet/ti/tlan.* +TLV PARSER +M: Roberto Sassu +L: linux-kernel@vger.kernel.org +S: Maintained +F: include/linux/tlv_parser.h +F: include/uapi/linux/tlv_parser.h +F: lib/tlv_parser.* + TMIO/SDHI MMC DRIVER M: Wolfram Sang L: linux-mmc@vger.kernel.org diff --git a/include/linux/tlv_parser.h b/include/linux/tlv_parser.h new file mode 100644 index 00000000000..7c673b5635e --- /dev/null +++ b/include/linux/tlv_parser.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * Header file of TLV parser. + */ + +#ifndef _LINUX_TLV_PARSER_H +#define _LINUX_TLV_PARSER_H + +#include + +typedef int (*parse_callback)(void *, __u64, const __u8 *, __u64); + +int tlv_parse_hdr(const __u8 **data, size_t *data_len, __u64 *parsed_data_type, + __u64 *parsed_num_fields, __u64 *parsed_total_len, + const char **data_types, __u64 num_data_types); +int tlv_parse_data(parse_callback callback, void *callback_data, + __u64 parsed_num_fields, const __u8 *data, size_t data_len, + const char **fields, __u64 num_fields); +int tlv_parse(__u64 expected_data_type, parse_callback callback, + void *callback_data, const __u8 *data, size_t data_len, + const char **data_types, __u64 num_data_types, + const char **fields, __u64 num_fields); + +#endif /* _LINUX_TLV_PARSER_H */ diff --git a/include/uapi/linux/tlv_parser.h b/include/uapi/linux/tlv_parser.h new file mode 100644 index 00000000000..fe87be4914d --- /dev/null +++ b/include/uapi/linux/tlv_parser.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * Implement the user space interface for the TLV parser. + */ + +#ifndef _UAPI_LINUX_TLV_PARSER_H +#define _UAPI_LINUX_TLV_PARSER_H + +#include + +/* + * TLV format: + * + * +-----------------+------------------+-----------------+ + * | data type (u64) | num fields (u64) | total len (u64) | # header + * +--------------+--+---------+--------+---------+-------+ + * | field1 (u64) | len1 (u64) | value1 (u8 len1) | + * +--------------+------------+------------------+ + * | ... | ... | ... | # data + * +--------------+------------+------------------+ + * | fieldN (u64) | lenN (u64) | valueN (u8 lenN) | + * +--------------+------------+------------------+ + */ + +/** + * struct tlv_hdr - Header of TLV format + * @data_type: Type of data to parse + * @num_fields: Number of fields provided + * @_reserved: Reserved for future use + * @total_len: Total length of the data blob, excluding the header + * + * This structure represents the header of the TLV data format. + */ +struct tlv_hdr { + __u64 data_type; + __u64 num_fields; + __u64 _reserved; + __u64 total_len; +} __packed; + +/** + * struct tlv_entry - Data entry of TLV format + * @field: Data field identifier + * @length: Data length + * @data: Data + * + * This structure represents a TLV entry of the data part of TLV data format. + */ +struct tlv_entry { + __u64 field; + __u64 length; + __u8 data[]; +} __packed; + +#endif /* _UAPI_LINUX_TLV_PARSER_H */ diff --git a/lib/Kconfig b/lib/Kconfig index 5c2da561c51..cea8d2c87b1 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -763,3 +763,6 @@ config ASN1_ENCODER config POLYNOMIAL tristate + +config TLV_PARSER + bool diff --git a/lib/Makefile b/lib/Makefile index 42d307ade22..ad55cd6c25b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -432,3 +432,6 @@ $(obj)/$(TEST_FORTIFY_LOG): $(addprefix $(obj)/, $(TEST_FORTIFY_LOGS)) FORCE ifeq ($(CONFIG_FORTIFY_SOURCE),y) $(obj)/string.o: $(obj)/$(TEST_FORTIFY_LOG) endif + +obj-$(CONFIG_TLV_PARSER) += tlv_parser.o +CFLAGS_tlv_parser.o += -I lib diff --git a/lib/tlv_parser.c b/lib/tlv_parser.c new file mode 100644 index 00000000000..c28e5584968 --- /dev/null +++ b/lib/tlv_parser.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * Implement the TLV parser. + */ + +#define pr_fmt(fmt) "TLV PARSER: "fmt +#include + +/** + * tlv_parse_hdr - Parse a TLV header + * @data: Data to parse (updated) + * @data_len: Length of @data (updated) + * @parsed_data_type: Parsed data type (updated) + * @parsed_num_fields: Parsed data fields (updated) + * @parsed_total_len: Length of parsed data part, excluding the header (updated) + * @data_types: Array of data type strings + * @num_data_types: Number of elements of @data_types + * + * Parse the header of the TLV data format, 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 tlv_parse_hdr(const __u8 **data, size_t *data_len, __u64 *parsed_data_type, + __u64 *parsed_num_fields, __u64 *parsed_total_len, + const char **data_types, __u64 num_data_types) +{ + struct tlv_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 tlv_hdr *)*data; + + *data += sizeof(*hdr); + *data_len -= sizeof(*hdr); + + *parsed_data_type = __be64_to_cpu(hdr->data_type); + if (*parsed_data_type >= num_data_types) { + pr_debug("Invalid data type %llu, max: %llu\n", + *parsed_data_type, num_data_types - 1); + return -EBADMSG; + } + + *parsed_num_fields = __be64_to_cpu(hdr->num_fields); + + if (hdr->_reserved != 0) { + pr_debug("_reserved must be zero\n"); + return -EBADMSG; + } + + *parsed_total_len = __be64_to_cpu(hdr->total_len); + if (*parsed_total_len > *data_len) { + pr_debug("Invalid total length %llu, expected: %lu\n", + *parsed_total_len, *data_len); + return -EBADMSG; + } + + pr_debug("Header: type: %s, num fields: %llu, total len: %lld\n", + data_types[*parsed_data_type], *parsed_num_fields, + *parsed_total_len); + + return 0; +} + +/** + * tlv_parse_data - Parse a TLV data + * @callback: Callback function to call to parse the fields + * @callback_data: Opaque data to supply to the callback function + * @parsed_num_fields: Parsed data fields + * @data: Data to parse + * @data_len: Length of @data + * @fields: Array of field strings + * @num_fields: Number of elements of @fields + * + * Parse the data part of the TLV data format 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 tlv_parse_data(parse_callback callback, void *callback_data, + __u64 parsed_num_fields, const __u8 *data, size_t data_len, + const char **fields, __u64 num_fields) +{ + const __u8 *data_ptr = data; + struct tlv_entry *entry; + __u64 parsed_field; + __u64 len; + int ret, i; + + for (i = 0; i < parsed_num_fields; i++) { + if (data_len < sizeof(*entry)) + return -EBADMSG; + + entry = (struct tlv_entry *)data_ptr; + data_ptr += sizeof(*entry); + data_len -= sizeof(*entry); + + parsed_field = __be64_to_cpu(entry->field); + if (parsed_field >= num_fields) { + pr_debug("Invalid field %llu, max: %llu\n", + parsed_field, num_fields - 1); + return -EBADMSG; + } + + len = __be64_to_cpu(entry->length); + + if (data_len < len) + return -EBADMSG; + + pr_debug("Data: field: %s, len: %llu\n", fields[parsed_field], + len); + + if (!len) + continue; + + ret = callback(callback_data, parsed_field, data_ptr, len); + if (ret < 0) { + pr_debug("Parsing of field %s failed, ret: %d\n", + fields[parsed_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; +} + +/** + * tlv_parse - Parse data in TLV format + * @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 + * @data_types: Array of data type strings + * @num_data_types: Number of elements of @data_types + * @fields: Array of field strings + * @num_fields: Number of elements of @fields + * + * Parse data in TLV format 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 tlv_parse(__u64 expected_data_type, parse_callback callback, + void *callback_data, const __u8 *data, size_t data_len, + const char **data_types, __u64 num_data_types, + const char **fields, __u64 num_fields) +{ + __u64 parsed_data_type; + __u64 parsed_num_fields; + __u64 parsed_total_len; + int ret = 0; + + pr_debug("Start parsing data blob, size: %ld, expected data type: %s\n", + data_len, data_types[expected_data_type]); + + while (data_len) { + ret = tlv_parse_hdr(&data, &data_len, &parsed_data_type, + &parsed_num_fields, &parsed_total_len, + data_types, num_data_types); + if (ret < 0) + goto out; + + if (parsed_data_type == expected_data_type) + break; + + /* + * tlv_parse_hdr() already checked that + * parsed_total_len <= data_len. + */ + data += parsed_total_len; + data_len -= parsed_total_len; + } + + if (!data_len) { + pr_debug("Data type %s not found\n", + data_types[expected_data_type]); + ret = -ENOENT; + goto out; + } + + ret = tlv_parse_data(callback, callback_data, parsed_num_fields, data, + parsed_total_len, fields, num_fields); +out: + pr_debug("End of parsing data blob, ret: %d\n", ret); + return ret; +} diff --git a/lib/tlv_parser.h b/lib/tlv_parser.h new file mode 100644 index 00000000000..b196c6edbf0 --- /dev/null +++ b/lib/tlv_parser.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * Header file of TLV parser. + */ + +#ifndef _LIB_TLV_PARSER_H +#define _LIB_TLV_PARSER_H + +#include +#include +#include + +#endif /* _LIB_TLV_PARSER_H */ From patchwork Thu Jul 20 15:32:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13320666 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8499EEB64DC for ; Thu, 20 Jul 2023 15:35:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232638AbjGTPfA (ORCPT ); Thu, 20 Jul 2023 11:35:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40590 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232645AbjGTPew (ORCPT ); Thu, 20 Jul 2023 11:34:52 -0400 Received: from frasgout13.his.huawei.com (ecs-14-137-139-46.compute.hwclouds-dns.com [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 703131BC1; Thu, 20 Jul 2023 08:34:50 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.229]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4R6Gft0xYyz9xyNR; Thu, 20 Jul 2023 23:23:34 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBHquXFU7lkGHDRBA--.21759S4; Thu, 20 Jul 2023 16:34:10 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, 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 Subject: [RFC][PATCH v3 2/9] crypto: Export public key algorithm information Date: Thu, 20 Jul 2023 17:32:38 +0200 Message-Id: <20230720153247.3755856-3-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> References: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBHquXFU7lkGHDRBA--.21759S4 X-Coremail-Antispam: 1UD129KBjvJXoWxGFy7ur13WrW8Gw47uw1UGFg_yoWrGFWDpr s09a1rX3y8ZFy7KryS9FyFyryft3yF9r15tanrXw1fAFn7tw18Jrs2vrZrCF1kXFsrJ3yr ua97ZF9rGw18GaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUB2b4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUXw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV WxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_ Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ew Av7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY 6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxAIw28IcxkI7V AKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCj r7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZVWrXwCIc40Y0x0EwIxGrwCI42IY6x IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1lIxAIcVCF 04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7 CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUFa9-UUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAEBF1jj4y-0wAAsT X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Export the public keys algorithm identifiers, so that user space can reference them when passing data to the kernel. Define and export the pub_key_algo_name array, so that kernel subsystems can get the string associated to the public key algorithm identifier. Signed-off-by: Roberto Sassu --- crypto/Kconfig | 3 +++ crypto/Makefile | 1 + crypto/pub_key_info.c | 20 ++++++++++++++++++++ include/crypto/pub_key_info.h | 15 +++++++++++++++ include/uapi/linux/pub_key_info.h | 22 ++++++++++++++++++++++ 5 files changed, 61 insertions(+) create mode 100644 crypto/pub_key_info.c create mode 100644 include/crypto/pub_key_info.h create mode 100644 include/uapi/linux/pub_key_info.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 650b1b3620d..2558025461b 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1420,6 +1420,9 @@ endmenu config CRYPTO_HASH_INFO bool +config CRYPTO_PUB_KEY_INFO + bool + if !KMSAN # avoid false positives from assembly if ARM source "arch/arm/crypto/Kconfig" diff --git a/crypto/Makefile b/crypto/Makefile index 953a7e105e5..fcdb5918e58 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -206,6 +206,7 @@ obj-$(CONFIG_XOR_BLOCKS) += xor.o obj-$(CONFIG_ASYNC_CORE) += async_tx/ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o +obj-$(CONFIG_CRYPTO_PUB_KEY_INFO) += pub_key_info.o crypto_simd-y := simd.o obj-$(CONFIG_CRYPTO_SIMD) += crypto_simd.o diff --git a/crypto/pub_key_info.c b/crypto/pub_key_info.c new file mode 100644 index 00000000000..d12a08e5972 --- /dev/null +++ b/crypto/pub_key_info.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Public key info: Public key algorithms information + */ + +#include +#include + +const char *const pub_key_algo_name[PKEY_ALGO__LAST] = { + [PKEY_ALGO_RSA] = "rsa", + [PKEY_ALGO_ECDSA] = "ecdsa", + [PKEY_ALGO_ECDSA_P192] = "ecdsa-nist-p192", + [PKEY_ALGO_ECDSA_P256] = "ecdsa-nist-p256", + [PKEY_ALGO_ECDSA_P384] = "ecdsa-nist-p384", + [PKEY_ALGO_ECRDSA] = "ecrdsa", + [PKEY_ALGO_SM2] = "sm2", +}; +EXPORT_SYMBOL_GPL(pub_key_algo_name); diff --git a/include/crypto/pub_key_info.h b/include/crypto/pub_key_info.h new file mode 100644 index 00000000000..ea411792778 --- /dev/null +++ b/include/crypto/pub_key_info.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Public key info: Public key algorithms information + */ + +#ifndef _CRYPTO_PUB_KEY_INFO_H +#define _CRYPTO_PUB_KEY_INFO_H + +#include + +extern const char *const pub_key_algo_name[PKEY_ALGO__LAST]; + +#endif /* _CRYPTO_PUB_KEY_INFO_H */ diff --git a/include/uapi/linux/pub_key_info.h b/include/uapi/linux/pub_key_info.h new file mode 100644 index 00000000000..a5595969156 --- /dev/null +++ b/include/uapi/linux/pub_key_info.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Public key info: Public key algorithms information + */ + +#ifndef _UAPI_LINUX_PUB_KEY_INFO_H +#define _UAPI_LINUX_PUB_KEY_INFO_H + +enum pub_key_algo { + PKEY_ALGO_RSA, + PKEY_ALGO_ECDSA, + PKEY_ALGO_ECDSA_P192, + PKEY_ALGO_ECDSA_P256, + PKEY_ALGO_ECDSA_P384, + PKEY_ALGO_ECRDSA, + PKEY_ALGO_SM2, + PKEY_ALGO__LAST, +}; + +#endif /* _UAPI_LINUX_PUB_KEY_INFO_H */ From patchwork Thu Jul 20 15:32:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13320667 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04514EB64DC for ; Thu, 20 Jul 2023 15:35:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232723AbjGTPfR (ORCPT ); Thu, 20 Jul 2023 11:35:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40888 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232695AbjGTPfF (ORCPT ); Thu, 20 Jul 2023 11:35:05 -0400 Received: from frasgout13.his.huawei.com (ecs-14-137-139-46.compute.hwclouds-dns.com [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B7E042699; Thu, 20 Jul 2023 08:35:01 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4R6Gg61Rs7z9xyNR; Thu, 20 Jul 2023 23:23:46 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBHquXFU7lkGHDRBA--.21759S5; Thu, 20 Jul 2023 16:34:22 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, 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 Subject: [RFC][PATCH v3 3/9] crypto: Export signature encoding information Date: Thu, 20 Jul 2023 17:32:39 +0200 Message-Id: <20230720153247.3755856-4-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> References: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBHquXFU7lkGHDRBA--.21759S5 X-Coremail-Antispam: 1UD129KBjvJXoWxZw1kJFWkXrykGr1DZFWfGrg_yoW5Kr47pa n8KrWfGrWrJFyxCr93uw4xKryrt3ykuFyYkanruF18AryxCr18XrsFyryDCF1kJrs7CFW8 WFWvg3Wqgwn8GaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBab4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUWw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCF04k20xvY0x 0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E 7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_WrylIxkGc2Ij64vIr41lIxAIcV C0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI42IY 6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aV CY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x07UAkuxUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAEBF1jj4y-0wABsS X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Export the signature encoding identifiers, so that user space can reference them when passing data to the kernel. Define and export the sig_enc_name array, so that kernel subsystems can get the string associated to the signature encoding identifier. Signed-off-by: Roberto Sassu --- crypto/Kconfig | 3 +++ crypto/Makefile | 1 + crypto/sig_enc_info.c | 16 ++++++++++++++++ include/crypto/sig_enc_info.h | 15 +++++++++++++++ include/uapi/linux/sig_enc_info.h | 18 ++++++++++++++++++ 5 files changed, 53 insertions(+) create mode 100644 crypto/sig_enc_info.c create mode 100644 include/crypto/sig_enc_info.h create mode 100644 include/uapi/linux/sig_enc_info.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 2558025461b..ef6f1e4c5b4 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1423,6 +1423,9 @@ config CRYPTO_HASH_INFO config CRYPTO_PUB_KEY_INFO bool +config CRYPTO_SIG_ENC_INFO + bool + if !KMSAN # avoid false positives from assembly if ARM source "arch/arm/crypto/Kconfig" diff --git a/crypto/Makefile b/crypto/Makefile index fcdb5918e58..6d84fadfeda 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -207,6 +207,7 @@ obj-$(CONFIG_ASYNC_CORE) += async_tx/ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o obj-$(CONFIG_CRYPTO_PUB_KEY_INFO) += pub_key_info.o +obj-$(CONFIG_CRYPTO_SIG_ENC_INFO) += sig_enc_info.o crypto_simd-y := simd.o obj-$(CONFIG_CRYPTO_SIMD) += crypto_simd.o diff --git a/crypto/sig_enc_info.c b/crypto/sig_enc_info.c new file mode 100644 index 00000000000..649cf98385f --- /dev/null +++ b/crypto/sig_enc_info.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Sig enc info: Signature encoding information + */ + +#include +#include + +const char *const sig_enc_name[SIG_ENC__LAST] = { + [SIG_ENC_PKCS1] = "pkcs1", + [SIG_ENC_X962] = "x962", + [SIG_ENC_RAW] = "raw", +}; +EXPORT_SYMBOL_GPL(sig_enc_name); diff --git a/include/crypto/sig_enc_info.h b/include/crypto/sig_enc_info.h new file mode 100644 index 00000000000..6e28890a0e4 --- /dev/null +++ b/include/crypto/sig_enc_info.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Sig enc info: Signature encoding information + */ + +#ifndef _CRYPTO_SIG_ENC_INFO_H +#define _CRYPTO_SIG_ENC_INFO_H + +#include + +extern const char *const sig_enc_name[SIG_ENC__LAST]; + +#endif /* _CRYPTO_SIG_ENC_INFO_H */ diff --git a/include/uapi/linux/sig_enc_info.h b/include/uapi/linux/sig_enc_info.h new file mode 100644 index 00000000000..0a2ac028bef --- /dev/null +++ b/include/uapi/linux/sig_enc_info.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Sig enc info: Signature encoding information + */ + +#ifndef _UAPI_LINUX_SIG_ENC_INFO_H +#define _UAPI_LINUX_SIG_ENC_INFO_H + +enum sig_enc_info { + SIG_ENC_PKCS1, + SIG_ENC_X962, + SIG_ENC_RAW, + SIG_ENC__LAST, +}; + +#endif /* _UAPI_LINUX_SIG_ENC_INFO_H */ From patchwork Thu Jul 20 15:32:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13320668 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 604BDEB64DD for ; Thu, 20 Jul 2023 15:35:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232709AbjGTPfd (ORCPT ); Thu, 20 Jul 2023 11:35:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40584 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232700AbjGTPfZ (ORCPT ); Thu, 20 Jul 2023 11:35:25 -0400 Received: from frasgout12.his.huawei.com (unknown [14.137.139.154]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CDF82270E; Thu, 20 Jul 2023 08:35:12 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.229]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4R6Gd85ZWmz9xGXP; Thu, 20 Jul 2023 23:22:04 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBHquXFU7lkGHDRBA--.21759S6; Thu, 20 Jul 2023 16:34:34 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, 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 Subject: [RFC][PATCH v3 4/9] KEYS: asymmetric: Introduce the user asymmetric key parser Date: Thu, 20 Jul 2023 17:32:40 +0200 Message-Id: <20230720153247.3755856-5-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> References: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBHquXFU7lkGHDRBA--.21759S6 X-Coremail-Antispam: 1UD129KBjvAXoWfJrWDXr4rXFyxWFy7Xr13Jwb_yoW8Jr18Jo Zagr45Jw4fWw4qkan5uF17Ar4DZ345GF4fZ3y3uF1UZan0v34UKr4rCayxCFWfAw1UKwnY 9ryxJa4aqw4Utw15n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUYK7kC6x804xWl14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK 8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF 0E3s1l82xGYIkIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vE j48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxV AFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x02 67AKxVW8Jr0_Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F4 0Ex7xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC 6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82 IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC2 0s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r4a6rW5MIIYrxkI7VAKI48JMI IF0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr1l IxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4 A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUFgAwUUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAEBF1jj4y-2AAAsY X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Introduce a new parser for user asymmetric keys, in TLV format. User space tools are expected to convert keys from their original format to the TLV format. Signed-off-by: Roberto Sassu --- crypto/asymmetric_keys/Kconfig | 13 ++ crypto/asymmetric_keys/Makefile | 6 + crypto/asymmetric_keys/asymmetric_type.c | 3 +- crypto/asymmetric_keys/uasym_key_parser.c | 240 ++++++++++++++++++++++ crypto/asymmetric_keys/uasym_parser.h | 26 +++ include/keys/asymmetric-type.h | 1 + include/uapi/linux/uasym_parser.h | 50 +++++ 7 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 crypto/asymmetric_keys/uasym_key_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..4a5f66511d4 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -85,4 +85,17 @@ 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 + select CRYPTO_PUB_KEY_INFO + select TLV_PARSER + 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..5ba30cca09e 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -76,3 +76,9 @@ 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_key_parser.o diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c index a5da8ccd353..53d0fc26eac 100644 --- a/crypto/asymmetric_keys/asymmetric_type.c +++ b/crypto/asymmetric_keys/asymmetric_type.c @@ -430,7 +430,7 @@ static int asymmetric_key_preparse(struct key_preparsed_payload *prep) /* * Clean up the key ID list */ -static void asymmetric_key_free_kids(struct asymmetric_key_ids *kids) +void asymmetric_key_free_kids(struct asymmetric_key_ids *kids) { int i; @@ -440,6 +440,7 @@ static void asymmetric_key_free_kids(struct asymmetric_key_ids *kids) kfree(kids); } } +EXPORT_SYMBOL_GPL(asymmetric_key_free_kids); /* * Clean up the preparse data diff --git a/crypto/asymmetric_keys/uasym_key_parser.c b/crypto/asymmetric_keys/uasym_key_parser.c new file mode 100644 index 00000000000..36a5faa2706 --- /dev/null +++ b/crypto/asymmetric_keys/uasym_key_parser.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * Implement the user asymmetric key parser. + */ + +#define pr_fmt(fmt) "UASYM KEY: "fmt +#include +#include +#include +#include + +#include "uasym_parser.h" + +const char *data_types_str[] = { + FOR_EACH_DATA_TYPE(GENERATE_STRING) +}; + +const char *fields_str[] = { + FOR_EACH_FIELD(GENERATE_STRING) +}; + +static int parse_key_pub(struct public_key *pub, enum fields field, + const u8 *field_data, u64 field_data_len) +{ + int ret = 0; + + kenter(",%u,%llu", field, field_data_len); + + pub->key = kmemdup(field_data, field_data_len, GFP_KERNEL); + if (!pub->key) { + ret = -ENOMEM; + goto out; + } + + pub->keylen = field_data_len; + pr_debug("Key length in bytes: %d\n", pub->keylen); +out: + kleave(" = %d", ret); + return ret; +} + +int parse_key_algo(const char **pkey_algo, enum fields field, + const u8 *field_data, u64 field_data_len) +{ + u8 algo; + int ret = 0; + + kenter(",%u,%llu", field, field_data_len); + + if (field_data_len != sizeof(u8)) { + pr_debug("Unexpected data length %llu, expected %lu\n", + field_data_len, sizeof(u8)); + ret = -EBADMSG; + goto out; + } + + algo = *field_data; + + if (algo >= PKEY_ALGO__LAST) { + pr_debug("Unexpected public key algo %u\n", algo); + ret = -EBADMSG; + goto out; + } + + *pkey_algo = pub_key_algo_name[algo]; + pr_debug("Public key algo: %s\n", *pkey_algo); +out: + kleave(" = %d", ret); + return ret; +} + +int parse_key_kid(struct asymmetric_key_id **id, enum fields field, + const u8 *field_data, u64 field_data_len) +{ + int ret = 0; + + kenter(",%u,%llu", field, field_data_len); + + *id = asymmetric_key_generate_id(field_data, field_data_len, NULL, 0); + if (!*id) { + ret = -ENOMEM; + goto out; + } + + pr_debug("Key/auth identifier: %*phN\n", (*id)->len, (*id)->data); +out: + kleave(" = %d", ret); + return ret; +} + +static int parse_key_desc(struct key_preparsed_payload *prep, enum fields field, + const u8 *field_data, u64 field_data_len) +{ + int ret = 0; + + kenter(",%u,%llu", field, field_data_len); + + if (field_data[field_data_len - 1] != '\0') { + pr_err("Non-terminated string\n"); + ret = -EBADMSG; + goto out; + } + + prep->description = kstrndup(field_data, field_data_len, GFP_KERNEL); + if (!prep->description) { + ret = -ENOMEM; + goto out; + } + + pr_debug("Key description: %s\n", prep->description); +out: + kleave(" = %d", ret); + return ret; +} + +struct callback_struct { + struct public_key *pub; + struct asymmetric_key_ids *kids; + struct key_preparsed_payload *prep; +}; + +static int key_callback(void *callback_data, u64 field, const u8 *field_data, + u64 field_data_len) +{ + struct callback_struct *cb_s = (struct callback_struct *)callback_data; + struct asymmetric_key_id **id; + int ret; + + switch (field) { + case KEY_PUB: + ret = parse_key_pub(cb_s->pub, field, field_data, + field_data_len); + break; + case KEY_ALGO: + ret = parse_key_algo(&cb_s->pub->pkey_algo, field, field_data, + field_data_len); + break; + case KEY_KID0: + id = (struct asymmetric_key_id **)&cb_s->kids->id[0]; + ret = parse_key_kid(id, field, field_data, field_data_len); + break; + case KEY_KID1: + id = (struct asymmetric_key_id **)&cb_s->kids->id[1]; + ret = parse_key_kid(id, field, field_data, field_data_len); + break; + case KEY_KID2: + id = (struct asymmetric_key_id **)&cb_s->kids->id[2]; + ret = parse_key_kid(id, field, field_data, field_data_len); + break; + case KEY_DESC: + ret = parse_key_desc(cb_s->prep, field, field_data, + field_data_len); + break; + default: + pr_debug("Unhandled field %llu\n", field); + /* Just ignore non-relevant fields. */ + ret = 0; + break; + } + + return ret; +} + +static int uasym_key_parse(struct key_preparsed_payload *prep) +{ + struct callback_struct cb_s; + int ret; + + kenter(""); + + cb_s.pub = kzalloc(sizeof(*cb_s.pub), GFP_KERNEL); + if (!cb_s.pub) { + ret = -ENOMEM; + goto out; + } + + cb_s.pub->id_type = "UASYM_KEY"; + + cb_s.kids = kzalloc(sizeof(*cb_s.kids), GFP_KERNEL); + if (!cb_s.kids) { + ret = -ENOMEM; + goto out; + } + + cb_s.prep = prep; + + ret = tlv_parse(TYPE_KEY, key_callback, &cb_s, prep->data, + prep->datalen, data_types_str, TYPE__LAST, fields_str, + FIELD__LAST); + if (ret < 0) + goto out; + + if (!cb_s.pub->key || !cb_s.pub->pkey_algo || + (!cb_s.kids->id[0] && !cb_s.kids->id[1] && !cb_s.kids->id[2])) { + pr_debug("Incomplete data\n"); + ret = -ENOENT; + goto out; + } + + /* We're pinning the module by being linked against it */ + __module_get(public_key_subtype.owner); + prep->payload.data[asym_subtype] = &public_key_subtype; + prep->payload.data[asym_key_ids] = cb_s.kids; + prep->payload.data[asym_crypto] = cb_s.pub; + prep->quotalen = 100; +out: + kleave(" = %d", ret); + + if (ret < 0) { + public_key_free(cb_s.pub); + asymmetric_key_free_kids(cb_s.kids); + return ret; + } + + return 0; +} + +static struct asymmetric_key_parser uasym_key_parser = { + .owner = THIS_MODULE, + .name = "uasym_key", + .parse = uasym_key_parse +}; + +static int __init uasym_key_init(void) +{ + return register_asymmetric_key_parser(&uasym_key_parser); +} + +static void __exit uasym_key_exit(void) +{ + unregister_asymmetric_key_parser(&uasym_key_parser); +} + +module_init(uasym_key_init); +module_exit(uasym_key_exit); +MODULE_LICENSE("GPL"); diff --git a/crypto/asymmetric_keys/uasym_parser.h b/crypto/asymmetric_keys/uasym_parser.h new file mode 100644 index 00000000000..cd8bc934d38 --- /dev/null +++ b/crypto/asymmetric_keys/uasym_parser.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * Header file of user asymmetric keys and signatures. + */ + +#include +#include + +#include + +#define kenter(FMT, ...) \ + pr_debug("==> %s("FMT")\n", __func__, ##__VA_ARGS__) +#define kleave(FMT, ...) \ + pr_debug("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) + +extern const char *data_types_str[]; +extern const char *fields_str[]; + +int parse_key_algo(const char **pkey_algo, enum fields field, + const u8 *field_data, u64 field_data_len); +int parse_key_kid(struct asymmetric_key_id **id, enum fields field, + const u8 *field_data, u64 field_data_len); diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h index 69a13e1e5b2..acbb8c805f6 100644 --- a/include/keys/asymmetric-type.h +++ b/include/keys/asymmetric-type.h @@ -66,6 +66,7 @@ extern struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1, size_t len_1, const void *val_2, size_t len_2); +void asymmetric_key_free_kids(struct asymmetric_key_ids *kids); static inline const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key) { diff --git a/include/uapi/linux/uasym_parser.h b/include/uapi/linux/uasym_parser.h new file mode 100644 index 00000000000..25c2995b3d4 --- /dev/null +++ b/include/uapi/linux/uasym_parser.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * Implement the user space interface for user asymmetric keys and signatures. + */ + +#ifndef _UAPI_LINUX_UASYM_PARSER_H +#define _UAPI_LINUX_UASYM_PARSER_H + +#include +#include + +#define FOR_EACH_DATA_TYPE(DATA_TYPE) \ + DATA_TYPE(TYPE_KEY) \ + DATA_TYPE(TYPE__LAST) + +#define FOR_EACH_FIELD(FIELD) \ + FIELD(KEY_PUB) \ + FIELD(KEY_ALGO) \ + FIELD(KEY_KID0) \ + FIELD(KEY_KID1) \ + FIELD(KEY_KID2) \ + FIELD(KEY_DESC) \ + 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 */ From patchwork Thu Jul 20 15:32:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13320669 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6C0FEC001DC for ; Thu, 20 Jul 2023 15:35:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232736AbjGTPfv (ORCPT ); Thu, 20 Jul 2023 11:35:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41512 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232741AbjGTPfj (ORCPT ); Thu, 20 Jul 2023 11:35:39 -0400 Received: from frasgout13.his.huawei.com (ecs-14-137-139-46.compute.hwclouds-dns.com [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 16F6D2711; Thu, 20 Jul 2023 08:35:24 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4R6GgZ2n3xz9xyNS; Thu, 20 Jul 2023 23:24:10 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBHquXFU7lkGHDRBA--.21759S7; Thu, 20 Jul 2023 16:34:46 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, 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 Subject: [RFC][PATCH v3 5/9] KEYS: asymmetric: Introduce the user asymmetric key signature parser Date: Thu, 20 Jul 2023 17:32:41 +0200 Message-Id: <20230720153247.3755856-6-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> References: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBHquXFU7lkGHDRBA--.21759S7 X-Coremail-Antispam: 1UD129KBjvAXoW3tryfuw13WryUuw1fKr1kGrg_yoW8CFWUWo Z3Wr45Ca1Fqr1qkF43G3WkCw48ZrWDJFWUAw43W3ZFq3Wjq34UKF48Ca47uFWfXw1UGrWf AF18Ja4xJ3yIqwn3n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUYK7kC6x804xWl14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK 8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF 0E3s1l82xGYIkIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vE j48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_JFI_Gr1l84ACjcxK6xIIjxv20xvEc7CjxV AFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x02 67AKxVW8Jr0_Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F4 0Ex7xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC 6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1l42xK82 IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC2 0s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r4a6rW5MIIYrxkI7VAKI48JMI IF0xvE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr1l IxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4 A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUFgAwUUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAEBF1jj5C8nwAAsD X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Introduce a parser for user asymmetric key signatures, in TLV format. User space tools are expected to convert signatures from their original format in the TLV format. Also, add the API to perform signature verification of system data, introduced in a later patch. Signed-off-by: Roberto Sassu --- MAINTAINERS | 1 + crypto/asymmetric_keys/Kconfig | 1 + crypto/asymmetric_keys/Makefile | 3 +- crypto/asymmetric_keys/uasym_sig_parser.c | 497 ++++++++++++++++++++++ include/crypto/uasym_keys_sigs.h | 72 ++++ include/uapi/linux/uasym_parser.h | 9 + 6 files changed, 582 insertions(+), 1 deletion(-) create mode 100644 crypto/asymmetric_keys/uasym_sig_parser.c create mode 100644 include/crypto/uasym_keys_sigs.h diff --git a/MAINTAINERS b/MAINTAINERS index 220463b2e51..d3af1e179b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3143,6 +3143,7 @@ F: Documentation/crypto/asymmetric-keys.rst F: crypto/asymmetric_keys/ F: include/crypto/pkcs7.h F: include/crypto/public_key.h +F: include/crypto/uasym_sig.h F: include/linux/verification.h ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 4a5f66511d4..d9d82cada0a 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -89,6 +89,7 @@ config UASYM_KEYS_SIGS tristate "User asymmetric keys and signatures" depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE select CRYPTO_PUB_KEY_INFO + select CRYPTO_SIG_ENC_INFO select TLV_PARSER help This option enables user asymmetric keys and signatures. They are diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index 5ba30cca09e..191b7fe8359 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -81,4 +81,5 @@ $(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_key_parser.o +uasym_keys_sigs-y := uasym_key_parser.o \ + uasym_sig_parser.o diff --git a/crypto/asymmetric_keys/uasym_sig_parser.c b/crypto/asymmetric_keys/uasym_sig_parser.c new file mode 100644 index 00000000000..97fa1381a78 --- /dev/null +++ b/crypto/asymmetric_keys/uasym_sig_parser.c @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Authors: + * David Howells + * Roberto Sassu + * + * Implement the user asymmetric key signature parser. + */ + +#define pr_fmt(fmt) "UASYM SIG: "fmt +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uasym_parser.h" + +struct uasym_sig_message { + struct public_key_signature *sig; + size_t data_len; + const void *data; + size_t sig_data_len; + const void *sig_data; +}; + +static int parse_sig_s(struct public_key_signature *sig, enum fields field, + const u8 *field_data, u64 field_data_len) +{ + int ret = 0; + + kenter(",%u,%llu", field, field_data_len); + + sig->s = kmemdup(field_data, field_data_len, GFP_KERNEL); + if (!sig->s) { + ret = -ENOMEM; + goto out; + } + + sig->s_size = field_data_len; + pr_debug("Signature length: %d\n", sig->s_size); +out: + kleave(" = %d", ret); + return ret; +} + +static int parse_sig_hash_algo_size(struct public_key_signature *sig, + enum fields field, const u8 *field_data, + u64 field_data_len) +{ + u8 algo; + int ret = 0; + + kenter(",%u,%llu", field, field_data_len); + + if (field_data_len != sizeof(u8)) { + pr_debug("Unexpected data length %llu, expected %lu\n", + field_data_len, sizeof(u8)); + ret = -EBADMSG; + goto out; + } + + algo = *field_data; + + if (algo >= HASH_ALGO__LAST) { + pr_debug("Unexpected hash algo %u\n", algo); + ret = -EBADMSG; + goto out; + } + + sig->hash_algo = hash_algo_name[algo]; + sig->digest_size = hash_digest_size[algo]; + pr_debug("Hash algo: %s, digest length: %d\n", sig->hash_algo, + sig->digest_size); +out: + kleave(" = %d", ret); + return ret; +} + +static int parse_sig_enc(struct public_key_signature *sig, enum fields field, + const u8 *field_data, u64 field_data_len) +{ + u8 enc; + int ret = 0; + + kenter(",%u,%llu", field, field_data_len); + + if (field_data_len != sizeof(u8)) { + pr_debug("Unexpected data length %llu, expected %lu\n", + field_data_len, sizeof(u8)); + ret = -EBADMSG; + goto out; + } + + enc = *field_data; + + if (enc >= SIG_ENC__LAST) { + pr_debug("Unexpected encoding %u\n", enc); + ret = -EBADMSG; + goto out; + } + + sig->encoding = sig_enc_name[enc]; + pr_debug("Signature encoding: %s\n", sig->encoding); +out: + kleave(" = %d", ret); + return ret; +} + +static int parse_sig_data_end(struct uasym_sig_message *uasym_sig, + enum fields field, const u8 *field_data, + u64 field_data_len) +{ + int ret = 0; + + kenter(",%u,%llu", field, field_data_len); + + uasym_sig->sig_data = kmemdup(field_data, field_data_len, GFP_KERNEL); + if (!uasym_sig->sig_data) { + ret = -ENOMEM; + goto out; + } + + uasym_sig->sig_data_len = field_data_len; + pr_debug("Signature data length appended at the end: %ld\n", + uasym_sig->sig_data_len); +out: + kleave(" = %d", ret); + return ret; +} + +static int sig_callback(void *callback_data, u64 field, const u8 *field_data, + u64 field_data_len) +{ + struct uasym_sig_message *uasym_sig; + struct public_key_signature *sig; + struct asymmetric_key_id **id; + int ret; + + uasym_sig = (struct uasym_sig_message *)callback_data; + sig = uasym_sig->sig; + + switch (field) { + case SIG_S: + ret = parse_sig_s(sig, field, field_data, field_data_len); + break; + case SIG_KEY_ALGO: + ret = parse_key_algo(&sig->pkey_algo, field, field_data, + field_data_len); + break; + case SIG_HASH_ALGO: + ret = parse_sig_hash_algo_size(sig, field, field_data, + field_data_len); + break; + case SIG_ENC: + ret = parse_sig_enc(sig, field, field_data, field_data_len); + break; + case SIG_KID0: + id = (struct asymmetric_key_id **)&sig->auth_ids[0]; + ret = parse_key_kid(id, field, field_data, field_data_len); + break; + case SIG_KID1: + id = (struct asymmetric_key_id **)&sig->auth_ids[1]; + ret = parse_key_kid(id, field, field_data, field_data_len); + break; + case SIG_KID2: + id = (struct asymmetric_key_id **)&sig->auth_ids[2]; + ret = parse_key_kid(id, field, field_data, field_data_len); + break; + case SIG_DATA_END: + ret = parse_sig_data_end(uasym_sig, field, field_data, + field_data_len); + break; + default: + pr_debug("Unhandled field %llu\n", field); + /* Just ignore non-relevant fields. */ + ret = 0; + break; + } + + return ret; +} + +/** + * uasym_sig_parse_message - Parse a user asymmetric key signature + * @sig_data: Signature blob + * @sig_len: Length of signature blob + * + * Parse a user asymmetric key signature and initialize the signature context. + * + * Return: A uasym_sig_message structure on success, an error pointer on error. + */ +struct uasym_sig_message *uasym_sig_parse_message(const u8 *sig_data, + size_t sig_len) +{ + struct uasym_sig_message *uasym_sig = NULL; + struct public_key_signature *sig; + int ret = -EBADMSG; + + kenter(""); + + uasym_sig = kzalloc(sizeof(*uasym_sig), GFP_KERNEL); + if (!uasym_sig) { + ret = -ENOMEM; + goto out; + } + + sig = kzalloc(sizeof(*sig), GFP_KERNEL); + if (!sig) { + ret = -ENOMEM; + goto out; + } + + uasym_sig->sig = sig; + + ret = tlv_parse(TYPE_SIG, sig_callback, uasym_sig, sig_data, sig_len, + data_types_str, TYPE__LAST, fields_str, FIELD__LAST); + if (ret < 0) + goto out; + + if (!sig->s || !sig->pkey_algo || !sig->hash_algo || !sig->encoding || + (!sig->auth_ids[0] && !sig->auth_ids[1] && !sig->auth_ids[2])) { + pr_debug("Incomplete data\n"); + ret = -ENOENT; + goto out; + } +out: + if (ret < 0) { + uasym_sig_free_message(uasym_sig); + uasym_sig = ERR_PTR(ret); + kleave(" = ERR_PTR(%d)", ret); + } + + kleave(" = PTR(uasym_sig)"); + return uasym_sig; +} +EXPORT_SYMBOL_GPL(uasym_sig_parse_message); + +/** + * uasym_sig_supply_detached_data - Supply data to verify a user asym key sig + * @uasym_sig: The signature context + * @data: The data to be verified + * @data_len: The amount of data + * + * Supply the detached data needed to verify a user asymmetric key signature. + * Note that no attempt to retain/pin the data is made. That is left to the + * caller. The data will not be modified by uasym_sig_verify_message() and will + * not be freed when the signature context is freed. + * + * Return: Zero on success, -EINVAL if data are already supplied. + */ +int uasym_sig_supply_detached_data(struct uasym_sig_message *uasym_sig, + const void *data, size_t data_len) +{ + if (uasym_sig->data) { + pr_debug("Data already supplied\n"); + return -EINVAL; + } + + uasym_sig->data = data; + uasym_sig->data_len = data_len; + return 0; +} +EXPORT_SYMBOL_GPL(uasym_sig_supply_detached_data); + +/** + * uasym_sig_get_content_data - Get access to content data and additional data + * @uasym_sig: The signature context + * @_data: Place to return a pointer to the data (updated) + * @_data_len: Place to return the data length (updated) + * @_headerlen: Size of the additional data (updated) + * + * Get access to the data associated to the user asymmetric key signature. + * This includes the content data eventually supplied by the caller of the user + * asymmetric key signatures API, and the additional data resulting from the + * signature parsing, appended at the end (more orderings can be supported + * in the future). + * + * Data is allocated, to concatenate together the two data sources, and must be + * freed by the caller. It is presented in a way that is suitable for + * calculating the digest for verifying the signature. + * + * Return: Zero if the data and additional data can be provided, + * a negative value on error. + */ +int uasym_sig_get_content_data(struct uasym_sig_message *uasym_sig, + const void **_data, size_t *_data_len, + size_t *_headerlen) +{ + void *data; + + if (!uasym_sig->data) + return -ENODATA; + + if (!_data) + goto skip_data; + + data = kmalloc(uasym_sig->data_len + uasym_sig->sig_data_len, + GFP_KERNEL); + if (!data) + return -ENOMEM; + + memcpy(data, uasym_sig->data, uasym_sig->data_len); + memcpy(data + uasym_sig->data_len, uasym_sig->sig_data, + uasym_sig->sig_data_len); + *_data = data; +skip_data: + if (_data_len) + *_data_len = uasym_sig->data_len + uasym_sig->sig_data_len; + if (_headerlen) + *_headerlen = uasym_sig->data_len; + return 0; +} +EXPORT_SYMBOL_GPL(uasym_sig_get_content_data); + +static int uasym_sig_digest(struct uasym_sig_message *uasym_sig) +{ + struct public_key_signature *sig = uasym_sig->sig; + struct crypto_shash *tfm; + struct shash_desc *desc; + size_t desc_size; + int ret; + + /* The digest was calculated already. */ + if (sig->digest) + return 0; + + tfm = crypto_alloc_shash(sig->hash_algo, 0, 0); + if (IS_ERR(tfm)) + return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); + + desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); + + ret = -ENOMEM; + sig->digest = kmalloc(sig->digest_size, GFP_KERNEL); + if (!sig->digest) + goto error_no_desc; + + desc = kzalloc(desc_size, GFP_KERNEL); + if (!desc) + goto error_no_desc; + + desc->tfm = tfm; + + ret = crypto_shash_init(desc); + if (ret < 0) + goto error; + + ret = crypto_shash_update(desc, uasym_sig->data, uasym_sig->data_len); + if (ret < 0) + goto error; + + if (uasym_sig->sig_data_len) { + ret = crypto_shash_update(desc, uasym_sig->sig_data, + uasym_sig->sig_data_len); + if (ret < 0) + goto error; + } + + ret = crypto_shash_final(desc, sig->digest); +error: + kfree(desc); +error_no_desc: + crypto_free_shash(tfm); + return ret; +} + +/** + * uasym_sig_get_digest - Obtain the digest and algorithm of the data to verify + * @uasym_sig: The signature context + * @digest: The buffer the digest is written to + * @digest_len: The length of @digest + * @hash_algo: The algorithm the digest is calculated with + * + * Calculate the digest of data to verify with the user asymmetric key + * signature, if not calculated already. Pass the pointer of the digest from + * the public_key_signature structure, the length and the algorithm to the + * caller. + * + * Return: Zero on success, a negative value otherwise. + */ +int uasym_sig_get_digest(struct uasym_sig_message *uasym_sig, const u8 **digest, + u32 *digest_len, enum hash_algo *hash_algo) +{ + struct public_key_signature *sig = uasym_sig->sig; + int i, ret; + + ret = uasym_sig_digest(uasym_sig); + if (ret) + return ret; + + *digest = sig->digest; + *digest_len = sig->digest_size; + + i = match_string(hash_algo_name, HASH_ALGO__LAST, sig->hash_algo); + if (i >= 0) + *hash_algo = i; + + return 0; +} +EXPORT_SYMBOL_GPL(uasym_sig_get_digest); + +static struct key *get_key(struct uasym_sig_message *uasym_sig, + struct key *keyring) +{ + struct public_key_signature *sig = uasym_sig->sig; + struct key *key; + + key = find_asymmetric_key(keyring, sig->auth_ids[0], sig->auth_ids[1], + sig->auth_ids[2], false); + if (IS_ERR(key)) { + pr_debug("Public key not found (%*phN, %*phN, %*phN)\n", + sig->auth_ids[0] ? sig->auth_ids[0]->len : 0, + sig->auth_ids[0] ? sig->auth_ids[0]->data : NULL, + sig->auth_ids[1] ? sig->auth_ids[1]->len : 0, + sig->auth_ids[1] ? sig->auth_ids[1]->data : NULL, + sig->auth_ids[2] ? sig->auth_ids[2]->len : 0, + sig->auth_ids[2] ? sig->auth_ids[2]->data : NULL); + + switch (PTR_ERR(key)) { + /* Hide some search errors */ + case -EACCES: + case -ENOTDIR: + case -EAGAIN: + return ERR_PTR(-ENOKEY); + default: + return ERR_CAST(key); + } + } + + return key; +} + +/** + * uasym_sig_verify_message - Verify the user asymmetric key signature + * @uasym_sig: The signature context + * @keyring: Keyring containing the key for signature verification + * + * Calculate the digest, search the key for signature verification, and verify + * the signature. + * + * Return: Zero if the signature is valid, a negative value otherwise. + */ +int uasym_sig_verify_message(struct uasym_sig_message *uasym_sig, + struct key *keyring) +{ + const struct public_key *pub; + struct key *key; + int ret; + + ret = uasym_sig_digest(uasym_sig); + if (ret < 0) + return ret; + + key = get_key(uasym_sig, keyring); + if (IS_ERR(key)) + return PTR_ERR(key); + + pub = key->payload.data[asym_crypto]; + + if (strcmp(pub->pkey_algo, uasym_sig->sig->pkey_algo) != 0 && + (strncmp(pub->pkey_algo, "ecdsa-", 6) != 0 || + strcmp(uasym_sig->sig->pkey_algo, "ecdsa") != 0)) { + ret = -EKEYREJECTED; + goto out; + } + + ret = verify_signature(key, uasym_sig->sig); +out: + key_put(key); + return ret; +} +EXPORT_SYMBOL_GPL(uasym_sig_verify_message); + +/** + * uasym_sig_free_message - Free the memory allocated + * @uasym_sig: The signature context + * + * Free the memory allocated for the verification of the user asymmetric key + * signature. + */ +void uasym_sig_free_message(struct uasym_sig_message *uasym_sig) +{ + if (!uasym_sig) + return; + + kfree(uasym_sig->sig_data); + public_key_signature_free(uasym_sig->sig); + kfree(uasym_sig); +} +EXPORT_SYMBOL_GPL(uasym_sig_free_message); diff --git a/include/crypto/uasym_keys_sigs.h b/include/crypto/uasym_keys_sigs.h new file mode 100644 index 00000000000..ac5bce6d081 --- /dev/null +++ b/include/crypto/uasym_keys_sigs.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * Header of the user asymmetric keys and signatures parser. + */ + +#ifndef _CRYPTO_UASYM_KEYS_SIGS_H +#define _CRYPTO_UASYM_KEYS_SIGS_H + +#include +#include + +struct key; +struct uasym_sig_message; + +#ifdef CONFIG_UASYM_KEYS_SIGS +struct uasym_sig_message *uasym_sig_parse_message(const u8 *sig_data, + size_t sig_len); +int uasym_sig_supply_detached_data(struct uasym_sig_message *uasym_sig, + const void *data, size_t data_len); +int uasym_sig_get_content_data(struct uasym_sig_message *uasym_sig, + const void **_data, size_t *_data_len, + size_t *_headerlen); +int uasym_sig_get_digest(struct uasym_sig_message *uasym_sig, const u8 **buf, + u32 *len, enum hash_algo *hash_algo); +int uasym_sig_verify_message(struct uasym_sig_message *uasym_sig, + struct key *keyring); +void uasym_sig_free_message(struct uasym_sig_message *uasym_sig); +#else +static inline struct uasym_sig_message * +uasym_sig_parse_message(const u8 *sig_data, size_t sig_len) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline int +uasym_sig_supply_detached_data(struct uasym_sig_message *uasym_sig, + const void *data, size_t data_len) +{ + return -EOPNOTSUPP; +} + +static inline int +uasym_sig_get_content_data(struct uasym_sig_message *uasym_sig, + const void **_data, size_t *_data_len, + size_t *_headerlen) +{ + return -EOPNOTSUPP; +} + +static inline int uasym_sig_get_digest(struct uasym_sig_message *uasym_sig, + const u8 **buf, u32 *len, + enum hash_algo *hash_algo) +{ + return -EOPNOTSUPP; +} + +static inline int uasym_sig_verify_message(struct uasym_sig_message *uasym_sig, + struct key *keyring) +{ + return -EOPNOTSUPP; +} + +static inline void uasym_sig_free_message(struct uasym_sig_message *uasym_sig) +{ +} + +#endif /* CONFIG_UASYM_KEYS_SIGS */ +#endif /* _CRYPTO_UASYM_KEYS_SIGS_H */ diff --git a/include/uapi/linux/uasym_parser.h b/include/uapi/linux/uasym_parser.h index 25c2995b3d4..d1bc823d954 100644 --- a/include/uapi/linux/uasym_parser.h +++ b/include/uapi/linux/uasym_parser.h @@ -15,6 +15,7 @@ #define FOR_EACH_DATA_TYPE(DATA_TYPE) \ DATA_TYPE(TYPE_KEY) \ + DATA_TYPE(TYPE_SIG) \ DATA_TYPE(TYPE__LAST) #define FOR_EACH_FIELD(FIELD) \ @@ -24,6 +25,14 @@ FIELD(KEY_KID1) \ FIELD(KEY_KID2) \ FIELD(KEY_DESC) \ + FIELD(SIG_S) \ + FIELD(SIG_KEY_ALGO) \ + FIELD(SIG_HASH_ALGO) \ + FIELD(SIG_ENC) \ + FIELD(SIG_KID0) \ + FIELD(SIG_KID1) \ + FIELD(SIG_KID2) \ + FIELD(SIG_DATA_END) \ FIELD(FIELD__LAST) #define GENERATE_ENUM(ENUM) ENUM, From patchwork Thu Jul 20 15:32:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13320670 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1AFEFEB64DD for ; Thu, 20 Jul 2023 15:36:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232764AbjGTPgM (ORCPT ); Thu, 20 Jul 2023 11:36:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41536 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232743AbjGTPfy (ORCPT ); Thu, 20 Jul 2023 11:35:54 -0400 Received: from frasgout11.his.huawei.com (unknown [14.137.139.23]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8D58E272B; Thu, 20 Jul 2023 08:35:37 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.228]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4R6Ggm1jDQz9v7g2; Thu, 20 Jul 2023 23:24:20 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBHquXFU7lkGHDRBA--.21759S8; Thu, 20 Jul 2023 16:34:58 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, 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 Subject: [RFC][PATCH v3 6/9] verification: Add verify_uasym_signature() and verify_uasym_sig_message() Date: Thu, 20 Jul 2023 17:32:42 +0200 Message-Id: <20230720153247.3755856-7-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> References: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBHquXFU7lkGHDRBA--.21759S8 X-Coremail-Antispam: 1UD129KBjvJXoW3JFy8CrW3Wr1rurykAF43ZFb_yoWxKF4xpF 9Yqr1rZF98Awn3Aa47Ka1I9w1fWrn5Jw17KasFy3WfZFnYq3ZrGrs0gF1YqrW5C348GFWj 9r9FvFW3KanxAw7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBvb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCF04k20x vY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I 3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_WrylIxkGc2Ij64vIr41lIx AIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI 42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z2 80aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x07UZo7tUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAEBF1jj5C8oAAAs8 X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Introduce verify_uasym_signature() and verify_uasym_sig_message(), to verify user asymmetric key 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 --- certs/system_keyring.c | 125 +++++++++++++++++++++++++++++++++++ include/linux/verification.h | 46 +++++++++++++ 2 files changed, 171 insertions(+) diff --git a/certs/system_keyring.c b/certs/system_keyring.c index a7a49b17ceb..dbee2e5b732 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -16,6 +16,7 @@ #include #include #include +#include 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_UASYM_KEYS_SIGS +/** + * verify_uasym_sig_message - Verify a user asym key signature on system data + * @data: The data to be verified (must be provided) + * @len: Size of @data + * @uasym_sig: The signature context + * @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 user asymmetric key 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_uasym_sig_message(const void *data, size_t len, + struct uasym_sig_message *uasym_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 && uasym_sig_supply_detached_data(uasym_sig, data, len)) { + pr_err("Failed to supply data for user asymmetric key 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 = uasym_sig_verify_message(uasym_sig, trusted_keys); + if (ret < 0) + goto error; + + if (view_content) { + size_t sig_data_len; + + ret = uasym_sig_get_content_data(uasym_sig, &data, &len, + &sig_data_len); + if (ret < 0) { + if (ret == -ENODATA) + pr_devel("User asymmetric key 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_uasym_sig_message); + +/** + * verify_uasym_signature - Verify a user asym key signature on system data + * @data: The data to be verified (must be provided) + * @len: Size of @data + * @raw_uasym_sig: The raw signature + * @raw_uasym_sig_len: The size of @raw_uasym_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 user asymmetric key 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_uasym_signature(const void *data, size_t len, + const void *raw_uasym_sig, size_t raw_uasym_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 uasym_sig_message *uasym_sig; + int ret; + + uasym_sig = uasym_sig_parse_message(raw_uasym_sig, raw_uasym_sig_len); + if (IS_ERR(uasym_sig)) + return PTR_ERR(uasym_sig); + + ret = verify_uasym_sig_message(data, len, uasym_sig, trusted_keys, usage, + view_content, ctx); + + uasym_sig_free_message(uasym_sig); + pr_devel("<==%s() = %d\n", __func__, ret); + return ret; +} +EXPORT_SYMBOL_GPL(verify_uasym_signature); +#endif /* CONFIG_UASYM_KEYS_SIGS */ #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */ #ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING diff --git a/include/linux/verification.h b/include/linux/verification.h index f34e50ebcf6..9e8deea7755 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 uasym_sig_message; extern int verify_pkcs7_signature(const void *data, size_t len, const void *raw_pkcs7, size_t pkcs7_len, @@ -62,6 +63,51 @@ extern int verify_pkcs7_message_sig(const void *data, size_t len, size_t asn1hdrlen), void *ctx); +#ifdef CONFIG_UASYM_KEYS_SIGS +int verify_uasym_sig_message(const void *data, size_t len, + struct uasym_sig_message *uasym_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 verify_uasym_signature(const void *data, size_t len, + const void *raw_uasym_sig, + size_t raw_uasym_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); +#else +static inline int verify_uasym_sig_message(const void *data, size_t len, + struct uasym_sig_message *uasym_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_uasym_signature(const void *data, size_t len, + const void *raw_uasym_sig, + size_t raw_uasym_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_UASYM_KEYS_SIGS */ + #ifdef CONFIG_SIGNED_PE_FILE_VERIFICATION extern int verify_pefile_signature(const void *pebuf, unsigned pelen, struct key *trusted_keys, From patchwork Thu Jul 20 15:32:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13320671 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6176BEB64DD for ; Thu, 20 Jul 2023 15:36:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232820AbjGTPg1 (ORCPT ); Thu, 20 Jul 2023 11:36:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41988 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232792AbjGTPgF (ORCPT ); Thu, 20 Jul 2023 11:36:05 -0400 Received: from frasgout11.his.huawei.com (unknown [14.137.139.23]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E8D692D75; Thu, 20 Jul 2023 08:35:48 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4R6Gh01dHcz9xqxP; Thu, 20 Jul 2023 23:24:32 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBHquXFU7lkGHDRBA--.21759S9; Thu, 20 Jul 2023 16:35:10 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, 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 Subject: [RFC][PATCH v3 7/9] KEYS: asymmetric: Preload user asymmetric keys from a keyring blob Date: Thu, 20 Jul 2023 17:32:43 +0200 Message-Id: <20230720153247.3755856-8-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> References: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBHquXFU7lkGHDRBA--.21759S9 X-Coremail-Antispam: 1UD129KBjvJXoW3AF13Xr1fAFWxCw4Dury5CFg_yoW7XF4rpa yrCrWrtFZ0ywn7C34FkF1Igw13CrW093y5Ka4Skw1Yv34qqF4kGrWIgr1rKry5Jr1kKayf Z34q9w4UCr1ktrJanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBvb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCF04k20x vY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I 3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_WrylIxkGc2Ij64vIr41lIx AIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI 42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z2 80aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x07UZo7tUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAEBF1jj4y-3QAAsd X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Provide a function to load user asymmetric keys from a keyring blob to the keyring supplied: int preload_uasym_keys(const u8 *data, size_t data_len, struct key *keyring); Signed-off-by: Roberto Sassu --- crypto/asymmetric_keys/Makefile | 3 +- crypto/asymmetric_keys/uasym_key_preload.c | 102 +++++++++++++++++++++ include/crypto/uasym_keys_sigs.h | 9 ++ 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 crypto/asymmetric_keys/uasym_key_preload.c diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index 191b7fe8359..ffc6c7d6e65 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -82,4 +82,5 @@ $(obj)/mscode.asn1.o: $(obj)/mscode.asn1.c $(obj)/mscode.asn1.h # obj-$(CONFIG_UASYM_KEYS_SIGS) += uasym_keys_sigs.o uasym_keys_sigs-y := uasym_key_parser.o \ - uasym_sig_parser.o + uasym_sig_parser.o \ + uasym_key_preload.o diff --git a/crypto/asymmetric_keys/uasym_key_preload.c b/crypto/asymmetric_keys/uasym_key_preload.c new file mode 100644 index 00000000000..039dbf64378 --- /dev/null +++ b/crypto/asymmetric_keys/uasym_key_preload.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Authors: + * David Howells + * Roberto Sassu + * + * Load user asymmetric keys from a keyring blob. + */ + +#define pr_fmt(fmt) "UASYM PRELOAD: "fmt +#include +#include +#include +#include + +#include "uasym_parser.h" + +/** + * create_uasym_key - Create a user asymmetric key + * @data_start: Where the user asymmetric key starts in the blob + * @data_end: Where the user asymmetric key ends in the blob + * @keyring: The keyring to add the new key to + * + * Create a user asymmetric key from the supplied buffer. + */ +static void __init create_uasym_key(const u8 *data_start, const u8 *data_end, + struct key *keyring) +{ + key_ref_t key; + + key = key_create_or_update(make_key_ref(keyring, 1), "asymmetric", NULL, + data_start, data_end - data_start, + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ), + KEY_ALLOC_NOT_IN_QUOTA | + KEY_ALLOC_BUILT_IN | + KEY_ALLOC_BYPASS_RESTRICTION); + if (IS_ERR(key)) { + pr_notice("Ignoring user asymmetric key, error: %ld\n", + PTR_ERR(key)); + return; + } + + pr_notice("Loaded user asymmetric key '%s'\n", + key_ref_to_ptr(key)->description); + + key_ref_put(key); +} + +/** + * preload_uasym_keys - Load user asymmetric keys from a keyring blob + * @data: The keyring blob containing the user asymmetric keys + * @data_len: The size of the @data blob + * @keyring: The keyring to add the new keys to + * + * Preload a pack of user asymmetric keys from a keyring blob. + * + * The callers should override the current creds if they want the keys to be + * owned by someone other than the current process's owner. Keys will not be + * accounted towards the owner's quota. + * + * This function may only be called whilst the kernel is booting. + * + * Return: Zero on success, a negative value otherwise. + */ +int __init preload_uasym_keys(const u8 *data, size_t data_len, + struct key *keyring) +{ + const u8 *data_ptr = data, *data_end = data + data_len; + u64 data_type; + u64 num_fields; + u64 total_len; + int ret; + + kenter(""); + + while (data_ptr < data_end) { + ret = tlv_parse_hdr(&data_ptr, &data_len, &data_type, + &num_fields, &total_len, data_types_str, + TYPE__LAST); + if (ret < 0) { + pr_notice("Unable to parse keyring blob, ret: %d\n", + ret); + return ret; + } + + if (data_type != TYPE_KEY) { + data_ptr += total_len; + continue; + } + + create_uasym_key(data_ptr - sizeof(struct tlv_hdr), + data_ptr + total_len, keyring); + + data_ptr += total_len; + } + + return 0; +} diff --git a/include/crypto/uasym_keys_sigs.h b/include/crypto/uasym_keys_sigs.h index ac5bce6d081..a227d6d082e 100644 --- a/include/crypto/uasym_keys_sigs.h +++ b/include/crypto/uasym_keys_sigs.h @@ -29,6 +29,9 @@ int uasym_sig_get_digest(struct uasym_sig_message *uasym_sig, const u8 **buf, int uasym_sig_verify_message(struct uasym_sig_message *uasym_sig, struct key *keyring); void uasym_sig_free_message(struct uasym_sig_message *uasym_sig); + +int __init preload_uasym_keys(const u8 *data, size_t data_len, + struct key *keyring); #else static inline struct uasym_sig_message * uasym_sig_parse_message(const u8 *sig_data, size_t sig_len) @@ -68,5 +71,11 @@ static inline void uasym_sig_free_message(struct uasym_sig_message *uasym_sig) { } +static inline int __init preload_uasym_keys(const u8 *data, size_t data_len, + struct key *keyring) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_UASYM_KEYS_SIGS */ #endif /* _CRYPTO_UASYM_KEYS_SIGS_H */ From patchwork Thu Jul 20 15:32:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13320672 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 11CB9EB64DD for ; Thu, 20 Jul 2023 15:36:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232806AbjGTPgm (ORCPT ); Thu, 20 Jul 2023 11:36:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232803AbjGTPgQ (ORCPT ); Thu, 20 Jul 2023 11:36:16 -0400 Received: from frasgout12.his.huawei.com (unknown [14.137.139.154]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0B5E030EE; Thu, 20 Jul 2023 08:36:01 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4R6Gf50KX0z9xGYG; Thu, 20 Jul 2023 23:22:53 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBHquXFU7lkGHDRBA--.21759S10; Thu, 20 Jul 2023 16:35:23 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, 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 Subject: [RFC][PATCH v3 8/9] KEYS: Introduce load_uasym_keyring() Date: Thu, 20 Jul 2023 17:32:44 +0200 Message-Id: <20230720153247.3755856-9-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> References: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBHquXFU7lkGHDRBA--.21759S10 X-Coremail-Antispam: 1UD129KBjvJXoWxJF1DtrW5Ww17KFyUGF48JFb_yoWruw1fp3 y0kryrKr4vywn3G3yfCFyjgr43Cr1vkw4Yg3W3Cw15AF1DXrn8ZrsrKF1UKry5Wry5AryF qryIvr4Skw1UtaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBvb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26r4UJVWxJr1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCF04k20x vY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I 3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_GFv_WrylIxkGc2Ij64vIr41lIx AIcVC0I7IYx2IY67AKxVWUCVW8JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI 42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z2 80aVCY1x0267AKxVW8Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x07UZo7tUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAEBF1jj5C8owAAs- X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Preload user asymmetric keys from 'uasym_keys.bin', placed in certs/ of the kernel source directory. Signed-off-by: Roberto Sassu --- certs/Kconfig | 11 ++++++++++ certs/Makefile | 7 +++++++ certs/system_certificates.S | 18 ++++++++++++++++ certs/system_keyring.c | 41 +++++++++++++++++++++++++++++++++++-- 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/certs/Kconfig b/certs/Kconfig index 1f109b07087..16bbf0f4bb6 100644 --- a/certs/Kconfig +++ b/certs/Kconfig @@ -138,4 +138,15 @@ config SYSTEM_BLACKLIST_AUTH_UPDATE keyring. The PKCS#7 signature of the description is set in the key payload. Blacklist keys cannot be removed. +config UASYM_PRELOAD_PUBLIC_KEYS + bool "Preload user asymmetric keys" + depends on SYSTEM_TRUSTED_KEYRING + select UASYM_KEYS_SIGS + default n + help + Load at boot time the user asymmetric keys from a reserved area + (populated with the content of 'certs/uasym_keys.bin' provided at + kernel build time), and add them to the built-in keyring. Invalid + keys are ignored and the loading continues. + endmenu diff --git a/certs/Makefile b/certs/Makefile index 799ad7b9e68..2e5be6668a6 100644 --- a/certs/Makefile +++ b/certs/Makefile @@ -22,6 +22,13 @@ $(obj)/blacklist_hash_list: $(CONFIG_SYSTEM_BLACKLIST_HASH_LIST) FORCE targets += blacklist_hash_list +ifdef CONFIG_UASYM_PRELOAD_PUBLIC_KEYS +ifeq ($(shell ls $(srctree)/certs/uasym_keys.bin 2> /dev/null), $(srctree)/certs/uasym_keys.bin) +AFLAGS_system_certificates.o += -DHAVE_UASYM_KEYRING_BLOB +$(obj)/system_certificates.o: $(srctree)/certs/uasym_keys.bin +endif +endif + quiet_cmd_extract_certs = CERT $@ cmd_extract_certs = $(obj)/extract-cert "$(extract-cert-in)" $@ extract-cert-in = $(filter-out $(obj)/extract-cert, $(real-prereqs)) diff --git a/certs/system_certificates.S b/certs/system_certificates.S index 003e25d4a17..67b7c5effb6 100644 --- a/certs/system_certificates.S +++ b/certs/system_certificates.S @@ -44,3 +44,21 @@ module_cert_size: #else .long __module_cert_end - __module_cert_start #endif + + .align 8 + .globl uasym_keys +uasym_keys: +__uasym_key_list_start: +#ifdef HAVE_UASYM_KEYRING_BLOB + .incbin "certs/uasym_keys.bin" +#endif +__uasym_key_list_end: + + .align 8 + .globl uasym_keys_size +uasym_keys_size: +#ifdef CONFIG_64BIT + .quad __uasym_key_list_end - __uasym_key_list_start +#else + .long __uasym_key_list_end - __uasym_key_list_start +#endif diff --git a/certs/system_keyring.c b/certs/system_keyring.c index dbee2e5b732..6035bd2f795 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -179,6 +179,31 @@ static __init int system_trusted_keyring_init(void) return 0; } +#ifdef CONFIG_UASYM_PRELOAD_PUBLIC_KEYS +extern __initconst const u8 uasym_keys[]; +extern __initconst const unsigned long uasym_keys_size; + +/** + * load_uasym_keyring - Load user asymmetric keys from a keyring blob + * + * Load user asymmetric keys from a keyring blob. Halt the parsing if + * a parsing error is encountered. If parsing succeed, ignore invalid keys. + * + * Return: Zero on success or on failure (ignored). + */ +static __init int load_uasym_keyring(void) +{ + pr_notice("Loading compiled-in user asymmetric keys\n"); + + if (preload_uasym_keys(uasym_keys, uasym_keys_size, + builtin_trusted_keys) < 0) + pr_err("Can't load user asymmetric keys\n"); + + return 0; +} +late_initcall(load_uasym_keyring); +#endif /* CONFIG_UASYM_PRELOAD_PUBLIC_KEYS */ + /* * Must be initialised before we try and load the keys into the keyring. */ @@ -186,13 +211,25 @@ device_initcall(system_trusted_keyring_init); __init int load_module_cert(struct key *keyring) { + int ret; + if (!IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG)) return 0; pr_notice("Loading compiled-in module X.509 certificates\n"); - return x509_load_certificate_list(system_certificate_list, - module_cert_size, keyring); + ret = x509_load_certificate_list(system_certificate_list, + module_cert_size, keyring); +#ifdef CONFIG_UASYM_PRELOAD_PUBLIC_KEYS + if (!ret) { + pr_notice("Loading compiled-in user asymmetric keys\n"); + + ret = preload_uasym_keys(uasym_keys, uasym_keys_size, keyring); + if (ret < 0) + pr_err("Can't load user asymmetric keys\n"); + } +#endif + return ret; } /* From patchwork Thu Jul 20 15:32:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 13320673 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0651AEB64DC for ; Thu, 20 Jul 2023 15:37:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232846AbjGTPhC (ORCPT ); Thu, 20 Jul 2023 11:37:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40854 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232792AbjGTPgh (ORCPT ); Thu, 20 Jul 2023 11:36:37 -0400 Received: from frasgout13.his.huawei.com (ecs-14-137-139-46.compute.hwclouds-dns.com [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E2D52D53; Thu, 20 Jul 2023 08:36:13 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.228]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4R6GhV51dvz9xyNl; Thu, 20 Jul 2023 23:24:58 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwBHquXFU7lkGHDRBA--.21759S11; Thu, 20 Jul 2023 16:35:35 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, zohar@linux.ibm.com, dmitry.kasatkin@gmail.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, 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 Subject: [RFC][PATCH v3 9/9] ima: Support non-PKCS#7 modsig types Date: Thu, 20 Jul 2023 17:32:45 +0200 Message-Id: <20230720153247.3755856-10-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> References: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwBHquXFU7lkGHDRBA--.21759S11 X-Coremail-Antispam: 1UD129KBjvJXoW3JrW7uw4fWFykCw1ktF18Krg_yoW7Ww48p3 ZxuF1rCrZ8G3WxJFnYyw1aywnIkw15Gw15K3yjk3Z0yrnxZw1DGw1j9w1fZFy3K3yDWFWf Jr4xXr4YkF1kXaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUBqb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26F4UJVW0owAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I 80ewAv7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCj c4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxAIw28Icx kI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2Iq xVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVW8ZVWrXwCIc40Y0x0EwIxGrwCI42 IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF 0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87 Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZEXa7IU13l1DUUUUU== X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAEBF1jj5C8owACs9 X-CFilter-Loop: Reflected Precedence: bulk List-ID: From: Roberto Sassu Add support for alternative signature formats through the newly introduced user asymmetric key signatures. The corresponding API is invoked if the signature type is not PKEY_ID_PKCS7. If the signature type is PKEY_ID_PKCS7, nothing changes, the existing API is still invoked. Signed-off-by: Roberto Sassu --- security/integrity/ima/ima_modsig.c | 79 +++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/security/integrity/ima/ima_modsig.c b/security/integrity/ima/ima_modsig.c index 3e7bee30080..7c96cb2613a 100644 --- a/security/integrity/ima/ima_modsig.c +++ b/security/integrity/ima/ima_modsig.c @@ -12,11 +12,14 @@ #include #include #include +#include #include "ima.h" struct modsig { struct pkcs7_message *pkcs7_msg; + struct uasym_sig_message *uasym_sig; + u8 id_type; enum hash_algo hash_algo; @@ -28,8 +31,8 @@ struct modsig { * This is what will go to the measurement list if the template requires * storing the signature. */ - int raw_pkcs7_len; - u8 raw_pkcs7[]; + int raw_sig_len; + u8 raw_sig[]; }; /* @@ -57,27 +60,43 @@ int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, buf_len -= marker_len; sig = (const struct module_signature *)(p - sizeof(*sig)); - rc = mod_check_sig(sig, buf_len, func_tokens[func]); - if (rc) - return rc; + if (sig->id_type == PKEY_ID_PKCS7) { + rc = mod_check_sig(sig, buf_len, func_tokens[func]); + if (rc) + return rc; + } else { + /* Same as mod_check_sig() but skipping the id_type check. */ + if (sig->algo != 0 || + sig->hash != 0 || + sig->signer_len != 0 || + sig->key_id_len != 0 || + sig->__pad[0] != 0 || + sig->__pad[1] != 0 || + sig->__pad[2] != 0) + return -EBADMSG; + } sig_len = be32_to_cpu(sig->sig_len); buf_len -= sig_len + sizeof(*sig); - /* Allocate sig_len additional bytes to hold the raw PKCS#7 data. */ + /* Allocate sig_len additional bytes to hold the raw sig data. */ hdr = kzalloc(sizeof(*hdr) + sig_len, GFP_KERNEL); if (!hdr) return -ENOMEM; - hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len); - if (IS_ERR(hdr->pkcs7_msg)) { - rc = PTR_ERR(hdr->pkcs7_msg); + if (sig->id_type == PKEY_ID_PKCS7) + hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len); + else + hdr->uasym_sig = uasym_sig_parse_message(buf + buf_len, sig_len); + + if (IS_ERR(hdr->pkcs7_msg) || IS_ERR(hdr->uasym_sig)) { kfree(hdr); return rc; } - memcpy(hdr->raw_pkcs7, buf + buf_len, sig_len); - hdr->raw_pkcs7_len = sig_len; + memcpy(hdr->raw_sig, buf + buf_len, sig_len); + hdr->raw_sig_len = sig_len; + hdr->id_type = sig->id_type; /* We don't know the hash algorithm yet. */ hdr->hash_algo = HASH_ALGO__LAST; @@ -105,21 +124,38 @@ void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size) * Provide the file contents (minus the appended sig) so that the PKCS7 * code can calculate the file hash. */ - size -= modsig->raw_pkcs7_len + strlen(MODULE_SIG_STRING) + + size -= modsig->raw_sig_len + strlen(MODULE_SIG_STRING) + sizeof(struct module_signature); - rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size); + if (modsig->id_type == PKEY_ID_PKCS7) + rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size); + else + rc = uasym_sig_supply_detached_data(modsig->uasym_sig, buf, + size); if (rc) return; /* Ask the PKCS7 code to calculate the file hash. */ - rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest, - &modsig->digest_size, &modsig->hash_algo); + if (modsig->id_type == PKEY_ID_PKCS7) + rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest, + &modsig->digest_size, &modsig->hash_algo); + else + rc = uasym_sig_get_digest(modsig->uasym_sig, &modsig->digest, + &modsig->digest_size, + &modsig->hash_algo); } int ima_modsig_verify(struct key *keyring, const struct modsig *modsig) { - return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg, keyring, - VERIFYING_MODULE_SIGNATURE, NULL, NULL); + if (modsig->id_type == PKEY_ID_PKCS7) + return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg, + keyring, + VERIFYING_MODULE_SIGNATURE, + NULL, NULL); + else + return verify_uasym_sig_message(NULL, 0, modsig->uasym_sig, + keyring, + VERIFYING_MODULE_SIGNATURE, + NULL, NULL); } int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo, @@ -135,8 +171,8 @@ int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo, int ima_get_raw_modsig(const struct modsig *modsig, const void **data, u32 *data_len) { - *data = &modsig->raw_pkcs7; - *data_len = modsig->raw_pkcs7_len; + *data = &modsig->raw_sig; + *data_len = modsig->raw_sig_len; return 0; } @@ -146,6 +182,9 @@ void ima_free_modsig(struct modsig *modsig) if (!modsig) return; - pkcs7_free_message(modsig->pkcs7_msg); + if (modsig->id_type == PKEY_ID_PKCS7) + pkcs7_free_message(modsig->pkcs7_msg); + else + uasym_sig_free_message(modsig->uasym_sig); kfree(modsig); }