From patchwork Thu Jul 6 14:42:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 700733 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 96BDDEB64DD for ; Thu, 6 Jul 2023 14:49:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233559AbjGFOtm (ORCPT ); Thu, 6 Jul 2023 10:49:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37360 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232562AbjGFOt1 (ORCPT ); Thu, 6 Jul 2023 10:49:27 -0400 Received: from frasgout13.his.huawei.com (unknown [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F25E26A9; Thu, 6 Jul 2023 07:48:50 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4QxfJG0Rkpz9xFGh; Thu, 6 Jul 2023 22:37:34 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwAHQg0y06ZkPxkwBA--.58122S13; Thu, 06 Jul 2023 15:47:47 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, song@kernel.org, jolsa@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, rostedt@goodmis.org, mhiramat@kernel.org, mykolal@fb.com, shuah@kernel.org Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, bpf@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, paul@paul-moore.com, linux-security-module@vger.kernel.org, wiktor@metacode.biz, devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org, ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name, antony@vennard.ch, konstantin@linuxfoundation.org, James.Bottomley@HansenPartnership.com, Roberto Sassu Subject: [RFC][GNUPG][PATCH 1/2] Convert PGP keys to the user asymmetric keys format Date: Thu, 6 Jul 2023 16:42:24 +0200 Message-Id: <20230706144225.1046544-12-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> References: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwAHQg0y06ZkPxkwBA--.58122S13 X-Coremail-Antispam: 1UD129KBjvAXoWfJFyrJF4kCrW8Kr4rJF1fJFb_yoW8GF4fCo WfWa1rJw15GF47Zws09r17Xa47XrnagrZrJw4fArWDZa1vyry5ta47Aa4fJ3y5Cr4F9r13 XFyftrWSkrs7tFn3n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUOY7kC6x804xWl14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK 8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF 0E3s1l82xGYIkIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vE j48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxV AFwI0_Cr1j6rxdM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVWxJr0_GcWle2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Wr v_Gr1UMIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Gr0_Xr1lIxAIcVC0I7IYx2IY 6xkF7I0E14v26F4UJVW0owCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aV AFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVWxJr0_GcJvcSsGvfC2KfnxnUUI43ZE Xa7IU0sqXPUUUUU== X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAKBF1jj4vZ8QAAse X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org From: Roberto Sassu Introduce the new gpg command --conv-kernel, to convert PGP keys to the user asymmetric keys format. The --export command cannot be used, as it would not allow to convert signatures from a file. Signed-off-by: Roberto Sassu --- configure.ac | 7 ++ doc/gpg.texi | 4 + g10/Makefile.am | 4 + g10/conv-packet.c | 287 ++++++++++++++++++++++++++++++++++++++++++++++ g10/conv-packet.h | 37 ++++++ g10/gpg.c | 15 ++- g10/mainproc.c | 17 ++- g10/options.h | 2 + 8 files changed, 371 insertions(+), 2 deletions(-) create mode 100644 g10/conv-packet.c create mode 100644 g10/conv-packet.h diff --git a/configure.ac b/configure.ac index fe7e821089b..6c867e6409e 100644 --- a/configure.ac +++ b/configure.ac @@ -105,6 +105,7 @@ have_libusb=no have_libtss=no have_system_resolver=no gnupg_have_ldap="n/a" +have_uasym_support=no use_zip=yes use_bzip2=yes @@ -1817,6 +1818,11 @@ if test x"$use_run_gnupg_user_socket" = x"yes"; then [If defined try /run/gnupg/user before /run/user]) fi +AC_CHECK_HEADERS([linux/uasym_parser.h], [have_uasym_support=yes], []) +AM_CONDITIONAL([UASYM_KEYS_SIGS], [test "$have_uasym_support" = yes]) +if test "$have_uasym_support" = yes; then + CFLAGS="$CFLAGS -DUASYM_KEYS_SIGS" +fi # # Decide what to build @@ -2158,6 +2164,7 @@ echo " TLS support: $use_tls_library TOFU support: $use_tofu Tor support: $show_tor_support + Uasym support: $have_uasym_support " if test "$have_libtss" != no -a -z "$TPMSERVER" -a -z "$SWTPM"; then cat < + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include +#ifdef __BIG_ENDIAN__ +#include +#else +#include +#endif +#include + +#include "gpg.h" +#include "../common/util.h" +#include "packet.h" +#include "conv-packet.h" +#include "options.h" +#include "../common/i18n.h" + +static estream_t listfp; + +static void init_output(void) +{ + if (!listfp) + { + listfp = es_stdout; + + if (opt.outfile) { + listfp = es_fopen (opt.outfile, "wb"); + if (!listfp) { + log_error(_("cannot open %s for writing\n"), opt.outfile); + exit(1); + } + } + } +} + +/* + * Simple encoder primitives for ASN.1 BER/DER/CER + * + * Copyright (C) 2019 James.Bottomley@HansenPartnership.com + */ +static int asn1_encode_length(unsigned char *data, __u32 *data_len, __u32 len) +{ + if (len <= 0x7f) { + data[0] = len; + *data_len = 1; + return 0; + } + + if (len <= 0xff) { + data[0] = 0x81; + data[1] = len & 0xff; + *data_len = 2; + return 0; + } + + if (len <= 0xffff) { + data[0] = 0x82; + data[1] = (len >> 8) & 0xff; + data[2] = len & 0xff; + *data_len = 3; + return 0; + } + + if (len > 0xffffff) + return -EINVAL; + + data[0] = 0x83; + data[1] = (len >> 16) & 0xff; + data[2] = (len >> 8) & 0xff; + data[3] = len & 0xff; + *data_len = 4; + + return 0; +} + +static int mpis_to_asn1_sequence(gcry_mpi_t *pkey, int num_keys, + unsigned char **buffer, size_t *buffer_len) +{ + unsigned char asn1_key_len[PUBKEY_MAX_NSKEY][4]; + unsigned char asn1_seq_len[4]; + unsigned char *buffer_ptr; + __u32 asn1_key_len_len[PUBKEY_MAX_NSKEY]; + __u32 asn1_seq_len_len; + __u32 asn1_seq_payload_len = 0; + size_t nbytes; + gpg_error_t err; + int ret, i; + + for (i = 0, nbytes = 0; i < num_keys; i++) { + err = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nbytes, pkey[i]); + if (err) + return -EINVAL; + + ret = asn1_encode_length(asn1_key_len[i], &asn1_key_len_len[i], nbytes); + if (ret < 0) + return ret; + + asn1_seq_payload_len += 1 + asn1_key_len_len[i] + nbytes; + } + + ret = asn1_encode_length(asn1_seq_len, &asn1_seq_len_len, + asn1_seq_payload_len); + if (ret < 0) + return ret; + + *buffer_len = 1 + asn1_seq_len_len + asn1_seq_payload_len; + *buffer = xmalloc_clear(*buffer_len); + if (!*buffer) + return -ENOMEM; + + buffer_ptr = *buffer; + + /* ASN1_SEQUENCE */ + *buffer_ptr++ = 0x30; + memcpy(buffer_ptr, &asn1_seq_len, asn1_seq_len_len); + buffer_ptr += asn1_seq_len_len; + + for (i = 0; i < num_keys; i++) { + /* ASN1_INTEGER */ + *buffer_ptr++ = 0x02; + memcpy(buffer_ptr, &asn1_key_len[i], asn1_key_len_len[i]); + buffer_ptr += asn1_key_len_len[i]; + + err = gcry_mpi_print(GCRYMPI_FMT_USG, buffer_ptr, + *buffer_len - (buffer_ptr - *buffer), &nbytes, pkey[i]); + if (err) { + xfree(*buffer); + return -EINVAL; + } + + buffer_ptr += nbytes; + } + + *buffer_len = buffer_ptr - *buffer; + + return 0; +} + +static int pgp_to_kernel_algo(int pgp_algorithm, gcry_mpi_t pkey, __u8 *algo) +{ + char *curve = NULL; + const char *name; + int ret = 0; + + switch (pgp_algorithm) { + case PUBKEY_ALGO_RSA: + case PUBKEY_ALGO_RSA_S: + *algo = PKEY_ALGO_RSA; + break; + case PUBKEY_ALGO_ECDSA: + *algo = PKEY_ALGO_ECDSA; + if (!pkey) + break; + + curve = openpgp_oid_to_str (pkey); + name = openpgp_oid_to_curve (curve, 0); + if (!strcmp(name, "nistp192")) + *algo = PKEY_ALGO_ECDSA_P192; + else if (!strcmp(name, "nistp256")) + *algo = PKEY_ALGO_ECDSA_P256; + else if (!strcmp(name, "nistp384")) + *algo = PKEY_ALGO_ECDSA_P384; + else + ret = -EOPNOTSUPP; + break; + default: + ret = -EOPNOTSUPP; + break; + } + + xfree(curve); + return ret; +} + +int write_kernel_key(PKT_public_key *pk) +{ + unsigned char *buffer = NULL; + size_t buffer_len = 0; + struct uasym_hdr hdr = { 0 }; + struct uasym_entry e_algo = { 0 }; + struct uasym_entry e_keyid = { 0 }; + struct uasym_entry e_key_pub = { 0 }; + struct uasym_entry e_key_desc = { 0 }; + __u8 algo; + __u32 keyid[2], _keyid; + __u64 total_len = 0; + /* PGP: */ + char key_desc[4 + 1 + 8 + 1]; + gpg_error_t err; + int ret = 0; + + init_output(); + keyid_from_pk (pk, keyid); + + ret = pgp_to_kernel_algo(pk->pubkey_algo, pk->pkey[0], &algo); + if (ret < 0) + return ret; + + /* algo */ + e_algo.field = __cpu_to_be16(KEY_ALGO); + e_algo.length = __cpu_to_be32(sizeof(algo)); + total_len += sizeof(e_algo) + sizeof(algo); + + /* key id */ + e_keyid.field = __cpu_to_be16(KEY_KID0); + e_keyid.length = __cpu_to_be32(sizeof(*pk->keyid) * 2); + total_len += sizeof(e_keyid) + sizeof(*pk->keyid) * 2; + + /* key desc */ + e_key_desc.field = __cpu_to_be16(KEY_DESC); + e_key_desc.length = __cpu_to_be32(sizeof(key_desc)); + total_len += sizeof(e_key_desc) + sizeof(key_desc); + + snprintf(key_desc, sizeof(key_desc), "PGP: %08x", pk->keyid[1]); + + switch (pk->pubkey_algo) { + case PUBKEY_ALGO_RSA: + case PUBKEY_ALGO_RSA_S: + ret = mpis_to_asn1_sequence(pk->pkey, pubkey_get_npkey(pk->pubkey_algo), + &buffer, &buffer_len); + break; + case PUBKEY_ALGO_ECDSA: + err = gcry_mpi_aprint(GCRYMPI_FMT_USG, &buffer, &buffer_len, pk->pkey[1]); + if (err) + ret = -EINVAL; + break; + default: + ret = -EOPNOTSUPP; + break; + } + + if (ret < 0) + goto out; + + /* key blob */ + e_key_pub.field = __cpu_to_be16(KEY_PUB); + e_key_pub.length = __cpu_to_be32(buffer_len); + total_len += sizeof(e_key_pub) + buffer_len; + + hdr.data_type = TYPE_KEY; + hdr.num_fields = __cpu_to_be16(4); + hdr.total_len = __cpu_to_be64(total_len); + + es_write(listfp, &hdr, sizeof(hdr), NULL); + + es_write(listfp, &e_algo, sizeof(e_algo), NULL); + es_write(listfp, &algo, sizeof(algo), NULL); + + es_write(listfp, &e_keyid, sizeof(e_keyid), NULL); + _keyid = __cpu_to_be32(pk->keyid[0]); + es_write(listfp, &_keyid, sizeof(_keyid), NULL); + _keyid = __cpu_to_be32(pk->keyid[1]); + es_write(listfp, &_keyid, sizeof(_keyid), NULL); + + es_write(listfp, &e_key_pub, sizeof(e_key_pub), NULL); + es_write(listfp, buffer, buffer_len, NULL); + + es_write(listfp, &e_key_desc, sizeof(e_key_desc), NULL); + es_write(listfp, key_desc, sizeof(key_desc), NULL); +out: + xfree(buffer); + return 0; +} diff --git a/g10/conv-packet.h b/g10/conv-packet.h new file mode 100644 index 00000000000..d35acb985fc --- /dev/null +++ b/g10/conv-packet.h @@ -0,0 +1,37 @@ +/* conv-packet.h - header of conv-packet.c + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef G10_CONV_PACKET_H +#define G10_CONV_PACKET_H + +#include "../common/openpgpdefs.h" + +#ifdef UASYM_KEYS_SIGS +int write_kernel_key(PKT_public_key *pk); +#else +static inline int write_kernel_key(PKT_public_key *pk) +{ + (void)pk; + return 0; +} + +#endif /* UASYM_KEYS_SIGS */ +#endif /*G10_CONV_PACKET_H*/ diff --git a/g10/gpg.c b/g10/gpg.c index 6e54aa7636c..410be8ab2ad 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -186,6 +186,7 @@ enum cmd_and_opt_values aPasswd, aServer, aTOFUPolicy, + aConvKernel, oMimemode, oTextmode, @@ -583,6 +584,8 @@ static gpgrt_opt_t opts[] = { ARGPARSE_c (aListSigs, "list-sig", "@"), /* alias */ ARGPARSE_c (aCheckKeys, "check-sig", "@"), /* alias */ ARGPARSE_c (aShowKeys, "show-key", "@"), /* alias */ + ARGPARSE_c (aConvKernel, "conv-kernel", + N_("convert to Linux kernel uasym format")), @@ -2657,6 +2660,7 @@ main (int argc, char **argv) case aCheckKeys: case aListPackets: + case aConvKernel: case aImport: case aFastImport: case aSendKeys: @@ -5381,6 +5385,12 @@ main (int argc, char **argv) log_info (_("WARNING: no command supplied." " Trying to guess what you mean ...\n")); /*FALLTHRU*/ + case aConvKernel: +#ifndef UASYM_KEYS_SIGS + log_error(_("No support for user asymmetric keys and signatures\n")); + exit(1); +#endif + /*FALLTHRU*/ case aListPackets: if( argc > 1 ) wrong_args("[filename]"); @@ -5411,7 +5421,10 @@ main (int argc, char **argv) if( cmd == aListPackets ) { opt.list_packets=1; set_packet_list_mode(1); - } + } else if( cmd == aConvKernel ) { + opt.list_packets=1; + opt.conv_kernel=1; + } rc = proc_packets (ctrl, NULL, a ); if( rc ) { diff --git a/g10/mainproc.c b/g10/mainproc.c index 7dea4972894..edef9907127 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -496,6 +496,16 @@ proc_symkey_enc (CTX c, PACKET *pkt) free_packet (pkt, NULL); } +static void +proc_conv (PACKET *pkt) +{ + switch (pkt->pkttype) + { + case PKT_PUBLIC_KEY: write_kernel_key(pkt->pkt.public_key); break; + default: break; + } + free_packet(pkt, NULL); +} static void proc_pubkey_enc (CTX c, PACKET *pkt) @@ -1652,7 +1662,7 @@ do_proc_packets (CTX c, iobuf_t a) continue; } newpkt = -1; - if (opt.list_packets) + if (opt.list_packets && !opt.conv_kernel) { switch (pkt->pkttype) { @@ -1665,6 +1675,11 @@ do_proc_packets (CTX c, iobuf_t a) default: newpkt = 0; break; } } + else if (opt.conv_kernel) + { + proc_conv(pkt); + newpkt = 0; + } else if (c->sigs_only) { switch (pkt->pkttype) diff --git a/g10/options.h b/g10/options.h index 914c24849f2..08125481511 100644 --- a/g10/options.h +++ b/g10/options.h @@ -26,6 +26,7 @@ #include #include "main.h" #include "packet.h" +#include "conv-packet.h" #include "tofu.h" #include "../common/session-env.h" #include "../common/compliance.h" @@ -91,6 +92,7 @@ struct int list_sigs; /* list signatures */ int no_armor; int list_packets; /* Option --list-packets active. */ + int conv_kernel; /* Option --conv-kernel active. */ int def_cipher_algo; int force_mdc; int disable_mdc; From patchwork Thu Jul 6 14:42:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 699937 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 0665FC001DD for ; Thu, 6 Jul 2023 14:50:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233438AbjGFOt6 (ORCPT ); Thu, 6 Jul 2023 10:49:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36304 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233520AbjGFOtc (ORCPT ); Thu, 6 Jul 2023 10:49:32 -0400 Received: from frasgout12.his.huawei.com (unknown [14.137.139.154]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0F9DC1FD2; Thu, 6 Jul 2023 07:48:58 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.229]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4QxfGZ6Lg9z9xFmp; Thu, 6 Jul 2023 22:36:06 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwAHQg0y06ZkPxkwBA--.58122S14; Thu, 06 Jul 2023 15:48:07 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, song@kernel.org, jolsa@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, rostedt@goodmis.org, mhiramat@kernel.org, mykolal@fb.com, shuah@kernel.org Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, bpf@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, paul@paul-moore.com, linux-security-module@vger.kernel.org, wiktor@metacode.biz, devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org, ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name, antony@vennard.ch, konstantin@linuxfoundation.org, James.Bottomley@HansenPartnership.com, Roberto Sassu Subject: [RFC][GNUPG][PATCH 2/2] Convert PGP signatures to the user asymmetric key signatures format Date: Thu, 6 Jul 2023 16:42:25 +0200 Message-Id: <20230706144225.1046544-13-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> References: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwAHQg0y06ZkPxkwBA--.58122S14 X-Coremail-Antispam: 1UD129KBjvJXoWxtFWUur13Wr4fKFyDAw48Crg_yoW3Gr45pa 4SkF1SvrW5ZFn7KF47Gw4Fqr13JwnYg3WDKFW3C3WS9wnIqrWqqF1jvryIgryrGFZ7KF18 AF4DXFZ7Wr4kAaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPvb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVWxJr0_GcWl84ACjcxK6I8E87Iv67AKxVWxJVW8Jr1l84ACjcxK6I8E87Iv6xkF7I0E 14v26F4UJVW0owAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I 80ewAv7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCj c4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4 kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E 5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWrXV W8Jr1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvE c7CjxVAFwI0_Cr1j6rxdMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67 AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26F4UJVW0obIYCTnIWIevJa73UjIFyTuY vjxUI-eODUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAKBF1jj4-V7gAAsK X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org From: Roberto Sassu Enhance the gpg command --conv-kernel to also support converting PGP signatures to the user asymmetric key signatures format. Signed-off-by: Roberto Sassu --- g10/conv-packet.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++ g10/conv-packet.h | 7 ++ g10/mainproc.c | 1 + 3 files changed, 208 insertions(+) diff --git a/g10/conv-packet.c b/g10/conv-packet.c index 360db30eb8d..d85d5a35002 100644 --- a/g10/conv-packet.c +++ b/g10/conv-packet.c @@ -31,6 +31,8 @@ #include #endif #include +#include +#include #include "gpg.h" #include "../common/util.h" @@ -41,6 +43,16 @@ static estream_t listfp; +static const enum hash_algo pgp_hash_algorithms[DIGEST_ALGO_SHA224 + 1] = { + [DIGEST_ALGO_MD5] = HASH_ALGO_MD5, + [DIGEST_ALGO_SHA1] = HASH_ALGO_SHA1, + [DIGEST_ALGO_RMD160] = HASH_ALGO_RIPE_MD_160, + [DIGEST_ALGO_SHA256] = HASH_ALGO_SHA256, + [DIGEST_ALGO_SHA384] = HASH_ALGO_SHA384, + [DIGEST_ALGO_SHA512] = HASH_ALGO_SHA512, + [DIGEST_ALGO_SHA224] = HASH_ALGO_SHA224, +}; + static void init_output(void) { if (!listfp) @@ -285,3 +297,191 @@ out: xfree(buffer); return 0; } + +/* Taken from sig_check.c */ +static int get_sig_data(PKT_signature * sig, __u8 **buf, __u32 *buf_len) +{ + __u8 *buf_ptr; + + *buf = xmalloc_clear(4 + 2 + sig->hashed->len + 6); + if (!*buf) + return -ENOMEM; + + buf_ptr = *buf; + + if (sig->version >= 4) + *buf_ptr++ = sig->version; + + *buf_ptr++ = sig->sig_class; + if (sig->version < 4) + { + u32 a = sig->timestamp; + *buf_ptr++ = ((a >> 24) & 0xff); + *buf_ptr++ = ((a >> 16) & 0xff); + *buf_ptr++ = ((a >> 8) & 0xff); + *buf_ptr++ = (a & 0xff); + } + else + { + size_t n; + *buf_ptr++ = sig->pubkey_algo; + *buf_ptr++ = sig->digest_algo; + if (sig->hashed) + { + n = sig->hashed->len; + *buf_ptr++ = n >> 8; + *buf_ptr++ = n; + memcpy(buf_ptr, sig->hashed->data, n); + buf_ptr += n; + n += 6; + } + else + { + /* Two octets for the (empty) length of the hashed + * section. */ + *buf_ptr++ = 0; + *buf_ptr++ = 0; + n = 6; + } + /* Add some magic per Section 5.2.4 of RFC 4880. */ + *buf_ptr++ = sig->version; + *buf_ptr++ = 0xff; + *buf_ptr++ = n >> 24; + *buf_ptr++ = n >> 16; + *buf_ptr++ = n >> 8; + *buf_ptr++ = n; + } + + *buf_len = buf_ptr - *buf; + return 0; +} + +int write_kernel_signature(PKT_signature *sig) +{ + unsigned char *buffer = NULL; + size_t buffer_len = 0, buffer_len_padded = 0; + struct uasym_hdr hdr = { 0 }; + struct uasym_entry e_key_algo = { 0 }; + struct uasym_entry e_hash_algo = { 0 }; + struct uasym_entry e_sig_encoding = { 0 }; + struct uasym_entry e_sig_kid0 = { 0 }; + struct uasym_entry e_sig_pub = { 0 }; + struct uasym_entry e_sig_data = { 0 }; + __u8 pkey_algo; + __u8 hash_algo; + __u8 sig_encoding = SIG_ENC_PKCS1; + __u8 *sig_data = NULL; + __u32 _keyid, sig_data_len; + __u64 total_len = 0; + gpg_error_t err; + int ret = 0; + + init_output(); + + ret = pgp_to_kernel_algo(sig->pubkey_algo, NULL, &pkey_algo); + if (ret < 0) + return ret; + + if (pkey_algo == PKEY_ALGO_ECDSA) + sig_encoding = SIG_ENC_X962; + + hash_algo = pgp_hash_algorithms[sig->digest_algo]; + + /* sig key algo */ + e_key_algo.field = __cpu_to_be16(SIG_KEY_ALGO); + e_key_algo.length = __cpu_to_be32(sizeof(pkey_algo)); + total_len += sizeof(e_key_algo) + sizeof(pkey_algo); + + /* sig hash algo */ + e_hash_algo.field = __cpu_to_be16(SIG_HASH_ALGO); + e_hash_algo.length = __cpu_to_be32(sizeof(hash_algo)); + total_len += sizeof(e_hash_algo) + sizeof(hash_algo); + + /* sig encoding */ + e_sig_encoding.field = __cpu_to_be16(SIG_ENC); + e_sig_encoding.length = __cpu_to_be32(sizeof(sig_encoding)); + total_len += sizeof(e_sig_encoding) + sizeof(sig_encoding); + + /* sig kid0 */ + e_sig_kid0.field = __cpu_to_be16(SIG_KID0); + e_sig_kid0.length = __cpu_to_be32(2 * sizeof(*sig->keyid)); + total_len += sizeof(e_sig_kid0) + 2 * sizeof(*sig->keyid); + + /* sig data */ + e_sig_data.field = __cpu_to_be16(SIG_DATA_END); + ret = get_sig_data(sig, &sig_data, &sig_data_len); + if (ret < 0) + goto out; + + e_sig_data.length = __cpu_to_be32(sig_data_len); + total_len += sizeof(e_sig_data) + sig_data_len; + + switch (sig->pubkey_algo) { + case PUBKEY_ALGO_ECDSA: + ret = mpis_to_asn1_sequence(sig->data, 2, &buffer, &buffer_len_padded); + break; + case PUBKEY_ALGO_RSA: + err = gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &buffer_len, sig->data[0]); + if (err) { + ret = -EINVAL; + break; + } + + buffer_len_padded = ((buffer_len + 7) / 8) * 8; + buffer = xmalloc_clear(buffer_len_padded); + if (!buffer) { + ret = -ENOMEM; + break; + } + + err = gcry_mpi_print(GCRYMPI_FMT_USG, + buffer + buffer_len_padded - buffer_len, buffer_len, + &buffer_len, sig->data[0]); + if (err) + ret = -EINVAL; + break; + default: + ret = -EOPNOTSUPP; + break; + } + + if (ret < 0) + goto out; + + /* key blob */ + e_sig_pub.field = __cpu_to_be16(SIG_S); + e_sig_pub.length = __cpu_to_be32(buffer_len_padded); + total_len += sizeof(e_sig_pub) + buffer_len_padded; + + hdr.data_type = TYPE_SIG; + hdr.num_fields = __cpu_to_be16(6); + hdr.total_len = __cpu_to_be64(total_len); + + es_write(listfp, &hdr, sizeof(hdr), NULL); + + es_write(listfp, &e_key_algo, sizeof(e_key_algo), NULL); + es_write(listfp, &pkey_algo, sizeof(pkey_algo), NULL); + + es_write(listfp, &e_hash_algo, sizeof(e_hash_algo), NULL); + es_write(listfp, &hash_algo, sizeof(hash_algo), NULL); + + es_write(listfp, &e_sig_encoding, sizeof(e_sig_encoding), NULL); + es_write(listfp, &sig_encoding, sizeof(sig_encoding), NULL); + + es_write(listfp, &e_sig_kid0, sizeof(e_sig_kid0), NULL); + _keyid = __cpu_to_be32(sig->keyid[0]); + es_write(listfp, &_keyid, sizeof(_keyid), NULL); + _keyid = __cpu_to_be32(sig->keyid[1]); + es_write(listfp, &_keyid, sizeof(_keyid), NULL); + + es_write(listfp, &e_sig_pub, sizeof(e_sig_pub), NULL); + es_write(listfp, buffer, buffer_len_padded, NULL); + + es_write(listfp, &e_sig_data, sizeof(e_sig_data), NULL); + es_write(listfp, sig_data, sig_data_len, NULL); + +out: + xfree(sig_data); + xfree(buffer); + return 0; +} diff --git a/g10/conv-packet.h b/g10/conv-packet.h index d35acb985fc..ef718de0a7a 100644 --- a/g10/conv-packet.h +++ b/g10/conv-packet.h @@ -26,6 +26,7 @@ #ifdef UASYM_KEYS_SIGS int write_kernel_key(PKT_public_key *pk); +int write_kernel_signature(PKT_signature *sig); #else static inline int write_kernel_key(PKT_public_key *pk) { @@ -33,5 +34,11 @@ static inline int write_kernel_key(PKT_public_key *pk) return 0; } +static inline int write_kernel_signature(PKT_signature *sig) +{ + (void)sig; + return 0; +} + #endif /* UASYM_KEYS_SIGS */ #endif /*G10_CONV_PACKET_H*/ diff --git a/g10/mainproc.c b/g10/mainproc.c index edef9907127..1cb08d82000 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -502,6 +502,7 @@ proc_conv (PACKET *pkt) switch (pkt->pkttype) { case PKT_PUBLIC_KEY: write_kernel_key(pkt->pkt.public_key); break; + case PKT_SIGNATURE: write_kernel_signature(pkt->pkt.signature); break; default: break; } free_packet(pkt, NULL); From patchwork Thu Jul 6 14:42:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 700737 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 5E419EB64D9 for ; Thu, 6 Jul 2023 14:46:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233355AbjGFOqU (ORCPT ); Thu, 6 Jul 2023 10:46:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35462 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233389AbjGFOqN (ORCPT ); Thu, 6 Jul 2023 10:46:13 -0400 Received: from frasgout13.his.huawei.com (unknown [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A2EF2173F; Thu, 6 Jul 2023 07:46:04 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.228]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4QxfFN70tgz9xFGd; Thu, 6 Jul 2023 22:35:04 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwAHQg0y06ZkPxkwBA--.58122S5; Thu, 06 Jul 2023 15:45:20 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, song@kernel.org, jolsa@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, rostedt@goodmis.org, mhiramat@kernel.org, mykolal@fb.com, shuah@kernel.org Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, bpf@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, paul@paul-moore.com, linux-security-module@vger.kernel.org, wiktor@metacode.biz, devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org, ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name, antony@vennard.ch, konstantin@linuxfoundation.org, James.Bottomley@HansenPartnership.com, Roberto Sassu Subject: [RFC][PATCH 03/10] KEYS: asymmetric: Introduce a parser for user asymmetric keys and sigs Date: Thu, 6 Jul 2023 16:42:16 +0200 Message-Id: <20230706144225.1046544-4-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> References: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwAHQg0y06ZkPxkwBA--.58122S5 X-Coremail-Antispam: 1UD129KBjvJXoW3tryfGr17ZrWUXw1rGF13XFb_yoWkKrW8pa 4fWry3trZ8twn7CrWfAr47Gr47ur4ruFWagF95CF1SvFs0vr1kCrW8KFy0gFy8Ka48Gry8 J3yYqFyDGw1kJw7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPmb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUWw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x0267AK xVW8Jr0_Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxVAaw2 AFwI0_GFv_Wryl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAq x4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26rWY6r 4UJwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY 1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67 AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4UJVWxJrUvcSsGvfC2KfnxnUUI43ZE Xa7IU04xRDUUUUU== X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAKBF1jj4-V4wABsG X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org From: Roberto Sassu Introduce the common parser for user asymmetric keys and signatures. The data format is TLV-based, and consists of a header and the data. Key and signature blobs can be parsed with the new function uasym_parse(). Each caller of that function should provide a callback function, responsible to parse their fields, and an opaque data pointer to be used by the callback function to store the parsed data. The same data format will be used to store both keys and signatures, albeit with different fields. Signed-off-by: Roberto Sassu --- crypto/asymmetric_keys/Kconfig | 12 ++ crypto/asymmetric_keys/Makefile | 7 + crypto/asymmetric_keys/uasym_parser.c | 201 ++++++++++++++++++++++++++ crypto/asymmetric_keys/uasym_parser.h | 30 ++++ include/uapi/linux/uasym_parser.h | 91 ++++++++++++ 5 files changed, 341 insertions(+) create mode 100644 crypto/asymmetric_keys/uasym_parser.c create mode 100644 crypto/asymmetric_keys/uasym_parser.h create mode 100644 include/uapi/linux/uasym_parser.h diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 1ef3b46d6f6..4f86fe78efd 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -85,4 +85,16 @@ config FIPS_SIGNATURE_SELFTEST depends on ASYMMETRIC_KEY_TYPE depends on PKCS7_MESSAGE_PARSER=X509_CERTIFICATE_PARSER +config UASYM_KEYS_SIGS + tristate "User asymmetric keys and signatures" + depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE + help + This option enables user asymmetric keys and signatures. They are + keys and signatures converted in user space from their native + format (e.g. PGP), to the TLV format (Type-Length-Value) understood + by the kernel. + + Key and signature-specific fields are defined in the UAPI interface, + so that user space converters can reference them. + endif # ASYMMETRIC_KEY_TYPE diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index 0d1fa1b692c..ac3955d834f 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -76,3 +76,10 @@ verify_signed_pefile-y := \ $(obj)/mscode_parser.o: $(obj)/mscode.asn1.h $(obj)/mscode.asn1.h $(obj)/mscode.asn1.o: $(obj)/mscode.asn1.c $(obj)/mscode.asn1.h + +# +# User asymmetric keys and signatures +# +obj-$(CONFIG_UASYM_KEYS_SIGS) += uasym_keys_sigs.o +uasym_keys_sigs-y := \ + uasym_parser.o diff --git a/crypto/asymmetric_keys/uasym_parser.c b/crypto/asymmetric_keys/uasym_parser.c new file mode 100644 index 00000000000..e207f350c40 --- /dev/null +++ b/crypto/asymmetric_keys/uasym_parser.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * Implement the user asymmetric keys and signature parser. + */ + +#define pr_fmt(fmt) "UASYM PARSER: "fmt + +#include "uasym_parser.h" + +const char *data_types_str[] = { + FOR_EACH_DATA_TYPE(GENERATE_STRING) +}; + +const char *fields_str[] = { + FOR_EACH_FIELD(GENERATE_STRING) +}; + +/** + * uasym_parse_hdr - Parse a user asymmetric key or signature header + * @data: Data to parse (updated) + * @data_len: Length of @data (updated) + * @data_type: Data type (updated) + * @num_fields: Data fields (updated) + * @total_len: Length of key or signature, excluding the header (updated) + * + * Parse the header of a user asymmetric key or signature, update the data + * pointer and length, and provide the data type, number of fields and the + * length of that element. + * + * Return: Zero on success, a negative value on error. + */ +int uasym_parse_hdr(const u8 **data, size_t *data_len, u8 *data_type, + u16 *num_fields, u64 *total_len) +{ + struct uasym_hdr *hdr; + + if (*data_len < sizeof(*hdr)) { + pr_debug("Data blob too short, %lu bytes, expected %lu\n", + *data_len, sizeof(*hdr)); + return -EBADMSG; + } + + hdr = (struct uasym_hdr *)*data; + + *data += sizeof(*hdr); + *data_len -= sizeof(*hdr); + + *data_type = hdr->data_type; + if (*data_type >= TYPE__LAST) { + pr_debug("Invalid data type %u\n", *data_type); + return -EBADMSG; + } + + if (hdr->_reserved0 != 0) { + pr_debug("_reserved0 must be zero\n"); + return -EBADMSG; + } + + *num_fields = be16_to_cpu(hdr->num_fields); + if (*num_fields >= FIELD__LAST) { + pr_debug("Too many fields %u, max: %u\n", *num_fields, + FIELD__LAST); + return -EBADMSG; + } + + if (hdr->_reserved1 != 0) { + pr_debug("_reserved1 must be zero\n"); + return -EBADMSG; + } + + *total_len = be64_to_cpu(hdr->total_len); + if (*total_len > *data_len) { + pr_debug("Invalid total length %llu, expected: %lu\n", + *total_len, *data_len); + return -EBADMSG; + } + + pr_debug("Header: type: %s, num fields: %d, total len: %lld\n", + data_types_str[hdr->data_type], *num_fields, *total_len); + + return 0; +} + +/** + * uasym_parse_data - Parse a user asymmetric key or signature data + * @callback: Callback function to call to parse the fields + * @callback_data: Opaque data to supply to the callback function + * @num_fields: Data fields + * @data: Data to parse + * @data_len: Length of @data + * + * Parse the data part of a user asymmetric key or signature and call the + * supplied callback function for each data field, passing also the opaque + * data pointer. + * + * Return: Zero on success, a negative value on error. + */ +int uasym_parse_data(parse_callback callback, void *callback_data, + u16 num_fields, const u8 *data, size_t data_len) +{ + const u8 *data_ptr = data; + struct uasym_entry *entry; + u16 field; + u32 len; + int ret, i; + + for (i = 0; i < num_fields; i++) { + if (data_len < sizeof(*entry)) + return -EBADMSG; + + entry = (struct uasym_entry *)data_ptr; + data_ptr += sizeof(*entry); + data_len -= sizeof(*entry); + + field = be16_to_cpu(entry->field); + len = be32_to_cpu(entry->length); + + if (data_len < len) + return -EBADMSG; + + pr_debug("Data: field: %s, len: %d\n", fields_str[field], len); + + if (!len) + continue; + + ret = callback(callback_data, field, data_ptr, len); + if (ret < 0) { + pr_debug("Parsing of field %s failed, ret: %d\n", + fields_str[field], ret); + return -EBADMSG; + } + + data_ptr += len; + data_len -= len; + } + + if (data_len) { + pr_debug("Excess data: %ld bytes\n", data_len); + return -EBADMSG; + } + + return 0; +} + +/** + * uasym_parse - Parse a user asymmetric key or signature + * @expected_data_type: Desired data type + * @callback: Callback function to call to parse the fields + * @callback_data: Opaque data to supply to the callback function + * @data: Data to parse + * @data_len: Length of @data + * + * Parse a user asymmetric key or signature and call the supplied callback + * function for each data field, passing also the opaque data pointer. + * + * Return: Zero on success, a negative value on error. + */ +int uasym_parse(enum data_types expected_data_type, parse_callback callback, + void *callback_data, const u8 *data, size_t data_len) +{ + u8 data_type; + u16 num_fields; + u64 total_len; + int ret = 0; + + pr_debug("Start parsing data blob, size: %ld, expected data type: %s\n", + data_len, data_types_str[expected_data_type]); + + while (data_len) { + ret = uasym_parse_hdr(&data, &data_len, &data_type, &num_fields, + &total_len); + if (ret < 0) + goto out; + + if (data_type == expected_data_type) + break; + + /* + * uasym_parse_hdr() already checked that total_len <= data_len. + */ + data += total_len; + data_len -= total_len; + } + + if (!data_len) { + pr_debug("Data type %s not found\n", + data_types_str[expected_data_type]); + ret = -ENOENT; + goto out; + } + + ret = uasym_parse_data(callback, callback_data, num_fields, data, + total_len); +out: + pr_debug("End of parsing data blob, ret: %d\n", ret); + return ret; +} diff --git a/crypto/asymmetric_keys/uasym_parser.h b/crypto/asymmetric_keys/uasym_parser.h new file mode 100644 index 00000000000..985dda6aad3 --- /dev/null +++ b/crypto/asymmetric_keys/uasym_parser.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * 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__) + +typedef int (*parse_callback)(void *, enum fields, const u8 *, u32); + +extern const char *data_types_str[]; +extern const char *fields_str[]; + +int uasym_parse_hdr(const u8 **data, size_t *data_len, u8 *data_type, + u16 *num_fields, u64 *total_len); +int uasym_parse_data(parse_callback callback, void *callback_data, + u16 num_fields, const u8 *data, size_t data_len); +int uasym_parse(enum data_types expected_data_type, parse_callback callback, + void *callback_data, const u8 *data, size_t data_len); diff --git a/include/uapi/linux/uasym_parser.h b/include/uapi/linux/uasym_parser.h new file mode 100644 index 00000000000..8f0bc235492 --- /dev/null +++ b/include/uapi/linux/uasym_parser.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH + * + * Author: Roberto Sassu + * + * 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 + +/* + * User asymmmetric key and signature format: + * + * +----------------+-----------------+-----------------+ + * | data type (u8) | num fields (u16)| total len (u64) | + * +--------------+-+----------+------+-----------+-----+ + * | field1 (u16) | len1 (u32) | value1 (u8 len1) | + * +--------------+------------+------------------+ + * | ... | ... | ... | + * +--------------+------------+------------------+ + * | fieldN (u16) | lenN (u32) | valueN (u8 lenN) | + * +--------------+------------+------------------+ + */ + +/** + * struct uasym_hdr - Header of user asymmetric keys and signatures + * @data_type: Type of data to parse + * @_reserved0: Reserved for future use + * @num_fields: Number of fields provided + * @_reserved1: Reserved for future use + * @total_len: Total length of the data blob, excluding the header + * + * This structure represents the header of the user asymmetric keys and + * signatures format. + */ +struct uasym_hdr { + __u8 data_type; + __u8 _reserved0; + __u16 num_fields; + __u32 _reserved1; + __u64 total_len; +} __packed; + +/** + * struct uasym_entry - Data entry of user asymmetric keys and signatures + * @field: Data field identifier + * @length: Data length + * @data: Data + * + * This structure represents a TLV entry of the data part of the user + * asymmetric keys and signatures format. + */ +struct uasym_entry { + __u16 field; + __u32 length; + __u8 data[]; +} __packed; + +#define FOR_EACH_DATA_TYPE(DATA_TYPE) \ + DATA_TYPE(TYPE__LAST) + +#define FOR_EACH_FIELD(FIELD) \ + FIELD(FIELD__LAST) + +#define GENERATE_ENUM(ENUM) ENUM, +#define GENERATE_STRING(STRING) #STRING, + +/** + * enum data_types - Type of data to parse + * + * Enumerates the type of data to parse. + */ +enum data_types { + FOR_EACH_DATA_TYPE(GENERATE_ENUM) +}; + +/** + * enum fields - Data fields + * + * Enumerates the data fields. Some belongs to keys, some to signatures. + */ +enum fields { + FOR_EACH_FIELD(GENERATE_ENUM) +}; + +#endif /* _UAPI_LINUX_UASYM_PARSER_H */ From patchwork Thu Jul 6 14:42:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 699941 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 EA246EB64DD for ; Thu, 6 Jul 2023 14:46:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233394AbjGFOqm (ORCPT ); Thu, 6 Jul 2023 10:46:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35702 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230309AbjGFOq1 (ORCPT ); Thu, 6 Jul 2023 10:46:27 -0400 Received: from frasgout12.his.huawei.com (unknown [14.137.139.154]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE1F01BEF; Thu, 6 Jul 2023 07:46:22 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.229]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4QxfCj66dhz9xFbn; Thu, 6 Jul 2023 22:33:37 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwAHQg0y06ZkPxkwBA--.58122S6; Thu, 06 Jul 2023 15:45:38 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, song@kernel.org, jolsa@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, rostedt@goodmis.org, mhiramat@kernel.org, mykolal@fb.com, shuah@kernel.org Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, bpf@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, paul@paul-moore.com, linux-security-module@vger.kernel.org, wiktor@metacode.biz, devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org, ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name, antony@vennard.ch, konstantin@linuxfoundation.org, James.Bottomley@HansenPartnership.com, Roberto Sassu Subject: [RFC][PATCH 04/10] KEYS: asymmetric: Introduce the user asymmetric key parser Date: Thu, 6 Jul 2023 16:42:17 +0200 Message-Id: <20230706144225.1046544-5-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> References: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwAHQg0y06ZkPxkwBA--.58122S6 X-Coremail-Antispam: 1UD129KBjvJXoWfJrWDXr4UtF1rZr4rtFy7KFg_yoWDWr18pa yrWryUKFW5Kwn2k3y3Ar17Kw12qry8ZFWagFyrAr1ak3sxXr4kGrWI9F4xuFyUtr1kt393 tr4UZFyUKr1DtrDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPGb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVWxJr0_GcWle2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Wr v_Gr1UMIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY 6xkF7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2js IE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnIWIevJa73UjIF yTuYvjxUI-eODUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAKBF1jj4-V4wACsF X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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 | 1 + crypto/asymmetric_keys/Makefile | 3 +- crypto/asymmetric_keys/asymmetric_type.c | 3 +- crypto/asymmetric_keys/uasym_key_parser.c | 229 ++++++++++++++++++++++ crypto/asymmetric_keys/uasym_parser.h | 5 + include/keys/asymmetric-type.h | 1 + include/uapi/linux/uasym_parser.h | 7 + 7 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 crypto/asymmetric_keys/uasym_key_parser.c diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 4f86fe78efd..d4b8f52a126 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -88,6 +88,7 @@ config FIPS_SIGNATURE_SELFTEST config UASYM_KEYS_SIGS tristate "User asymmetric keys and signatures" depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select CRYPTO_PUB_KEY_INFO help This option enables user asymmetric keys and signatures. They are keys and signatures converted in user space from their native diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index ac3955d834f..6708a9e81ed 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_parser.o + uasym_parser.o \ + 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..2de3f9afa64 --- /dev/null +++ b/crypto/asymmetric_keys/uasym_key_parser.c @@ -0,0 +1,229 @@ +// 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 "uasym_parser.h" + +static int parse_key_pub(struct public_key *pub, enum fields field, + const u8 *field_data, u32 field_data_len) +{ + int ret = 0; + + kenter(",%u,%u", 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, u32 field_data_len) +{ + u8 algo; + int ret = 0; + + kenter(",%u,%u", field, field_data_len); + + if (field_data_len != sizeof(u8)) { + pr_debug("Unexpected data length %u, 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, u32 field_data_len) +{ + int ret = 0; + + kenter(",%u,%u", 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, u32 field_data_len) +{ + int ret = 0; + + kenter(",%u,%u", 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, enum fields field, + const u8 *field_data, u32 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: + /* 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 = uasym_parse(TYPE_KEY, key_callback, &cb_s, prep->data, + prep->datalen); + 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 index 985dda6aad3..0f629fb7a9b 100644 --- a/crypto/asymmetric_keys/uasym_parser.h +++ b/crypto/asymmetric_keys/uasym_parser.h @@ -28,3 +28,8 @@ int uasym_parse_data(parse_callback callback, void *callback_data, u16 num_fields, const u8 *data, size_t data_len); int uasym_parse(enum data_types expected_data_type, parse_callback callback, void *callback_data, const u8 *data, size_t data_len); + +int parse_key_algo(const char **pkey_algo, enum fields field, + const u8 *field_data, u32 field_data_len); +int parse_key_kid(struct asymmetric_key_id **id, enum fields field, + const u8 *data, u32 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 index 8f0bc235492..42e0087ac2b 100644 --- a/include/uapi/linux/uasym_parser.h +++ b/include/uapi/linux/uasym_parser.h @@ -62,9 +62,16 @@ struct uasym_entry { } __packed; #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, From patchwork Thu Jul 6 14:42:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 700736 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 B61B2EB64D9 for ; Thu, 6 Jul 2023 14:47:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233376AbjGFOrF (ORCPT ); Thu, 6 Jul 2023 10:47:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35694 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233389AbjGFOqm (ORCPT ); Thu, 6 Jul 2023 10:46:42 -0400 Received: from frasgout13.his.huawei.com (unknown [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C73EF10F5; Thu, 6 Jul 2023 07:46:39 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.228]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4QxfG50r1rz9xFGg; Thu, 6 Jul 2023 22:35:41 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwAHQg0y06ZkPxkwBA--.58122S7; Thu, 06 Jul 2023 15:45:56 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, song@kernel.org, jolsa@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, rostedt@goodmis.org, mhiramat@kernel.org, mykolal@fb.com, shuah@kernel.org Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, bpf@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, paul@paul-moore.com, linux-security-module@vger.kernel.org, wiktor@metacode.biz, devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org, ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name, antony@vennard.ch, konstantin@linuxfoundation.org, James.Bottomley@HansenPartnership.com, Roberto Sassu Subject: [RFC][PATCH 05/10] KEYS: asymmetric: Introduce the user asymmetric key signature parser Date: Thu, 6 Jul 2023 16:42:18 +0200 Message-Id: <20230706144225.1046544-6-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> References: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwAHQg0y06ZkPxkwBA--.58122S7 X-Coremail-Antispam: 1UD129KBjvAXoW3tryfuw13Wr1xZr13Wr1ftFb_yoW8Zr4fGo Z3Wr45Ca1Fqr1qkF43G3WkCw48ZrWDJFWUAw43W3ZrX3Wjq34UtF48Ca47uFWfXw1UGrWf A3W8Ja4xJ3yxtwn3n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUOo7kC6x804xWl14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK 8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF 0E3s1l82xGYIkIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vE j48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_JFI_Gr1l84ACjcxK6xIIjxv20xvEc7CjxV AFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26F4j6r4UJwA2z4x0Y4vEx4A2jsIEc7Cj xVAFwI0_Cr1j6rxdM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F4 0Ex7xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC 6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxV Aaw2AFwI0_GFv_Wryl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2Iq xVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r WY6r4UJwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1I6r4UMIIF0xvE2Ix0cI8I cVCY1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87 Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26F4UJVW0obIYCTnIWIevJa73UjIF yTuYvjxUI-eODUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAKBF1jj4-V4wADsE X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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_parser.h | 8 + crypto/asymmetric_keys/uasym_sig_parser.c | 491 ++++++++++++++++++++++ include/crypto/uasym_keys_sigs.h | 73 ++++ include/uapi/linux/uasym_parser.h | 9 + 7 files changed, 585 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 e7d4ae01cdc..a27a2026fec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3219,6 +3219,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 d4b8f52a126..26080412f82 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 help This option enables user asymmetric keys and signatures. They are keys and signatures converted in user space from their native diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index 6708a9e81ed..cbaadab0c42 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -83,4 +83,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_parser.o \ - uasym_key_parser.o + uasym_key_parser.o \ + uasym_sig_parser.o diff --git a/crypto/asymmetric_keys/uasym_parser.h b/crypto/asymmetric_keys/uasym_parser.h index 0f629fb7a9b..3c009fb1998 100644 --- a/crypto/asymmetric_keys/uasym_parser.h +++ b/crypto/asymmetric_keys/uasym_parser.h @@ -17,6 +17,14 @@ #define kleave(FMT, ...) \ pr_debug("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) +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; +}; + typedef int (*parse_callback)(void *, enum fields, const u8 *, u32); extern const char *data_types_str[]; diff --git a/crypto/asymmetric_keys/uasym_sig_parser.c b/crypto/asymmetric_keys/uasym_sig_parser.c new file mode 100644 index 00000000000..6d8dd182104 --- /dev/null +++ b/crypto/asymmetric_keys/uasym_sig_parser.c @@ -0,0 +1,491 @@ +// 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 + +#include "uasym_parser.h" + +static int parse_sig_s(struct public_key_signature *sig, enum fields field, + const u8 *field_data, u32 field_data_len) +{ + int ret = 0; + + kenter(",%u,%u", 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, + u32 field_data_len) +{ + u8 algo; + int ret = 0; + + kenter(",%u,%u", field, field_data_len); + + if (field_data_len != sizeof(u8)) { + pr_debug("Unexpected data length %u, 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, u32 field_data_len) +{ + u8 enc; + int ret = 0; + + kenter(",%u,%u", field, field_data_len); + + if (field_data_len != sizeof(u8)) { + pr_debug("Unexpected data length %u, 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, + u32 field_data_len) +{ + int ret = 0; + + 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, enum fields field, + const u8 *field_data, u32 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: + /* 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 = uasym_parse(TYPE_SIG, sig_callback, uasym_sig, sig_data, sig_len); + 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) { + if (uasym_sig) { + public_key_signature_free(sig); + kfree(uasym_sig->sig_data); + kfree(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..d594a387766 --- /dev/null +++ b/include/crypto/uasym_keys_sigs.h @@ -0,0 +1,73 @@ +/* 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 +extern struct uasym_sig_message *uasym_sig_parse_message(const u8 *sig_data, + size_t sig_len); +extern int uasym_sig_supply_detached_data(struct uasym_sig_message *uasym_sig, + const void *data, size_t data_len); +extern int uasym_sig_get_content_data(struct uasym_sig_message *uasym_sig, + const void **_data, size_t *_data_len, + size_t *_headerlen); +extern int uasym_sig_get_digest(struct uasym_sig_message *uasym_sig, + const u8 **buf, u32 *len, + enum hash_algo *hash_algo); +extern int uasym_sig_verify_message(struct uasym_sig_message *uasym_sig, + struct key *keyring); +extern 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 42e0087ac2b..b6f59815130 100644 --- a/include/uapi/linux/uasym_parser.h +++ b/include/uapi/linux/uasym_parser.h @@ -63,6 +63,7 @@ struct uasym_entry { #define FOR_EACH_DATA_TYPE(DATA_TYPE) \ DATA_TYPE(TYPE_KEY) \ + DATA_TYPE(TYPE_SIG) \ DATA_TYPE(TYPE__LAST) #define FOR_EACH_FIELD(FIELD) \ @@ -72,6 +73,14 @@ struct uasym_entry { 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 6 14:42:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 699940 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 C8414EB64DC for ; Thu, 6 Jul 2023 14:47:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233487AbjGFOr0 (ORCPT ); Thu, 6 Jul 2023 10:47:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34784 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233270AbjGFOrB (ORCPT ); Thu, 6 Jul 2023 10:47:01 -0400 Received: from frasgout11.his.huawei.com (unknown [14.137.139.23]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 939291FD0; Thu, 6 Jul 2023 07:46:59 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4QxfGN6k7Yz9v7VL; Thu, 6 Jul 2023 22:35:56 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwAHQg0y06ZkPxkwBA--.58122S8; Thu, 06 Jul 2023 15:46:14 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, song@kernel.org, jolsa@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, rostedt@goodmis.org, mhiramat@kernel.org, mykolal@fb.com, shuah@kernel.org Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, bpf@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, paul@paul-moore.com, linux-security-module@vger.kernel.org, wiktor@metacode.biz, devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org, ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name, antony@vennard.ch, konstantin@linuxfoundation.org, James.Bottomley@HansenPartnership.com, Roberto Sassu Subject: [RFC][PATCH 06/10] verification: Add verify_uasym_signature() and verify_uasym_sig_message() Date: Thu, 6 Jul 2023 16:42:19 +0200 Message-Id: <20230706144225.1046544-7-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> References: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwAHQg0y06ZkPxkwBA--.58122S8 X-Coremail-Antispam: 1UD129KBjvJXoW3JFy8CrW3Wr1rurykAF43ZFb_yoWxKFW5pF 9Yqr1rZF98Awn3Aa47Ka1I9w1fWrn5Jw17KasFy3WfZF1vq3ZrGrs0gF1YqrW5C348GFWY 9rZFvFW3KanxAw7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVWxJr0_GcWle2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Wr v_Gr1UMIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY 6xkF7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2js IE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Cr1j6rxdYxBIdaVFxhVjvjDU0xZF pf9x07jIPfQUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAgAKBF1jj4vZ7gAAsB X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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 | 50 ++++++++++++++ 2 files changed, 175 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..818f0ca4e12 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,55 @@ extern int verify_pkcs7_message_sig(const void *data, size_t len, size_t asn1hdrlen), void *ctx); +#ifdef CONFIG_UASYM_KEYS_SIGS +extern 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); +extern 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 6 14:42:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 700735 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 2AFB5EB64DD for ; Thu, 6 Jul 2023 14:47:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233512AbjGFOrp (ORCPT ); Thu, 6 Jul 2023 10:47:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36100 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233471AbjGFOrV (ORCPT ); Thu, 6 Jul 2023 10:47:21 -0400 Received: from frasgout11.his.huawei.com (unknown [14.137.139.23]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 860F61FF5; Thu, 6 Jul 2023 07:47:16 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.228]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4QxfGk6QDFz9v7Vc; Thu, 6 Jul 2023 22:36:14 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwAHQg0y06ZkPxkwBA--.58122S9; Thu, 06 Jul 2023 15:46:32 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, song@kernel.org, jolsa@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, rostedt@goodmis.org, mhiramat@kernel.org, mykolal@fb.com, shuah@kernel.org Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, bpf@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, paul@paul-moore.com, linux-security-module@vger.kernel.org, wiktor@metacode.biz, devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org, ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name, antony@vennard.ch, konstantin@linuxfoundation.org, James.Bottomley@HansenPartnership.com, Roberto Sassu Subject: [RFC][PATCH 07/10] KEYS: asymmetric: Preload user asymmetric keys from a keyring blob Date: Thu, 6 Jul 2023 16:42:20 +0200 Message-Id: <20230706144225.1046544-8-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> References: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwAHQg0y06ZkPxkwBA--.58122S9 X-Coremail-Antispam: 1UD129KBjvJXoWxZw15Kw4fAFy5uF47tF13urg_yoW7Gry5pa yrCrWrtFZ0ywn7C348Cr1Igw43CrW093yYga4Skw1Yv3s0qF4kGrWIgr1rKry5Jr1kKayf A34q9w4jkF1DtrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVWxJr0_GcWle2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Wr v_Gr1UMIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY 6xkF7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2js IE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Cr1j6rxdYxBIdaVFxhVjvjDU0xZF pf9x07jIPfQUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAKBF1jj4-V5wAAsD X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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 | 99 ++++++++++++++++++++++ include/crypto/uasym_keys_sigs.h | 9 ++ 3 files changed, 110 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 cbaadab0c42..2cb4087f867 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -84,4 +84,5 @@ obj-$(CONFIG_UASYM_KEYS_SIGS) += uasym_keys_sigs.o uasym_keys_sigs-y := \ uasym_parser.o \ 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..dfb3e79cf7d --- /dev/null +++ b/crypto/asymmetric_keys/uasym_key_preload.c @@ -0,0 +1,99 @@ +// 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. + */ + +#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; + u8 data_type; + u16 num_fields; + u64 total_len; + int ret; + + kenter(""); + + while (data_ptr < data_end) { + ret = uasym_parse_hdr(&data_ptr, &data_len, &data_type, + &num_fields, &total_len); + 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 uasym_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 d594a387766..7270e38275f 100644 --- a/include/crypto/uasym_keys_sigs.h +++ b/include/crypto/uasym_keys_sigs.h @@ -30,6 +30,9 @@ extern int uasym_sig_get_digest(struct uasym_sig_message *uasym_sig, extern int uasym_sig_verify_message(struct uasym_sig_message *uasym_sig, struct key *keyring); extern 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) @@ -69,5 +72,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 6 14:42:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 699939 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 67152EB64DD for ; Thu, 6 Jul 2023 14:48:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233327AbjGFOsI (ORCPT ); Thu, 6 Jul 2023 10:48:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36110 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233477AbjGFOrq (ORCPT ); Thu, 6 Jul 2023 10:47:46 -0400 Received: from frasgout13.his.huawei.com (unknown [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EAAB92132; Thu, 6 Jul 2023 07:47:34 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.227]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4QxfH727bTz9xFGg; Thu, 6 Jul 2023 22:36:35 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwAHQg0y06ZkPxkwBA--.58122S10; Thu, 06 Jul 2023 15:46:50 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, song@kernel.org, jolsa@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, rostedt@goodmis.org, mhiramat@kernel.org, mykolal@fb.com, shuah@kernel.org Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, bpf@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, paul@paul-moore.com, linux-security-module@vger.kernel.org, wiktor@metacode.biz, devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org, ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name, antony@vennard.ch, konstantin@linuxfoundation.org, James.Bottomley@HansenPartnership.com, Roberto Sassu Subject: [RFC][PATCH 08/10] KEYS: Introduce load_uasym_keyring() Date: Thu, 6 Jul 2023 16:42:21 +0200 Message-Id: <20230706144225.1046544-9-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> References: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwAHQg0y06ZkPxkwBA--.58122S10 X-Coremail-Antispam: 1UD129KBjvJXoWxJF1DtrW5Ww17KFyUGF48JFb_yoWruw1fp3 y0kryrKr4vywn3G3yfCFyjgr43Cr1vkw4Yg3W3Cw15AF1DXrn8ZrsrKF1UKry5Wry5AryF qryIvr4Skw1UtaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVWxJr0_GcWle2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Wr v_Gr1UMIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY 6xkF7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2js IE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Cr1j6rxdYxBIdaVFxhVjvjDU0xZF pf9x07jIPfQUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAKBF1jj4-V5wABsC X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org 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 6 14:42:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 700734 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 6BF34C0015E for ; Thu, 6 Jul 2023 14:48:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233451AbjGFOsh (ORCPT ); Thu, 6 Jul 2023 10:48:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37474 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233501AbjGFOsS (ORCPT ); Thu, 6 Jul 2023 10:48:18 -0400 Received: from frasgout13.his.huawei.com (unknown [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 841F026AA; Thu, 6 Jul 2023 07:47:53 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.228]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4QxfHT2m3Cz9xFGF; Thu, 6 Jul 2023 22:36:53 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwAHQg0y06ZkPxkwBA--.58122S11; Thu, 06 Jul 2023 15:47:08 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, song@kernel.org, jolsa@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, rostedt@goodmis.org, mhiramat@kernel.org, mykolal@fb.com, shuah@kernel.org Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, bpf@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, paul@paul-moore.com, linux-security-module@vger.kernel.org, wiktor@metacode.biz, devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org, ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name, antony@vennard.ch, konstantin@linuxfoundation.org, James.Bottomley@HansenPartnership.com, Roberto Sassu Subject: [RFC][PATCH 09/10] bpf: Introduce bpf_verify_uasym_signature() kfunc Date: Thu, 6 Jul 2023 16:42:22 +0200 Message-Id: <20230706144225.1046544-10-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> References: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwAHQg0y06ZkPxkwBA--.58122S11 X-Coremail-Antispam: 1UD129KBjvJXoWxCw47Cry5XFyxurWrXr45GFg_yoWrWr4UpF W8Kr4Svry8Jrs7Ja48Ja1fZF1rCr4vqw17G3sFy34kAFn5Xr13Z34kKF45G3s0k348trWD ZrWIqw43u3ZrGw7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUCVW8JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Cr0_Gr1UM28EF7xvwVC2z280aVCY1x02 67AKxVWxJr0_GcWle2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Wr v_Gr1UMIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY 6xkF7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2js IE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Cr1j6rxdYxBIdaVFxhVjvjDU0xZF pf9x07jIPfQUUUUU= X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAKBF1jj4-V5wACsB X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org From: Roberto Sassu Introduce the bpf_verify_uasym_signature() kfunc, to verify user asymmetric key signatures. The parameters and usage are the same as for bpf_verify_pkcs7_signature(). Signed-off-by: Roberto Sassu --- kernel/trace/bpf_trace.c | 68 +++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 5f2dcabad20..476b6d526de 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1281,7 +1281,7 @@ __bpf_kfunc struct bpf_key *bpf_lookup_user_key(u32 serial, u64 flags) * The key pointer is marked as invalid, to prevent bpf_key_put() from * attempting to decrement the key reference count on that pointer. The key * pointer set in such way is currently understood only by - * verify_pkcs7_signature(). + * verify_pkcs7_signature() and verify_uasym_signature(). * * Set *id* to one of the values defined in include/linux/verification.h: * 0 for the primary keyring (immutable keyring of system keys); @@ -1327,6 +1327,25 @@ __bpf_kfunc void bpf_key_put(struct bpf_key *bkey) } #ifdef CONFIG_SYSTEM_DATA_VERIFICATION +static int validate_key(struct bpf_key *trusted_keyring) +{ + int ret = 0; + + if (trusted_keyring->has_ref) { + /* + * Do the permission check deferred in bpf_lookup_user_key(). + * See bpf_lookup_user_key() for more details. + * + * A call to key_task_permission() here would be redundant, as + * it is already done by keyring_search() called by + * find_asymmetric_key(). + */ + ret = key_validate(trusted_keyring->key); + } + + return ret; +} + /** * bpf_verify_pkcs7_signature - verify a PKCS#7 signature * @data_ptr: data to verify @@ -1344,19 +1363,9 @@ __bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr_kern *data_ptr, { int ret; - if (trusted_keyring->has_ref) { - /* - * Do the permission check deferred in bpf_lookup_user_key(). - * See bpf_lookup_user_key() for more details. - * - * A call to key_task_permission() here would be redundant, as - * it is already done by keyring_search() called by - * find_asymmetric_key(). - */ - ret = key_validate(trusted_keyring->key); - if (ret < 0) - return ret; - } + ret = validate_key(trusted_keyring); + if (ret < 0) + return ret; return verify_pkcs7_signature(data_ptr->data, __bpf_dynptr_size(data_ptr), @@ -1366,6 +1375,36 @@ __bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr_kern *data_ptr, VERIFYING_UNSPECIFIED_SIGNATURE, NULL, NULL); } + +/** + * bpf_verify_uasym_signature - Verify a user asymmetric key signature + * @data_ptr: Data to verify + * @sig_ptr: Signature of the data + * @trusted_keyring: Keyring with keys trusted for signature verification + * + * Verify the user asymmetric key signature *sig_ptr* against the supplied + * *data_ptr* with keys in a keyring referenced by *trusted_keyring*. + * + * Return: 0 on success, a negative value on error. + */ +__bpf_kfunc int bpf_verify_uasym_signature(struct bpf_dynptr_kern *data_ptr, + struct bpf_dynptr_kern *sig_ptr, + struct bpf_key *trusted_keyring) +{ + int ret; + + ret = validate_key(trusted_keyring); + if (ret < 0) + return ret; + + return verify_uasym_signature(data_ptr->data, + __bpf_dynptr_size(data_ptr), + sig_ptr->data, + __bpf_dynptr_size(sig_ptr), + trusted_keyring->key, + VERIFYING_UNSPECIFIED_SIGNATURE, NULL, + NULL); +} #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */ __diag_pop(); @@ -1376,6 +1415,7 @@ BTF_ID_FLAGS(func, bpf_lookup_system_key, KF_ACQUIRE | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_key_put, KF_RELEASE) #ifdef CONFIG_SYSTEM_DATA_VERIFICATION BTF_ID_FLAGS(func, bpf_verify_pkcs7_signature, KF_SLEEPABLE) +BTF_ID_FLAGS(func, bpf_verify_uasym_signature, KF_SLEEPABLE) #endif BTF_SET8_END(key_sig_kfunc_set) From patchwork Thu Jul 6 14:42:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roberto Sassu X-Patchwork-Id: 699938 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 EF5F8C0015E for ; Thu, 6 Jul 2023 14:49:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233445AbjGFOtH (ORCPT ); Thu, 6 Jul 2023 10:49:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36070 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233491AbjGFOsj (ORCPT ); Thu, 6 Jul 2023 10:48:39 -0400 Received: from frasgout13.his.huawei.com (unknown [14.137.139.46]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A7A0C2125; Thu, 6 Jul 2023 07:48:13 -0700 (PDT) Received: from mail02.huawei.com (unknown [172.18.147.229]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4QxfHq32sWz9xFGP; Thu, 6 Jul 2023 22:37:11 +0800 (CST) Received: from huaweicloud.com (unknown [10.204.63.22]) by APP1 (Coremail) with SMTP id LxC2BwAHQg0y06ZkPxkwBA--.58122S12; Thu, 06 Jul 2023 15:47:26 +0100 (CET) From: Roberto Sassu To: dhowells@redhat.com, dwmw2@infradead.org, herbert@gondor.apana.org.au, davem@davemloft.net, jarkko@kernel.org, song@kernel.org, jolsa@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, sdf@google.com, haoluo@google.com, rostedt@goodmis.org, mhiramat@kernel.org, mykolal@fb.com, shuah@kernel.org Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org, linux-crypto@vger.kernel.org, bpf@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, pbrobinson@gmail.com, zbyszek@in.waw.pl, zohar@linux.ibm.com, linux-integrity@vger.kernel.org, paul@paul-moore.com, linux-security-module@vger.kernel.org, wiktor@metacode.biz, devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org, ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name, antony@vennard.ch, konstantin@linuxfoundation.org, James.Bottomley@HansenPartnership.com, Roberto Sassu Subject: [RFC][PATCH 10/10] selftests/bpf: Prepare a test for user asymmetric key signatures Date: Thu, 6 Jul 2023 16:42:23 +0200 Message-Id: <20230706144225.1046544-11-roberto.sassu@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> References: <20230706144225.1046544-1-roberto.sassu@huaweicloud.com> MIME-Version: 1.0 X-CM-TRANSID: LxC2BwAHQg0y06ZkPxkwBA--.58122S12 X-Coremail-Antispam: 1UD129KBjvAXoWfGF4furWUCw1xZw4UurW8Crg_yoW8GF4rCo Z3K3y7K3W5Kr1UCw17XFyUCFWfury8K3s8Zws0v3ZFq3W7KryUAr4kGw1fX34agw4F9rWr WFn3A3WkZ397trn8n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUOo7kC6x804xWl14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK 8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF 0E3s1l82xGYIkIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vE j48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Gr0_Xr1l84ACjcxK6xIIjxv20xvEc7CjxV AFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26F4j6r4UJwA2z4x0Y4vEx4A2jsIEc7Cj xVAFwI0_Cr1j6rxdM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F4 0Ex7xfMcIj6xIIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC 6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxV Aaw2AFwI0_GFv_Wryl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2Iq xVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r WY6r4UJwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r4j6ryUMIIF0xvE2Ix0cI8I cVCY1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87 Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26F4UJVW0obIYCTnIWIevJa73UjIF yTuYvjxUI-eODUUUU X-CM-SenderInfo: purev21wro2thvvxqx5xdzvxpfor3voofrz/1tbiAQAKBF1jj4-V5wAHsE X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org From: Roberto Sassu Reuse the existing test for PKCS#7 signatures, to test also user asymmetric key signatures. Run the new test only if gpg supports the new command --conv-kernel. Signed-off-by: Roberto Sassu --- ...y_pkcs7_sig.c => verify_pkcs7_uasym_sig.c} | 159 +++++++++++++++--- ...s7_sig.c => test_verify_pkcs7_uasym_sig.c} | 18 +- .../testing/selftests/bpf/verify_sig_setup.sh | 82 ++++++++- 3 files changed, 226 insertions(+), 33 deletions(-) rename tools/testing/selftests/bpf/prog_tests/{verify_pkcs7_sig.c => verify_pkcs7_uasym_sig.c} (69%) rename tools/testing/selftests/bpf/progs/{test_verify_pkcs7_sig.c => test_verify_pkcs7_uasym_sig.c} (82%) diff --git a/tools/testing/selftests/bpf/prog_tests/verify_pkcs7_sig.c b/tools/testing/selftests/bpf/prog_tests/verify_pkcs7_uasym_sig.c similarity index 69% rename from tools/testing/selftests/bpf/prog_tests/verify_pkcs7_sig.c rename to tools/testing/selftests/bpf/prog_tests/verify_pkcs7_uasym_sig.c index dd7f2bc7004..89664351d98 100644 --- a/tools/testing/selftests/bpf/prog_tests/verify_pkcs7_sig.c +++ b/tools/testing/selftests/bpf/prog_tests/verify_pkcs7_uasym_sig.c @@ -18,7 +18,7 @@ #include #include -#include "test_verify_pkcs7_sig.skel.h" +#include "test_verify_pkcs7_uasym_sig.skel.h" #define MAX_DATA_SIZE (1024 * 1024) #define MAX_SIG_SIZE 1024 @@ -29,6 +29,24 @@ /* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */ #define MODULE_SIG_STRING "~Module signature appended~\n" +#define PKEY_ID_PGP 0 +#define PKEY_ID_X509 1 +#define PKEY_ID_PKCS7 2 + +static char *key_types_str[PKEY_ID_PKCS7 + 1] = { + [PKEY_ID_PGP] = "pgp", + [PKEY_ID_X509] = "x509", + [PKEY_ID_PKCS7] = "pkcs7", +}; + +enum algos { ALGO_RSA, ALGO_ECDSA_P256, ALGO_ECDSA_P384, ALGO__LAST }; + +static char *algos_str[ALGO_ECDSA_P384 + 1] = { + [ALGO_RSA] = "rsa", + [ALGO_ECDSA_P256] = "ecdsa_p256", + [ALGO_ECDSA_P384] = "ecdsa_p384", +}; + /* * Module signature information block. * @@ -74,13 +92,15 @@ static int libbpf_print_cb(enum libbpf_print_level level, const char *fmt, return 0; } -static int _run_setup_process(const char *setup_dir, const char *cmd) +static int _run_setup_process(const char *setup_dir, const char *cmd, + __u8 key_type, __u8 pkey_algo) { int child_pid, child_status; child_pid = fork(); if (child_pid == 0) { - execlp("./verify_sig_setup.sh", "./verify_sig_setup.sh", cmd, + execlp("./verify_sig_setup.sh", "./verify_sig_setup.sh", + cmd, key_types_str[key_type], algos_str[pkey_algo] ?: "", setup_dir, NULL); exit(errno); @@ -92,11 +112,13 @@ static int _run_setup_process(const char *setup_dir, const char *cmd) return -EINVAL; } -static int populate_data_item_str(const char *tmp_dir, struct data *data_item) +static int populate_data_item_str(const char *tmp_dir, __u8 key_type, + struct data *data_item) { struct stat st; char data_template[] = "/tmp/dataXXXXXX"; char path[PATH_MAX]; + char path_out[PATH_MAX]; int ret, fd, child_status, child_pid; data_item->data_len = 4; @@ -123,10 +145,26 @@ static int populate_data_item_str(const char *tmp_dir, struct data *data_item) } if (child_pid == 0) { - snprintf(path, sizeof(path), "%s/signing_key.pem", tmp_dir); - - return execlp("./sign-file", "./sign-file", "-d", "sha256", - path, path, data_template, NULL); + if (key_type == PKEY_ID_PKCS7) { + snprintf(path, sizeof(path), "%s/signing_key.pem", + tmp_dir); + + return execlp("./sign-file", "./sign-file", "-d", + "sha256", path, path, data_template, + NULL); + } else { + snprintf(path, sizeof(path), "%s.gpg", data_template); + + return execlp("gpg", "gpg", "--no-options", + "--no-auto-check-trustdb", + "--no-permission-warning", + "--default-key", "eBPF_UASYM_Test", + "--sign", "-o", path, "--batch", "--yes", + "--compress-algo=none", "-b", + "--passphrase", "abc", + "--pinentry-mode", "loopback", "-q", + data_template, NULL); + } } waitpid(child_pid, &child_status, 0); @@ -135,7 +173,35 @@ static int populate_data_item_str(const char *tmp_dir, struct data *data_item) if (ret) goto out; - snprintf(path, sizeof(path), "%s.p7s", data_template); + if (key_type != PKEY_ID_PKCS7) { + child_pid = fork(); + + if (child_pid == -1) { + ret = -errno; + goto out; + } + + if (child_pid == 0) { + snprintf(path, sizeof(path), "%s.gpg", data_template); + snprintf(path_out, sizeof(path), "%s.kernel", + data_template); + + return execlp("gpg", "gpg", "--no-keyring", + "--conv-kernel", "-o", path_out, path, + NULL); + } + + waitpid(child_pid, &child_status, 0); + + ret = WEXITSTATUS(child_status); + if (ret) + goto out; + } + + if (key_type == PKEY_ID_PKCS7) + snprintf(path, sizeof(path), "%s.p7s", data_template); + else + snprintf(path, sizeof(path), "%s.kernel", data_template); ret = stat(path, &st); if (ret == -1) { @@ -254,12 +320,12 @@ static int populate_data_item_mod(struct data *data_item) return ret; } -void test_verify_pkcs7_sig(void) +static void test_verify_pkcs7_uasym_sig(__u8 key_type, __u8 pkey_algo) { libbpf_print_fn_t old_print_cb; char tmp_dir_template[] = "/tmp/verify_sigXXXXXX"; char *tmp_dir; - struct test_verify_pkcs7_sig *skel = NULL; + struct test_verify_pkcs7_uasym_sig *skel = NULL; struct bpf_map *map; struct data data; int ret, zero = 0; @@ -272,37 +338,38 @@ void test_verify_pkcs7_sig(void) if (!ASSERT_OK_PTR(tmp_dir, "mkdtemp")) return; - ret = _run_setup_process(tmp_dir, "setup"); + ret = _run_setup_process(tmp_dir, "setup", key_type, pkey_algo); if (!ASSERT_OK(ret, "_run_setup_process")) goto close_prog; - skel = test_verify_pkcs7_sig__open(); - if (!ASSERT_OK_PTR(skel, "test_verify_pkcs7_sig__open")) + skel = test_verify_pkcs7_uasym_sig__open(); + if (!ASSERT_OK_PTR(skel, "test_verify_pkcs7_uasym_sig__open")) goto close_prog; old_print_cb = libbpf_set_print(libbpf_print_cb); - ret = test_verify_pkcs7_sig__load(skel); + ret = test_verify_pkcs7_uasym_sig__load(skel); libbpf_set_print(old_print_cb); if (ret < 0 && kfunc_not_supported) { printf( - "%s:SKIP:bpf_verify_pkcs7_signature() kfunc not supported\n", + "%s:SKIP:bpf_verify_*_signature() kfunc not supported\n", __func__); test__skip(); goto close_prog; } - if (!ASSERT_OK(ret, "test_verify_pkcs7_sig__load")) + if (!ASSERT_OK(ret, "test_verify_pkcs7_uasym_sig__load")) goto close_prog; - ret = test_verify_pkcs7_sig__attach(skel); - if (!ASSERT_OK(ret, "test_verify_pkcs7_sig__attach")) + ret = test_verify_pkcs7_uasym_sig__attach(skel); + if (!ASSERT_OK(ret, "test_verify_pkcs7_uasym_sig__attach")) goto close_prog; map = bpf_object__find_map_by_name(skel->obj, "data_input"); if (!ASSERT_OK_PTR(map, "data_input not found")) goto close_prog; + skel->bss->key_type = key_type; skel->bss->monitored_pid = getpid(); /* Test without data and signature. */ @@ -313,7 +380,7 @@ void test_verify_pkcs7_sig(void) goto close_prog; /* Test successful signature verification with session keyring. */ - ret = populate_data_item_str(tmp_dir, &data); + ret = populate_data_item_str(tmp_dir, key_type, &data); if (!ASSERT_OK(ret, "populate_data_item_str")) goto close_prog; @@ -363,9 +430,13 @@ void test_verify_pkcs7_sig(void) if (!ASSERT_LT(ret, 0, "bpf_map_update_elem data_input")) goto close_prog; - ret = populate_data_item_mod(&data); - if (!ASSERT_OK(ret, "populate_data_item_mod")) - goto close_prog; + data.data_len = 0; + + if (key_type == PKEY_ID_PKCS7) { + ret = populate_data_item_mod(&data); + if (!ASSERT_OK(ret, "populate_data_item_mod")) + goto close_prog; + } /* Test signature verification with system keyrings. */ if (data.data_len) { @@ -392,11 +463,49 @@ void test_verify_pkcs7_sig(void) } close_prog: - _run_setup_process(tmp_dir, "cleanup"); + _run_setup_process(tmp_dir, "cleanup", key_type, pkey_algo); if (!skel) return; skel->bss->monitored_pid = 0; - test_verify_pkcs7_sig__destroy(skel); + test_verify_pkcs7_uasym_sig__destroy(skel); +} + +static bool gpg_conv_kernel_supported(void) +{ + bool supported = false; + char line[1024]; + FILE *fp; + + fp = popen("gpg --conv-kernel /dev/null 2>&1", "r"); + if (!fp) + return false; + + while (fgets(line, sizeof(line), fp)) { + if (strstr(line, "gpg: processing message failed: Unknown system error")) { + supported = true; + break; + } + } + + pclose(fp); + return supported; +} + +void test_verify_pkcs7_sig(void) +{ + test_verify_pkcs7_uasym_sig(PKEY_ID_PKCS7, ALGO__LAST); +} + +void test_verify_uasym_sig(void) +{ + int i; + + /* This test requires support for the new gpg command --conv-kernel. */ + if (!gpg_conv_kernel_supported()) + return; + + for (i = 0; i < ALGO__LAST; i++) + test_verify_pkcs7_uasym_sig(PKEY_ID_PGP, i); } diff --git a/tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c b/tools/testing/selftests/bpf/progs/test_verify_pkcs7_uasym_sig.c similarity index 82% rename from tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c rename to tools/testing/selftests/bpf/progs/test_verify_pkcs7_uasym_sig.c index 7748cc23de8..f25a023b5bb 100644 --- a/tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c +++ b/tools/testing/selftests/bpf/progs/test_verify_pkcs7_uasym_sig.c @@ -20,10 +20,14 @@ extern void bpf_key_put(struct bpf_key *key) __ksym; extern int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_ptr, struct bpf_dynptr *sig_ptr, struct bpf_key *trusted_keyring) __ksym; +extern int bpf_verify_uasym_signature(struct bpf_dynptr *data_ptr, + struct bpf_dynptr *sig_ptr, + struct bpf_key *trusted_keyring) __ksym; __u32 monitored_pid; __u32 user_keyring_serial; __u64 system_keyring_id; +__u8 key_type; struct data { __u8 data[MAX_DATA_SIZE]; @@ -86,7 +90,19 @@ int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size) if (!trusted_keyring) return -ENOENT; - ret = bpf_verify_pkcs7_signature(&data_ptr, &sig_ptr, trusted_keyring); + switch (key_type) { + case PKEY_ID_PKCS7: + ret = bpf_verify_pkcs7_signature(&data_ptr, &sig_ptr, + trusted_keyring); + break; + case PKEY_ID_PGP: + ret = bpf_verify_uasym_signature(&data_ptr, &sig_ptr, + trusted_keyring); + break; + default: + ret = -EOPNOTSUPP; + break; + } bpf_key_put(trusted_keyring); diff --git a/tools/testing/selftests/bpf/verify_sig_setup.sh b/tools/testing/selftests/bpf/verify_sig_setup.sh index ba08922b4a2..90770ae9e12 100755 --- a/tools/testing/selftests/bpf/verify_sig_setup.sh +++ b/tools/testing/selftests/bpf/verify_sig_setup.sh @@ -26,13 +26,39 @@ subjectKeyIdentifier=hash authorityKeyIdentifier=keyid " +gpg_genkey_content_common="\ + Name-Real: eBPF_UASYM_Test + Name-Comment: eBPF_UASYM_Test + Name-Email: ebpf_uasym_test@localhost + Expire-Date: 0 + Passphrase: abc + %commit +" +gpg_genkey_content_rsa="\ + Key-Type: RSA + Key-Length: 4096 + $gpg_genkey_content_common +" + +gpg_genkey_content_ecdsa_p256="\ + Key-Type: ECDSA + Key-Curve: NIST P-256 + $gpg_genkey_content_common +" + +gpg_genkey_content_ecdsa_p384="\ + Key-Type: ECDSA + Key-Curve: NIST P-384 + $gpg_genkey_content_common +" + usage() { - echo "Usage: $0 " + echo "Usage: $0 " exit 1 } -setup() +setup_pkcs7() { local tmp_dir="$1" @@ -52,11 +78,37 @@ setup() keyctl link $key_id $keyring_id } -cleanup() { +setup_pgp() +{ + local tmp_dir="$1" + local varname="gpg_genkey_content_$2" + + modprobe ecdsa_generic + + echo "${!varname}" > ${tmp_dir}/gpg.genkey + gpg --batch --generate-key ${tmp_dir}/gpg.genkey + + key_id=$(gpg --export eBPF_UASYM_Test | gpg --conv-kernel | keyctl padd asymmetric ebpf_testing_key @s) + keyring_id=$(keyctl newring ebpf_testing_keyring @s) + keyctl link $key_id $keyring_id +} + +cleanup_pkcs7() { + local tmp_dir="$1" + + keyctl unlink $(keyctl search @s asymmetric ebpf_testing_key) @s + keyctl unlink $(keyctl search @s keyring ebpf_testing_keyring) @s + rm -rf ${tmp_dir} +} + +cleanup_pgp() { local tmp_dir="$1" keyctl unlink $(keyctl search @s asymmetric ebpf_testing_key) @s keyctl unlink $(keyctl search @s keyring ebpf_testing_keyring) @s + key_fingerprint=$(gpg --fingerprint --with-colons eBPF_UASYM_Test | awk -F ":" '$1 == "fpr" {print $(NF-1)}') + gpg --delete-secret-key --batch --yes $key_fingerprint + gpg --delete-key --batch --yes $key_fingerprint rm -rf ${tmp_dir} } @@ -75,17 +127,33 @@ catch() main() { - [[ $# -ne 2 ]] && usage + [[ $# -ne 4 ]] && usage local action="$1" - local tmp_dir="$2" + local key_type="$2" + local key_algo="$3" + local tmp_dir="$4" [[ ! -d "${tmp_dir}" ]] && echo "Directory ${tmp_dir} doesn't exist" && exit 1 if [[ "${action}" == "setup" ]]; then - setup "${tmp_dir}" + if [[ "${key_type}" == "pkcs7" ]]; then + setup_pkcs7 "${tmp_dir}" + elif [[ "${key_type}" == "pgp" ]]; then + setup_pgp "${tmp_dir}" "${key_algo}" + else + echo "Unknown key type: ${key_type}" + exit 1 + fi elif [[ "${action}" == "cleanup" ]]; then - cleanup "${tmp_dir}" + if [[ "${key_type}" == "pkcs7" ]]; then + cleanup_pkcs7 "${tmp_dir}" + elif [[ "${key_type}" == "pgp" ]]; then + cleanup_pgp "${tmp_dir}" + else + echo "Unknown key type: ${key_type}" + exit 1 + fi else echo "Unknown action: ${action}" exit 1