From nobody Mon Feb 9 02:08:18 2026 Received: from frasgout12.his.huawei.com (frasgout12.his.huawei.com [14.137.139.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4CDF5134CC6; Fri, 16 Feb 2024 15:25:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.154 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097140; cv=none; b=t2zA4/jMj8puWrC3OGoO1OFJYJsBk0mD1W6RJXo5G3KFxpC/zLVH7kju9ZWu6ysF8HmeKsEf6XFj4AhjiUwrhakNwuf1eRV7y8ODSPNbeZe2trAfkOuUcku6aRnieOWkHSlsmBlDFyczuR6WIzXvUbPiUUiBf3fvVlu/KZRDNyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097140; c=relaxed/simple; bh=yBLUhpeAUzPAqo16EKBu9cOxlJA9biOKiyVYJXyBxSE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=WYiDEb0NJ7k2hzI1IYnGOlgul1ZpEHgWgqJRA+c4X+FKQa0SX4XQhu18u07Si4vDgsdhydDq9x0JRahOdJ158SkpDs1qljeocAC75iKKAKbD/yZ8u5HV137C5jrynUPPdWIkA+dULhHBdSQgkj5oCirTIamebsZaM7t3UVbx2bY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.154 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.51]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4TbwHh2Gb4z9xsyV; Fri, 16 Feb 2024 23:06:24 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 9E75A1405A2; Fri, 16 Feb 2024 23:25:25 +0800 (CST) Received: from huaweicloud.com (unknown [10.48.131.30]) by APP2 (Coremail) with SMTP id GxC2BwAHQCRBfs9lTLSaAg--.11044S3; Fri, 16 Feb 2024 16:25:24 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?UTF-8?B?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , David Howells , Petr Tesarik Subject: [RFC 1/8] mpi: Introduce mpi_key_length() Date: Fri, 16 Feb 2024 16:24:28 +0100 Message-Id: <20240216152435.1575-2-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240216152435.1575-1-petrtesarik@huaweicloud.com> References: <20240216152435.1575-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwAHQCRBfs9lTLSaAg--.11044S3 X-Coremail-Antispam: 1UD129KBjvJXoW7WrWUJFyUAr47KFWUuF4kZwb_yoW8KF4fpF 4Ykw45JrWkJr1SkFyfC3Z5G3W5G3WvgF1UKrZrJw17J39xCrnxWFZ7C34Yva18Gr1xAF1U X3y3WFZ5Crn5ZaDanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmI14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jr4l82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UM2 8EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E14v26r4UJVWxJr1l e2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI 8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwAC jcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lFIxGxcIEc7CjxVA2Y2ka0x kIwI1lc7CjxVAaw2AFwI0_GFv_Wryl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_ Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1V AY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF 0xvE2Ix0cI8IcVCY1x0267AKxVWxJVW8Jr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMI IF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr1j6F4UJbIYCTnI WIevJa73UjIFyTuYvjTRMfOzDUUUU X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Introduce the new function to get the number of bits and bytes from an MPI. Signed-off-by: Roberto Sassu --- include/linux/mpi.h | 2 ++ lib/crypto/mpi/mpicoder.c | 33 ++++++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/include/linux/mpi.h b/include/linux/mpi.h index eb0d1c1db208..a7dd4c9d8120 100644 --- a/include/linux/mpi.h +++ b/include/linux/mpi.h @@ -90,6 +90,8 @@ enum gcry_mpi_format { }; =20 MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes); +int mpi_key_length(const void *xbuffer, unsigned int ret_nread, + unsigned int *nbits_arg, unsigned int *nbytes_arg); MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread); int mpi_fromstr(MPI val, const char *str); MPI mpi_scanval(const char *string); diff --git a/lib/crypto/mpi/mpicoder.c b/lib/crypto/mpi/mpicoder.c index 3cb6bd148fa9..92447a1c8bf9 100644 --- a/lib/crypto/mpi/mpicoder.c +++ b/lib/crypto/mpi/mpicoder.c @@ -79,22 +79,41 @@ MPI mpi_read_raw_data(const void *xbuffer, size_t nbyte= s) } EXPORT_SYMBOL_GPL(mpi_read_raw_data); =20 -MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) +int mpi_key_length(const void *xbuffer, unsigned int ret_nread, + unsigned int *nbits_arg, unsigned int *nbytes_arg) { const uint8_t *buffer =3D xbuffer; - unsigned int nbits, nbytes; - MPI val; + unsigned int nbits; =20 - if (*ret_nread < 2) - return ERR_PTR(-EINVAL); + if (ret_nread < 2) + return -EINVAL; nbits =3D buffer[0] << 8 | buffer[1]; =20 if (nbits > MAX_EXTERN_MPI_BITS) { pr_info("MPI: mpi too large (%u bits)\n", nbits); - return ERR_PTR(-EINVAL); + return -EINVAL; } =20 - nbytes =3D DIV_ROUND_UP(nbits, 8); + if (nbits_arg) + *nbits_arg =3D nbits; + if (nbytes_arg) + *nbytes_arg =3D DIV_ROUND_UP(nbits, 8); + + return 0; +} +EXPORT_SYMBOL_GPL(mpi_key_length); + +MPI mpi_read_from_buffer(const void *xbuffer, unsigned int *ret_nread) +{ + const uint8_t *buffer =3D xbuffer; + unsigned int nbytes; + MPI val; + int ret; + + ret =3D mpi_key_length(xbuffer, *ret_nread, NULL, &nbytes); + if (ret < 0) + return ERR_PTR(ret); + if (nbytes + 2 > *ret_nread) { pr_info("MPI: mpi larger than buffer nbytes=3D%u ret_nread=3D%u\n", nbytes, *ret_nread); --=20 2.34.1 From nobody Mon Feb 9 02:08:18 2026 Received: from frasgout12.his.huawei.com (frasgout12.his.huawei.com [14.137.139.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8A91A1350C0; Fri, 16 Feb 2024 15:25:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.154 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097158; cv=none; b=r9TxpsZv6NM//pV0l6/TMOBkBwh6iPopN7zwIhusO+a48woCOo9Ny4LF2pajK6CWnuNnbC1zei8iKT6bck43gEuK0vKkD2YC6rPZHB5BCXCpJlo5+nkCjQLG5pq9o7CYH5KrmZrsLdSff08bLws+WS40+XRXQej9sq6AU9C5yY0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097158; c=relaxed/simple; bh=A2BcJYDl5tONmMZ4A16bYcljQ/ecPCjaz0WFAl8YME4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=FD2PF2EWxAzg+tHINHuVfuWOe609eqUP6fKwfp43zsr6Ees1rKxiVMU/WSKelBsJbqd/FpAhyg92AE+TYOfv5svO4t3YR+xroEfsE58D9wfl7VXD/3rrYHPZl8VO3V8eKz5yxHNEaIe67beUsOi3wWPiGK0dnKpObR+7qapwyZc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.154 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.51]) by frasgout12.his.huawei.com (SkyGuard) with ESMTP id 4TbwJ31Gg8z9xtVJ; Fri, 16 Feb 2024 23:06:43 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 0AFDF1408C5; Fri, 16 Feb 2024 23:25:42 +0800 (CST) Received: from huaweicloud.com (unknown [10.48.131.30]) by APP2 (Coremail) with SMTP id GxC2BwAHQCRBfs9lTLSaAg--.11044S4; Fri, 16 Feb 2024 16:25:41 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?UTF-8?B?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , David Howells , Petr Tesarik Subject: [RFC 2/8] rsa: add parser of raw format Date: Fri, 16 Feb 2024 16:24:29 +0100 Message-Id: <20240216152435.1575-3-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240216152435.1575-1-petrtesarik@huaweicloud.com> References: <20240216152435.1575-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwAHQCRBfs9lTLSaAg--.11044S4 X-Coremail-Antispam: 1UD129KBjvJXoWxJF1fXw48uFy8Wr4xKr1kGrg_yoW7Gr4fpF 45G3yrKrWUJFyvyF4fuw1fJr13Jw1fuw4jqFZ3J3sYywsrWr1UJw47CF4F9Fy5Gr9FyF12 yr4Yg3WY9r1DXaDanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmS14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_Jryl82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJw A2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AKxVW8Jr0_Cr1U M2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjx v20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1l F7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7M4IIrI8v6xkF7I0E8cxan2 IY04v7MxkF7I0En4kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY 6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17 CEb7AF67AKxVWrXVW8Jr1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI 42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF 4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBI daVFxhVjvjDU0xZFpf9x0pRHKZLUUUUU= X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Parse the RSA key with RAW format if the ASN.1 parser returns an error. Signed-off-by: Roberto Sassu --- crypto/rsa.c | 14 +++++-- crypto/rsa_helper.c | 69 +++++++++++++++++++++++++++++++++++ include/crypto/internal/rsa.h | 6 +++ 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/crypto/rsa.c b/crypto/rsa.c index b9cd11fb7d36..a26cfda7d7c9 100644 --- a/crypto/rsa.c +++ b/crypto/rsa.c @@ -244,8 +244,11 @@ static int rsa_set_pub_key(struct crypto_akcipher *tfm= , const void *key, rsa_free_mpi_key(mpi_key); =20 ret =3D rsa_parse_pub_key(&raw_key, key, keylen); - if (ret) - return ret; + if (ret) { + ret =3D rsa_parse_pub_key_raw(&raw_key, key, keylen); + if (ret) + return ret; + } =20 mpi_key->e =3D mpi_read_raw_data(raw_key.e, raw_key.e_sz); if (!mpi_key->e) @@ -283,8 +286,11 @@ static int rsa_set_priv_key(struct crypto_akcipher *tf= m, const void *key, rsa_free_mpi_key(mpi_key); =20 ret =3D rsa_parse_priv_key(&raw_key, key, keylen); - if (ret) - return ret; + if (ret) { + ret =3D rsa_parse_priv_key_raw(&raw_key, key, keylen); + if (ret) + return ret; + } =20 mpi_key->d =3D mpi_read_raw_data(raw_key.d, raw_key.d_sz); if (!mpi_key->d) diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c index 94266f29049c..fb9443df8f0b 100644 --- a/crypto/rsa_helper.c +++ b/crypto/rsa_helper.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "rsapubkey.asn1.h" #include "rsaprivkey.asn1.h" @@ -148,6 +149,32 @@ int rsa_get_qinv(void *context, size_t hdrlen, unsigne= d char tag, return 0; } =20 +typedef int (*rsa_get_func)(void *, size_t, unsigned char, + const void *, size_t); + +static int rsa_parse_key_raw(struct rsa_key *rsa_key, + const void *key, unsigned int key_len, + rsa_get_func *func, int n_func) +{ + unsigned int nbytes, len =3D key_len; + const void *key_ptr =3D key; + int ret, i; + + for (i =3D 0; i < n_func; i++) { + ret =3D mpi_key_length(key_ptr, len, NULL, &nbytes); + if (ret < 0) + return ret; + + ret =3D func[i](rsa_key, 0, 0, key_ptr + 2, nbytes); + if (ret < 0) + return ret; + + key_ptr +=3D nbytes + 2; + } + + return (key_ptr =3D=3D key + key_len) ? 0 : -EINVAL; +} + /** * rsa_parse_pub_key() - decodes the BER encoded buffer and stores in the * provided struct rsa_key, pointers to the raw key = as is, @@ -166,6 +193,27 @@ int rsa_parse_pub_key(struct rsa_key *rsa_key, const v= oid *key, } EXPORT_SYMBOL_GPL(rsa_parse_pub_key); =20 +/** + * rsa_parse_pub_key_raw() - parse the RAW key and store in the provided s= truct + * rsa_key, pointers to the raw key as is, so th= at + * the caller can copy it or MPI parse it, etc. + * + * @rsa_key: struct rsa_key key representation + * @key: key in RAW format + * @key_len: length of key + * + * Return: 0 on success or error code in case of error + */ +int rsa_parse_pub_key_raw(struct rsa_key *rsa_key, const void *key, + unsigned int key_len) +{ + rsa_get_func pub_func[] =3D {rsa_get_n, rsa_get_e}; + + return rsa_parse_key_raw(rsa_key, key, key_len, + pub_func, ARRAY_SIZE(pub_func)); +} +EXPORT_SYMBOL_GPL(rsa_parse_pub_key_raw); + /** * rsa_parse_priv_key() - decodes the BER encoded buffer and stores in the * provided struct rsa_key, pointers to the raw key @@ -184,3 +232,24 @@ int rsa_parse_priv_key(struct rsa_key *rsa_key, const = void *key, return asn1_ber_decoder(&rsaprivkey_decoder, rsa_key, key, key_len); } EXPORT_SYMBOL_GPL(rsa_parse_priv_key); + +/** + * rsa_parse_priv_key_raw() - parse the RAW key and store in the provided = struct + * rsa_key, pointers to the raw key as is, so t= hat + * the caller can copy it or MPI parse it, etc. + * + * @rsa_key: struct rsa_key key representation + * @key: key in RAW format + * @key_len: length of key + * + * Return: 0 on success or error code in case of error + */ +int rsa_parse_priv_key_raw(struct rsa_key *rsa_key, const void *key, + unsigned int key_len) +{ + rsa_get_func priv_func[] =3D {rsa_get_n, rsa_get_e, rsa_get_d}; + + return rsa_parse_key_raw(rsa_key, key, key_len, + priv_func, ARRAY_SIZE(priv_func)); +} +EXPORT_SYMBOL_GPL(rsa_parse_priv_key_raw); diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h index e870133f4b77..7141e806ceea 100644 --- a/include/crypto/internal/rsa.h +++ b/include/crypto/internal/rsa.h @@ -50,8 +50,14 @@ struct rsa_key { int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key, unsigned int key_len); =20 +int rsa_parse_pub_key_raw(struct rsa_key *rsa_key, const void *key, + unsigned int key_len); + int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key, unsigned int key_len); =20 +int rsa_parse_priv_key_raw(struct rsa_key *rsa_key, const void *key, + unsigned int key_len); + extern struct crypto_template rsa_pkcs1pad_tmpl; #endif --=20 2.34.1 From nobody Mon Feb 9 02:08:18 2026 Received: from frasgout13.his.huawei.com (frasgout13.his.huawei.com [14.137.139.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D4AE61350C0; Fri, 16 Feb 2024 15:26:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097173; cv=none; b=jEeEkDxspcbB/DBdLr4Zi3JGcbZNoImJrGKrucwLB5KKT91RO609Ev1Iz8xztvciENZNS03yRMdJlXzABpdZvfMQQpZiJdAGzKP9M02/GAy6m+YkZvFnS7fht1hyU9Ts75WeK+AjCJnQXV47spM3ljTp6QHvDfgtuPxHsE5j/lk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097173; c=relaxed/simple; bh=D2P1yAQ0Z4GYC0IevJCC6fp7n/FzZgFoYgFfIMUNd38=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=F43+nt3slHGrXCJ+5uCI7PatXH15ECnC6I0AO3mSRTe6j/xrcrP8ora/PBVDMaClKjTF3N27nFfTCiGL5yWoxKFU89lHfp9k9OEGtv0RaW0T3FfhnGEdbF3QFwUxf7Gy/7Jc0nD6QWRv868RzoAZLJLwAwNuPky72iOVXEKW0L4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.51]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4TbwNp38jTz9yBkY; Fri, 16 Feb 2024 23:10:50 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 65CB014064F; Fri, 16 Feb 2024 23:25:58 +0800 (CST) Received: from huaweicloud.com (unknown [10.48.131.30]) by APP2 (Coremail) with SMTP id GxC2BwAHQCRBfs9lTLSaAg--.11044S5; Fri, 16 Feb 2024 16:25:57 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?UTF-8?B?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , David Howells , Petr Tesarik Subject: [RFC 3/8] PGPLIB: PGP definitions (RFC 4880) Date: Fri, 16 Feb 2024 16:24:30 +0100 Message-Id: <20240216152435.1575-4-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240216152435.1575-1-petrtesarik@huaweicloud.com> References: <20240216152435.1575-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwAHQCRBfs9lTLSaAg--.11044S5 X-Coremail-Antispam: 1UD129KBjvJXoWxuFW5Zw1UurW3XFWUur4fAFb_yoW7Kw1Upr s5Gr95XFyDt343tr4Sqr42va4fJrsrAr1kGrn7tw15t3Z8WryIg34ktr1kXan3Ga98J3yY kFW5Arn3Cwn0y37anT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmS14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JrWl82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_Jr0_JF4l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJw A2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AKxVW8Jr0_Cr1U M2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjx v20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1l F7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7M4IIrI8v6xkF7I0E8cxan2 IY04v7MxkF7I0En4kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY 6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17 CEb7AF67AKxVWrXVW8Jr1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI 42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF 4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1UYxBI daVFxhVjvjDU0xZFpf9x0pRl_MsUUUUU= X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ Content-Type: text/plain; charset="utf-8" From: David Howells Provide some useful PGP definitions from RFC 4880. These describe details of public key crypto as used by crypto keys for things like signature verification. Signed-off-by: David Howells Co-developed-by: Roberto Sassu Signed-off-by: Roberto Sassu --- crypto/asymmetric_keys/pgp.h | 206 +++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 crypto/asymmetric_keys/pgp.h diff --git a/crypto/asymmetric_keys/pgp.h b/crypto/asymmetric_keys/pgp.h new file mode 100644 index 000000000000..5eb4f4222090 --- /dev/null +++ b/crypto/asymmetric_keys/pgp.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* PGP definitions (RFC 4880) + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include + +struct pgp_key_ID { + u8 id[8]; +} __packed; + +struct pgp_time { + u8 time[4]; +} __packed; + +/* + * PGP public-key algorithm identifiers [RFC4880: 9.1] + */ +enum pgp_pubkey_algo { + PGP_PUBKEY_RSA_ENC_OR_SIG =3D 1, + PGP_PUBKEY_RSA_ENC_ONLY =3D 2, + PGP_PUBKEY_RSA_SIG_ONLY =3D 3, + PGP_PUBKEY_ELGAMAL =3D 16, + PGP_PUBKEY_DSA =3D 17, + PGP_PUBKEY__LAST +}; + +/* + * PGP symmetric-key algorithm identifiers [RFC4880: 9.2] + */ +enum pgp_symkey_algo { + PGP_SYMKEY_PLAINTEXT =3D 0, + PGP_SYMKEY_IDEA =3D 1, + PGP_SYMKEY_3DES =3D 2, + PGP_SYMKEY_CAST5 =3D 3, + PGP_SYMKEY_BLOWFISH =3D 4, + PGP_SYMKEY_AES_128KEY =3D 7, + PGP_SYMKEY_AES_192KEY =3D 8, + PGP_SYMKEY_AES_256KEY =3D 9, + PGP_SYMKEY_TWOFISH_256KEY =3D 10, +}; + +/* + * PGP compression algorithm identifiers [RFC4880: 9.3] + */ +enum pgp_compr_algo { + PGP_COMPR_UNCOMPRESSED =3D 0, + PGP_COMPR_ZIP =3D 1, + PGP_COMPR_ZLIB =3D 2, + PGP_COMPR_BZIP2 =3D 3, +}; + +/* + * PGP hash algorithm identifiers [RFC4880: 9.4] + */ +enum pgp_hash_algo { + PGP_HASH_MD5 =3D 1, + PGP_HASH_SHA1 =3D 2, + PGP_HASH_RIPE_MD_160 =3D 3, + PGP_HASH_SHA256 =3D 8, + PGP_HASH_SHA384 =3D 9, + PGP_HASH_SHA512 =3D 10, + PGP_HASH_SHA224 =3D 11, + PGP_HASH__LAST +}; + +extern const char *const pgp_hash_algorithms[PGP_HASH__LAST]; + +/* + * PGP packet type tags [RFC4880: 4.3]. + */ +enum pgp_packet_tag { + PGP_PKT_RESERVED =3D 0, + PGP_PKT_PUBKEY_ENC_SESSION_KEY =3D 1, + PGP_PKT_SIGNATURE =3D 2, + PGP_PKT_SYMKEY_ENC_SESSION_KEY =3D 3, + PGP_PKT_ONEPASS_SIGNATURE =3D 4, + PGP_PKT_SECRET_KEY =3D 5, + PGP_PKT_PUBLIC_KEY =3D 6, + PGP_PKT_SECRET_SUBKEY =3D 7, + PGP_PKT_COMPRESSED_DATA =3D 8, + PGP_PKT_SYM_ENC_DATA =3D 9, + PGP_PKT_MARKER =3D 10, + PGP_PKT_LITERAL_DATA =3D 11, + PGP_PKT_TRUST =3D 12, + PGP_PKT_USER_ID =3D 13, + PGP_PKT_PUBLIC_SUBKEY =3D 14, + PGP_PKT_USER_ATTRIBUTE =3D 17, + PGP_PKT_SYM_ENC_AND_INTEG_DATA =3D 18, + PGP_PKT_MODIFY_DETECT_CODE =3D 19, + PGP_PKT_PRIVATE_0 =3D 60, + PGP_PKT_PRIVATE_3 =3D 63, + PGP_PKT__HIGHEST =3D 63 +}; + +/* + * Signature (tag 2) packet [RFC4880: 5.2]. + */ +enum pgp_signature_version { + PGP_SIG_VERSION_3 =3D 3, + PGP_SIG_VERSION_4 =3D 4, +}; + +enum pgp_signature_type { + PGP_SIG_BINARY_DOCUMENT_SIG =3D 0x00, + PGP_SIG_CANONICAL_TEXT_DOCUMENT_SIG =3D 0x01, + PGP_SIG_STANDALONE_SIG =3D 0x02, + PGP_SIG_GENERAL_CERT_OF_UID_PUBKEY =3D 0x10, + PGP_SIG_PERSONAL_CERT_OF_UID_PUBKEY =3D 0x11, + PGP_SIG_CASUAL_CERT_OF_UID_PUBKEY =3D 0x12, + PGP_SIG_POSTITIVE_CERT_OF_UID_PUBKEY =3D 0x13, + PGP_SIG_SUBKEY_BINDING_SIG =3D 0x18, + PGP_SIG_PRIMARY_KEY_BINDING_SIG =3D 0x19, + PGP_SIG_DIRECTLY_ON_KEY =3D 0x1F, + PGP_SIG_KEY_REVOCATION_SIG =3D 0x20, + PGP_SIG_SUBKEY_REVOCATION_SIG =3D 0x28, + PGP_SIG_CERT_REVOCATION_SIG =3D 0x30, + PGP_SIG_TIMESTAMP_SIG =3D 0x40, + PGP_SIG_THIRD_PARTY_CONFIRM_SIG =3D 0x50, +}; + +struct pgp_signature_v3_packet { + enum pgp_signature_version version : 8; /* =3D=3D PGP_SIG_VERSION_3 */ + u8 length_of_hashed; /* =3D=3D 5 */ + struct { + enum pgp_signature_type signature_type : 8; + struct pgp_time creation_time; + } __packed hashed; + struct pgp_key_ID issuer; + enum pgp_pubkey_algo pubkey_algo : 8; + enum pgp_hash_algo hash_algo : 8; +} __packed; + +struct pgp_signature_v4_packet { + enum pgp_signature_version version : 8; /* =3D=3D PGP_SIG_VERSION_4 */ + enum pgp_signature_type signature_type : 8; + enum pgp_pubkey_algo pubkey_algo : 8; + enum pgp_hash_algo hash_algo : 8; +} __packed; + +/* + * V4 signature subpacket types [RFC4880: 5.2.3.1]. + */ +enum pgp_sig_subpkt_type { + PGP_SIG_CREATION_TIME =3D 2, + PGP_SIG_EXPIRATION_TIME =3D 3, + PGP_SIG_EXPORTABLE_CERT =3D 4, + PGP_SIG_TRUST_SIG =3D 5, + PGP_SIG_REGEXP =3D 6, + PGP_SIG_REVOCABLE =3D 7, + PGP_SIG_KEY_EXPIRATION_TIME =3D 9, + PGP_SIG_PREF_SYM_ALGO =3D 11, + PGP_SIG_REVOCATION_KEY =3D 12, + PGP_SIG_ISSUER =3D 16, + PGP_SIG_NOTATION_DATA =3D 20, + PGP_SIG_PREF_HASH_ALGO =3D 21, + PGP_SIG_PREF_COMPR_ALGO =3D 22, + PGP_SIG_KEY_SERVER_PREFS =3D 23, + PGP_SIG_PREF_KEY_SERVER =3D 24, + PGP_SIG_PRIMARY_USER_ID =3D 25, + PGP_SIG_POLICY_URI =3D 26, + PGP_SIG_KEY_FLAGS =3D 27, + PGP_SIG_SIGNERS_USER_ID =3D 28, + PGP_SIG_REASON_FOR_REVOCATION =3D 29, + PGP_SIG_FEATURES =3D 30, + PGP_SIG_TARGET =3D 31, + PGP_SIG_EMBEDDED_SIG =3D 32, + PGP_SIG__LAST +}; + +#define PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK 0x80 + +/* + * Key (tag 5, 6, 7 and 14) packet + */ +enum pgp_key_version { + PGP_KEY_VERSION_2 =3D 2, + PGP_KEY_VERSION_3 =3D 3, + PGP_KEY_VERSION_4 =3D 4, +}; + +struct pgp_key_v3_packet { + enum pgp_key_version version : 8; + struct pgp_time creation_time; + u8 expiry[2]; /* 0 or time in days till expiry */ + enum pgp_pubkey_algo pubkey_algo : 8; + u8 key_material[0]; +} __packed; + +struct pgp_key_v4_packet { + enum pgp_key_version version : 8; + struct pgp_time creation_time; + enum pgp_pubkey_algo pubkey_algo : 8; + u8 key_material[0]; +} __packed; + +/* + * Literal Data (tag 11) packet + */ +enum pgp_literal_data_format { + PGP_LIT_FORMAT_BINARY =3D 0x62, + PGP_LIT_FORMAT_TEXT =3D 0x74, + PGP_LIT_FORMAT_TEXT_UTF8 =3D 0x75, +}; --=20 2.34.1 From nobody Mon Feb 9 02:08:18 2026 Received: from frasgout13.his.huawei.com (frasgout13.his.huawei.com [14.137.139.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BA3BC1350C0; Fri, 16 Feb 2024 15:26:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097185; cv=none; b=Mk9pi9HMKUFE8Sx+K7L7ZRauvukAHjJTR/naWF3nFw/X3usprdcjLI/JzUVmF87kO5vEDKIxJ9Esl0CwT9bRtnvQFJh6bVQsl04Z0jElGVdilonv3cphZVQ3QhuicIUXsQCMN4aLhfmDU5JLYS7J7JNQDtcDsRKItStyUHZ7Ckc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097185; c=relaxed/simple; bh=wDRrVItlMgBFAtEOauo1qK60I52wT/Rx/468pjENbkI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YnoPNvnEg5AUSZimrmvh326ZY61jH8zgfiXkCBdSTv0b9QJ2S9VEmKJVxgTi5AZOZsYqAbL6SF97RPSYLX2yO4q77ZNlhvbUBx06uxgXJYI+s3lwnAR6HPvtLRNk6bBsc846NYM7bDCr8l8bUrvK9Ds6KNUcdxZOygPtmL7YQ0A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4TbwP30gdfz9yBkV; Fri, 16 Feb 2024 23:11:03 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id C388A140E02; Fri, 16 Feb 2024 23:26:14 +0800 (CST) Received: from huaweicloud.com (unknown [10.48.131.30]) by APP2 (Coremail) with SMTP id GxC2BwAHQCRBfs9lTLSaAg--.11044S6; Fri, 16 Feb 2024 16:26:14 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?UTF-8?B?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , David Howells , Petr Tesarik Subject: [RFC 4/8] PGPLIB: Basic packet parser Date: Fri, 16 Feb 2024 16:24:31 +0100 Message-Id: <20240216152435.1575-5-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240216152435.1575-1-petrtesarik@huaweicloud.com> References: <20240216152435.1575-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwAHQCRBfs9lTLSaAg--.11044S6 X-Coremail-Antispam: 1UD129KBjvJXoWxtrW7GF43Ar48trWxZr47urg_yoWDGw4fpa 48CryrKa1UGwn2krWfAr17W3srCr48ZFyagayFvw1Yy39FgwnYgrZFkF18Ka48KF4DJ3yS krs0gFyY93WqqrJanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmm14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF0E3s1l82xGYI kIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2 z4x0Y4vE2Ix0cI8IcVAFwI0_JFI_Gr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F 4UJwA2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AKxVW8Jr0_ Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6x IIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_ Gr1lF7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7M4IIrI8v6xkF7I0E8c xan2IY04v7MxkF7I0En4kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCj c4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4 CE17CEb7AF67AKxVWrXVW8Jr1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWU CwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr 0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1U YxBIdaVFxhVjvjDU0xZFpf9x0pRQJ5wUUUUU= X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ Content-Type: text/plain; charset="utf-8" From: David Howells Provide a simple parser that extracts the packets from a PGP packet blob and passes the desirous ones to the given processor function: struct pgp_parse_context { u64 types_of_interest; int (*process_packet)(struct pgp_parse_context *context, enum pgp_packet_tag type, u8 headerlen, const u8 *data, size_t datalen); }; int pgp_parse_packets(const u8 *data, size_t datalen, struct pgp_parse_context *ctx); This is configured on with CONFIG_PGP_LIBRARY. Signed-off-by: David Howells Co-developed-by: Roberto Sassu Signed-off-by: Roberto Sassu --- crypto/asymmetric_keys/Kconfig | 6 + crypto/asymmetric_keys/Makefile | 16 ++ crypto/asymmetric_keys/pgp_library.c | 272 +++++++++++++++++++++++++++ crypto/asymmetric_keys/pgplib.h | 33 ++++ 4 files changed, 327 insertions(+) create mode 100644 crypto/asymmetric_keys/pgp_library.c create mode 100644 crypto/asymmetric_keys/pgplib.h diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 59ec726b7c77..ebe9dc88d975 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -86,4 +86,10 @@ config FIPS_SIGNATURE_SELFTEST depends on PKCS7_MESSAGE_PARSER=3DX509_CERTIFICATE_PARSER depends on X509_CERTIFICATE_PARSER =20 +config PGP_LIBRARY + tristate "PGP parsing library" + help + This option enables a library that provides a number of simple + utility functions for parsing PGP (RFC 4880) packet-based messages. + endif # ASYMMETRIC_KEY_TYPE diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makef= ile index 1a273d6df3eb..f7e5ee59857f 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -77,3 +77,19 @@ verify_signed_pefile-y :=3D \ =20 $(obj)/mscode_parser.o: $(obj)/mscode.asn1.h $(obj)/mscode.asn1.h $(obj)/mscode.asn1.o: $(obj)/mscode.asn1.c $(obj)/mscode.asn1.h + +# +# TPM private key parsing +# +obj-$(CONFIG_TPM_KEY_PARSER) +=3D tpm_key_parser.o +tpm_key_parser-y :=3D \ + tpm.asn1.o \ + tpm_parser.o + +$(obj)/tpm_parser.o: $(obj)/tpm.asn1.h +$(obj)/tpm.asn1.o: $(obj)/tpm.asn1.c $(obj)/tpm.asn1.h + +# +# PGP handling +# +obj-$(CONFIG_PGP_LIBRARY) +=3D pgp_library.o diff --git a/crypto/asymmetric_keys/pgp_library.c b/crypto/asymmetric_keys/= pgp_library.c new file mode 100644 index 000000000000..d2c3149983d5 --- /dev/null +++ b/crypto/asymmetric_keys/pgp_library.c @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: GPL-2.0 +/* PGP packet parser (RFC 4880) + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#define pr_fmt(fmt) "PGPL: "fmt +#include +#include +#include + +#include "pgplib.h" + +MODULE_LICENSE("GPL"); + +const char *const pgp_hash_algorithms[PGP_HASH__LAST] =3D { + [PGP_HASH_MD5] =3D "md5", + [PGP_HASH_SHA1] =3D "sha1", + [PGP_HASH_RIPE_MD_160] =3D "rmd160", + [PGP_HASH_SHA256] =3D "sha256", + [PGP_HASH_SHA384] =3D "sha384", + [PGP_HASH_SHA512] =3D "sha512", + [PGP_HASH_SHA224] =3D "sha224", +}; +EXPORT_SYMBOL_GPL(pgp_hash_algorithms); + +/** + * pgp_parse_packet_header - Parse a PGP packet header + * @_data: Start of the PGP packet (updated to PGP packet data) + * @_datalen: Amount of data remaining in buffer (decreased) + * @_type: Where the packet type will be returned + * @_headerlen: Where the header length will be returned + * + * Parse a set of PGP packet header [RFC 4880: 4.2]. + * + * Return: packet data size on success; non-zero on error. If successful, + * *_data and *_datalen will have been updated and *_headerlen will be set= to + * hold the length of the packet header. + */ +static ssize_t pgp_parse_packet_header(const u8 **_data, size_t *_datalen, + enum pgp_packet_tag *_type, + u8 *_headerlen) +{ + enum pgp_packet_tag type; + const u8 *data =3D *_data; + size_t size, datalen =3D *_datalen; + + pr_devel("-->%s(,%zu,,)\n", __func__, datalen); + + if (datalen < 2) + goto short_packet; + + pr_devel("pkthdr %02x, %02x\n", data[0], data[1]); + + type =3D *data++; + datalen--; + if (!(type & 0x80)) { + pr_debug("Packet type does not have MSB set\n"); + return -EBADMSG; + } + type &=3D ~0x80; + + if (type & 0x40) { + /* New packet length format */ + type &=3D ~0x40; + pr_devel("new format: t=3D%u\n", type); + switch (data[0]) { + case 0x00 ... 0xbf: + /* One-byte length */ + size =3D data[0]; + data++; + datalen--; + *_headerlen =3D 2; + break; + case 0xc0 ... 0xdf: + /* Two-byte length */ + if (datalen < 2) + goto short_packet; + size =3D (data[0] - 192) * 256; + size +=3D data[1] + 192; + data +=3D 2; + datalen -=3D 2; + *_headerlen =3D 3; + break; + case 0xff: + /* Five-byte length */ + if (datalen < 5) + goto short_packet; + size =3D data[1] << 24; + size |=3D data[2] << 16; + size |=3D data[3] << 8; + size |=3D data[4]; + data +=3D 5; + datalen -=3D 5; + *_headerlen =3D 6; + break; + default: + pr_debug("Partial body length packet not supported\n"); + return -EBADMSG; + } + } else { + /* Old packet length format */ + u8 length_type =3D type & 0x03; + + type >>=3D 2; + pr_devel("old format: t=3D%u lt=3D%u\n", type, length_type); + + switch (length_type) { + case 0: + /* One-byte length */ + size =3D data[0]; + data++; + datalen--; + *_headerlen =3D 2; + break; + case 1: + /* Two-byte length */ + if (datalen < 2) + goto short_packet; + size =3D data[0] << 8; + size |=3D data[1]; + data +=3D 2; + datalen -=3D 2; + *_headerlen =3D 3; + break; + case 2: + /* Four-byte length */ + if (datalen < 4) + goto short_packet; + size =3D data[0] << 24; + size |=3D data[1] << 16; + size |=3D data[2] << 8; + size |=3D data[3]; + data +=3D 4; + datalen -=3D 4; + *_headerlen =3D 5; + break; + default: + pr_debug("Indefinite length packet not supported\n"); + return -EBADMSG; + } + } + + pr_devel("datalen=3D%zu size=3D%zu\n", datalen, size); + if (datalen < size) + goto short_packet; + if (size > INT_MAX) + goto too_big; + + *_data =3D data; + *_datalen =3D datalen; + *_type =3D type; + pr_devel("Found packet type=3D%u size=3D%zd\n", type, size); + return size; + +short_packet: + pr_debug("Attempt to parse short packet\n"); + return -EBADMSG; +too_big: + pr_debug("Signature subpacket size >2G\n"); + return -EMSGSIZE; +} + +/** + * pgp_parse_packets - Parse a set of PGP packets + * @data: Data to be parsed (updated) + * @datalen: Amount of data (updated) + * @ctx: Parsing context + * + * Parse a set of PGP packets [RFC 4880: 4]. + * + * Return: 0 on successful parsing, a negative value otherwise + */ +int pgp_parse_packets(const u8 *data, size_t datalen, + struct pgp_parse_context *ctx) +{ + enum pgp_packet_tag type; + ssize_t pktlen; + u8 headerlen; + int ret; + + while (datalen > 2) { + pktlen =3D pgp_parse_packet_header(&data, &datalen, &type, + &headerlen); + if (pktlen < 0) + return pktlen; + + if ((ctx->types_of_interest >> type) & 1) { + ret =3D ctx->process_packet(ctx, type, headerlen, + data, pktlen); + if (ret < 0) + return ret; + } + data +=3D pktlen; + datalen -=3D pktlen; + } + + if (datalen !=3D 0) { + pr_debug("Excess octets in packet stream\n"); + return -EBADMSG; + } + + return 0; +} +EXPORT_SYMBOL_GPL(pgp_parse_packets); + +/** + * pgp_parse_public_key - Parse the common part of a PGP pubkey packet + * @_data: Content of packet (updated) + * @_datalen: Length of packet remaining (updated) + * @pk: Public key data + * + * Parse the common data struct for a PGP pubkey packet [RFC 4880: 5.5.2]. + * + * Return: 0 on successful parsing, a negative value otherwise + */ +int pgp_parse_public_key(const u8 **_data, size_t *_datalen, + struct pgp_parse_pubkey *pk) +{ + const u8 *data =3D *_data; + size_t datalen =3D *_datalen; + unsigned int tmp; + + if (datalen < 12) { + pr_debug("Public key packet too short\n"); + return -EBADMSG; + } + + pk->version =3D *data++; + switch (pk->version) { + case PGP_KEY_VERSION_2: + case PGP_KEY_VERSION_3: + case PGP_KEY_VERSION_4: + break; + default: + pr_debug("Public key packet with unhandled version %d\n", + pk->version); + return -EBADMSG; + } + + tmp =3D *data++ << 24; + tmp |=3D *data++ << 16; + tmp |=3D *data++ << 8; + tmp |=3D *data++; + pk->creation_time =3D tmp; + if (pk->version =3D=3D PGP_KEY_VERSION_4) { + pk->expires_at =3D 0; /* Have to get it from the selfsignature */ + } else { + unsigned short ndays; + + ndays =3D *data++ << 8; + ndays |=3D *data++; + if (ndays) + pk->expires_at =3D pk->creation_time + ndays * 86400UL; + else + pk->expires_at =3D 0; + datalen -=3D 2; + } + + pk->pubkey_algo =3D *data++; + datalen -=3D 6; + + pr_devel("%x,%x,%lx,%lx\n", + pk->version, pk->pubkey_algo, pk->creation_time, + pk->expires_at); + + *_data =3D data; + *_datalen =3D datalen; + return 0; +} +EXPORT_SYMBOL_GPL(pgp_parse_public_key); diff --git a/crypto/asymmetric_keys/pgplib.h b/crypto/asymmetric_keys/pgpli= b.h new file mode 100644 index 000000000000..d82b84179433 --- /dev/null +++ b/crypto/asymmetric_keys/pgplib.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* PGP library definitions (RFC 4880) + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include "pgp.h" + +/* + * PGP library packet parser + */ +struct pgp_parse_context { + u64 types_of_interest; + int (*process_packet)(struct pgp_parse_context *context, + enum pgp_packet_tag type, + u8 headerlen, + const u8 *data, + size_t datalen); +}; + +extern int pgp_parse_packets(const u8 *data, size_t datalen, + struct pgp_parse_context *ctx); + +struct pgp_parse_pubkey { + enum pgp_key_version version : 8; + enum pgp_pubkey_algo pubkey_algo : 8; + __kernel_old_time_t creation_time; + __kernel_old_time_t expires_at; +}; + +extern int pgp_parse_public_key(const u8 **_data, size_t *_datalen, + struct pgp_parse_pubkey *pk); --=20 2.34.1 From nobody Mon Feb 9 02:08:18 2026 Received: from frasgout13.his.huawei.com (frasgout13.his.huawei.com [14.137.139.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 12C8E135416; Fri, 16 Feb 2024 15:26:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097206; cv=none; b=pFtBbk9u9CiIxknchSJxqV6oFNVD82/jlqR9EX+iIw8ClHfWDewdixcSCZSmLMHzHsJL1gBkPz6QbJF+OHPiCMoGE/+xtBODWHl/J72jlKCcp/KiCrTCHkVds8lnHCrzN1XZbwFSvFsVWjjWkuNDJ3MygC9Wvw7bpXDFrVe1Qig= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097206; c=relaxed/simple; bh=Oz2/9YzU5D10pdbzfEmKDaUKj6akAqmbwAHuQa67quY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=JkBk2UqMnzDbUiAYmN6OhVO+VkXuksEBixtBCUi2X6xgExJUYXEA3frFhyuxMQi/gbqEAwClMzBHyUD6hoPQ5+H6y/JUFN0OMjm0XC7AeyIhtABog7W1XE6PKtZVEu2OokrYUHiSuytCpMnuXY7TP4Swfu4Yc9fJoiEgEewI/IE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout13.his.huawei.com (SkyGuard) with ESMTP id 4TbwPS2mTGz9yKXQ; Fri, 16 Feb 2024 23:11:24 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 3B634140661; Fri, 16 Feb 2024 23:26:31 +0800 (CST) Received: from huaweicloud.com (unknown [10.48.131.30]) by APP2 (Coremail) with SMTP id GxC2BwAHQCRBfs9lTLSaAg--.11044S7; Fri, 16 Feb 2024 16:26:30 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?UTF-8?B?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , David Howells , Petr Tesarik Subject: [RFC 5/8] PGPLIB: Signature parser Date: Fri, 16 Feb 2024 16:24:32 +0100 Message-Id: <20240216152435.1575-6-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240216152435.1575-1-petrtesarik@huaweicloud.com> References: <20240216152435.1575-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwAHQCRBfs9lTLSaAg--.11044S7 X-Coremail-Antispam: 1UD129KBjvJXoWxuFW8tryruF45Cw1rAF47urg_yoWDGry3pa 40y34ftrWUG3ZavrW8Ar47X3y5Cr40y347Ka9Yq3WYy39agrn8ZrWvkFyFkFZ8t3WkX3yx CrZ8ta98ur4kZw7anT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmm14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF0E3s1l82xGYI kIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2 z4x0Y4vE2Ix0cI8IcVAFwI0_JFI_Gr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F 4UJwA2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AKxVW8Jr0_ Cr1UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6x IIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_ Gr1lF7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7M4IIrI8v6xkF7I0E8c xan2IY04v7MxkF7I0En4kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCj c4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4 CE17CEb7AF67AKxVWrXVW8Jr1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8 JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr 0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1U YxBIdaVFxhVjvjDU0xZFpf9x0pRQJ5wUUUUU= X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ Content-Type: text/plain; charset="utf-8" From: David Howells Provide some PGP signature parsing helpers: (1) A function to parse V4 signature subpackets and pass the desired ones to a processor function: int pgp_parse_sig_subpkts(const u8 *data, size_t datalen, struct pgp_parse_sig_context *ctx); (2) A function to parse out basic signature parameters from any PGP signature such that the algorithms and public key can be selected: int pgp_parse_sig_params(const u8 **_data, size_t *_datalen, struct pgp_sig_parameters *p); Signed-off-by: David Howells Co-developed-by: Roberto Sassu Signed-off-by: Roberto Sassu --- crypto/asymmetric_keys/pgp_library.c | 284 +++++++++++++++++++++++++++ crypto/asymmetric_keys/pgplib.h | 25 +++ 2 files changed, 309 insertions(+) diff --git a/crypto/asymmetric_keys/pgp_library.c b/crypto/asymmetric_keys/= pgp_library.c index d2c3149983d5..de4a748db9be 100644 --- a/crypto/asymmetric_keys/pgp_library.c +++ b/crypto/asymmetric_keys/pgp_library.c @@ -270,3 +270,287 @@ int pgp_parse_public_key(const u8 **_data, size_t *_d= atalen, return 0; } EXPORT_SYMBOL_GPL(pgp_parse_public_key); + +/** + * pgp_parse_sig_subpkt_header - Parse a PGP V4 signature subpacket header + * @_data: Start of the subpacket (updated to subpacket data) + * @_datalen: Amount of data remaining in buffer (decreased) + * @_type: Where the subpacket type will be returned + * + * Parse a PGP V4 signature subpacket header [RFC 4880: 5.2.3.1]. + * + * Return: packet data size on success; non-zero on error. If successful, + * *_data and *_datalen will have been updated and *_headerlen will be set= to + * hold the length of the packet header. + */ +static ssize_t pgp_parse_sig_subpkt_header(const u8 **_data, size_t *_data= len, + enum pgp_sig_subpkt_type *_type) +{ + enum pgp_sig_subpkt_type type; + const u8 *data =3D *_data; + size_t size, datalen =3D *_datalen; + + pr_devel("-->%s(,%zu,,)\n", __func__, datalen); + + if (datalen < 2) + goto short_subpacket; + + pr_devel("subpkt hdr %02x, %02x\n", data[0], data[1]); + + switch (data[0]) { + case 0x00 ... 0xbf: + /* One-byte length */ + size =3D data[0]; + data++; + datalen--; + break; + case 0xc0 ... 0xfe: + /* Two-byte length */ + if (datalen < 3) + goto short_subpacket; + size =3D (data[0] - 192) * 256; + size +=3D data[1] + 192; + data +=3D 2; + datalen -=3D 2; + break; + case 0xff: + if (datalen < 6) + goto short_subpacket; + size =3D data[1] << 24; + size |=3D data[2] << 16; + size |=3D data[3] << 8; + size |=3D data[4]; + data +=3D 5; + datalen -=3D 5; + break; + } + + /* The type octet is included in the size */ + pr_devel("datalen=3D%zu size=3D%zu\n", datalen, size); + if (datalen < size) + goto short_subpacket; + if (size =3D=3D 0) + goto very_short_subpacket; + if (size > INT_MAX) + goto too_big; + + type =3D *data++ & ~PGP_SIG_SUBPKT_TYPE_CRITICAL_MASK; + datalen--; + size--; + + *_data =3D data; + *_datalen =3D datalen; + *_type =3D type; + pr_devel("Found subpkt type=3D%u size=3D%zd\n", type, size); + return size; + +very_short_subpacket: + pr_debug("Signature subpacket size can't be zero\n"); + return -EBADMSG; +short_subpacket: + pr_debug("Attempt to parse short signature subpacket\n"); + return -EBADMSG; +too_big: + pr_debug("Signature subpacket size >2G\n"); + return -EMSGSIZE; +} + +/** + * pgp_parse_sig_subpkts - Parse a set of PGP V4 signatute subpackets + * @data: Data to be parsed (updated) + * @datalen: Amount of data (updated) + * @ctx: Parsing context + * + * Parse a set of PGP signature subpackets [RFC 4880: 5.2.3]. + * + * Return: 0 on successful parsing, an error value otherwise + */ +static int pgp_parse_sig_subpkts(const u8 *data, size_t datalen, + struct pgp_parse_sig_context *ctx) +{ + enum pgp_sig_subpkt_type type; + ssize_t pktlen; + int ret; + + pr_devel("-->%s(,%zu,,)\n", __func__, datalen); + + while (datalen > 2) { + pktlen =3D pgp_parse_sig_subpkt_header(&data, &datalen, &type); + if (pktlen < 0) + return pktlen; + if (test_bit(type, ctx->types_of_interest)) { + ret =3D ctx->process_packet(ctx, type, data, pktlen); + if (ret < 0) + return ret; + } + data +=3D pktlen; + datalen -=3D pktlen; + } + + if (datalen !=3D 0) { + pr_debug("Excess octets in signature subpacket stream\n"); + return -EBADMSG; + } + + return 0; +} + +struct pgp_parse_sig_params_ctx { + struct pgp_parse_sig_context base; + struct pgp_sig_parameters *params; + bool got_the_issuer; +}; + +/* + * Process a V4 signature subpacket. + */ +static int pgp_process_sig_params_subpkt(struct pgp_parse_sig_context *con= text, + enum pgp_sig_subpkt_type type, + const u8 *data, + size_t datalen) +{ + struct pgp_parse_sig_params_ctx *ctx =3D + container_of(context, struct pgp_parse_sig_params_ctx, base); + + if (ctx->got_the_issuer) { + pr_debug("V4 signature packet has multiple issuers\n"); + return -EBADMSG; + } + + if (datalen !=3D 8) { + pr_debug("V4 signature issuer subpkt not 8 long (%zu)\n", + datalen); + return -EBADMSG; + } + + memcpy(&ctx->params->issuer, data, 8); + ctx->got_the_issuer =3D true; + return 0; +} + +/** + * pgp_parse_sig_params - Parse basic parameters from a PGP signature pack= et + * @_data: Content of packet (updated) + * @_datalen: Length of packet remaining (updated) + * @p: The basic parameters + * + * Parse the basic parameters from a PGP signature packet [RFC 4880: 5.2] = that + * are needed to start off a signature verification operation. The only o= nes + * actually necessary are the signature type (which affects how the data is + * transformed) and the hash algorithm. + * + * We also extract the public key algorithm and the issuer's key ID as we'= ll + * need those to determine if we actually have the public key available. = If + * not, then we can't verify the signature anyway. + * + * Return: 0 if successful or a negative error code. *_data and *_datalen= are + * updated to point to the 16-bit subset of the hash value and the set of = MPIs. + */ +int pgp_parse_sig_params(const u8 **_data, size_t *_datalen, + struct pgp_sig_parameters *p) +{ + const u8 *data =3D *_data; + size_t datalen =3D *_datalen; + int ret; + + pr_devel("-->%s(,%zu,,)\n", __func__, datalen); + + if (datalen < 1) + return -EBADMSG; + p->version =3D *data; + + if (p->version =3D=3D PGP_SIG_VERSION_3) { + const struct pgp_signature_v3_packet *v3 =3D (const void *)data; + + if (datalen < sizeof(*v3)) { + pr_debug("Short V3 signature packet\n"); + return -EBADMSG; + } + datalen -=3D sizeof(*v3); + data +=3D sizeof(*v3); + + /* V3 has everything we need in the header */ + p->signature_type =3D v3->hashed.signature_type; + memcpy(&p->issuer, &v3->issuer, 8); + p->pubkey_algo =3D v3->pubkey_algo; + p->hash_algo =3D v3->hash_algo; + + } else if (p->version =3D=3D PGP_SIG_VERSION_4) { + const struct pgp_signature_v4_packet *v4 =3D (const void *)data; + struct pgp_parse_sig_params_ctx ctx =3D { + .base.process_packet =3D pgp_process_sig_params_subpkt, + .params =3D p, + .got_the_issuer =3D false, + }; + size_t subdatalen; + + if (datalen < sizeof(*v4) + 2 + 2 + 2) { + pr_debug("Short V4 signature packet\n"); + return -EBADMSG; + } + datalen -=3D sizeof(*v4); + data +=3D sizeof(*v4); + + /* V4 has most things in the header... */ + p->signature_type =3D v4->signature_type; + p->pubkey_algo =3D v4->pubkey_algo; + p->hash_algo =3D v4->hash_algo; + + /* + * ... but we have to get the key ID from the subpackets, of + * which there are two sets. + */ + __set_bit(PGP_SIG_ISSUER, ctx.base.types_of_interest); + + subdatalen =3D *data++ << 8; + subdatalen |=3D *data++; + datalen -=3D 2; + if (subdatalen) { + /* Hashed subpackets */ + pr_devel("hashed data: %zu (after %zu)\n", + subdatalen, sizeof(*v4)); + if (subdatalen > datalen + 2 + 2) { + pr_debug("Short V4 signature packet [hdata]\n"); + return -EBADMSG; + } + ret =3D pgp_parse_sig_subpkts(data, subdatalen, + &ctx.base); + if (ret < 0) + return ret; + data +=3D subdatalen; + datalen -=3D subdatalen; + } + + subdatalen =3D *data++ << 8; + subdatalen |=3D *data++; + datalen -=3D 2; + if (subdatalen) { + /* Unhashed subpackets */ + pr_devel("unhashed data: %zu\n", subdatalen); + if (subdatalen > datalen + 2) { + pr_debug("Short V4 signature packet [udata]\n"); + return -EBADMSG; + } + ret =3D pgp_parse_sig_subpkts(data, subdatalen, + &ctx.base); + if (ret < 0) + return ret; + data +=3D subdatalen; + datalen -=3D subdatalen; + } + + if (!ctx.got_the_issuer) { + pr_debug("V4 signature packet lacks issuer\n"); + return -EBADMSG; + } + } else { + pr_debug("Signature packet with unhandled version %d\n", + p->version); + return -EBADMSG; + } + + *_data =3D data; + *_datalen =3D datalen; + return 0; +} +EXPORT_SYMBOL_GPL(pgp_parse_sig_params); diff --git a/crypto/asymmetric_keys/pgplib.h b/crypto/asymmetric_keys/pgpli= b.h index d82b84179433..967e2853186d 100644 --- a/crypto/asymmetric_keys/pgplib.h +++ b/crypto/asymmetric_keys/pgplib.h @@ -31,3 +31,28 @@ struct pgp_parse_pubkey { =20 extern int pgp_parse_public_key(const u8 **_data, size_t *_datalen, struct pgp_parse_pubkey *pk); + +struct pgp_parse_sig_context { + unsigned long types_of_interest[128 / BITS_PER_LONG]; + int (*process_packet)(struct pgp_parse_sig_context *context, + enum pgp_sig_subpkt_type type, + const u8 *data, + size_t datalen); +}; + +extern int pgp_parse_sig_packets(const u8 *data, size_t datalen, + struct pgp_parse_sig_context *ctx); + +struct pgp_sig_parameters { + enum pgp_signature_version version : 8; + enum pgp_signature_type signature_type : 8; + enum pgp_pubkey_algo pubkey_algo : 8; + enum pgp_hash_algo hash_algo : 8; + union { + struct pgp_key_ID issuer; + __be32 issuer32[2]; + }; +}; + +extern int pgp_parse_sig_params(const u8 **_data, size_t *_datalen, + struct pgp_sig_parameters *p); --=20 2.34.1 From nobody Mon Feb 9 02:08:18 2026 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6DEE2135A72; Fri, 16 Feb 2024 15:26:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097212; cv=none; b=qx0ACPNA2ZODnr42qRjLcOBqlRC5M/++L96EqKfKtl4trrb2P5YMTGIS/NZlfdqhMPa2nOf3c1qBdEKeLFav+QEAGYl2zfiVR7fA254p/anLbu3s7KlLykX5EE+ru1MZMjN3mxc3EeU3ZzD4cb1nAi5vzjCupMp8pPs4JSBhYgM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097212; c=relaxed/simple; bh=vX8bdfkhJXIidlLH/j/4oK9ZgQH2R8GvtkPECNYgHJw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=lZ2cZHlwLf1IXywbXNYyRfjm3ks/IG+28bePnnCyIe2DsAzThxdTsp+LKUaJyYtNh/6oXhIZOmsQ5TeJ7djUepvnbO+HgDYTN6ZSyF4J/Sya0CUTteO0CI1lUS+KBOamsstdVU/EYjG8d0cNElc2KIQ8QuxvKuRulR2fHr5i/Mk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4TbwPX4pSqz9ybvJ; Fri, 16 Feb 2024 23:11:28 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id A816D140631; Fri, 16 Feb 2024 23:26:47 +0800 (CST) Received: from huaweicloud.com (unknown [10.48.131.30]) by APP2 (Coremail) with SMTP id GxC2BwAHQCRBfs9lTLSaAg--.11044S8; Fri, 16 Feb 2024 16:26:46 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?UTF-8?B?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , David Howells , Petr Tesarik Subject: [RFC 6/8] KEYS: PGP data parser Date: Fri, 16 Feb 2024 16:24:33 +0100 Message-Id: <20240216152435.1575-7-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240216152435.1575-1-petrtesarik@huaweicloud.com> References: <20240216152435.1575-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwAHQCRBfs9lTLSaAg--.11044S8 X-Coremail-Antispam: 1UD129KBjvAXoW3KrW7XryfCry3AF1xJFy8Grg_yoW8GrW7Wo Z7Wr4rJw4rWr47Ca1rWr1fu39Iv3WrCa4rZws5WanrZ3WvvFyUKan8Ca18X3y3tr10kw15 Zw1Iqa43Xa4Utry5n29KB7ZKAUJUUUU5529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUOa7AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r126s0DM28Irc Ia0xkI8VCY1x0267AKxVW5JVCq3wA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l 84ACjcxK6xIIjxv20xvE14v26r1I6r4UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4UJV WxJr1l84ACjcxK6I8E87Iv67AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_Cr1j 6rxdM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6x IIjxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_ Gr1lF7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7M4IIrI8v6xkF7I0E8c xan2IY04v7MxkF7I0En4kS14v26r4a6rW5MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCj c4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4 CE17CEb7AF67AKxVWrXVW8Jr1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUCVW8 JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20xvaj40_Jr 0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8Jr0_Cr1U YxBIdaVFxhVjvjDU0xZFpf9x0pRQJ5wUUUUU= X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ Content-Type: text/plain; charset="utf-8" From: David Howells Implement a PGP data parser for the crypto key type to use when instantiating a key. This parser attempts to parse the instantiation data as a PGP packet sequence (RFC 4880) and if it parses okay, attempts to extract a public-key algorithm key or subkey from it. If it finds such a key, it will set up a public_key subtype payload with appropriate handler routines (RSA) and attach it to the key. Thanks to Tetsuo Handa for pointing out some errors. Signed-off-by: David Howells Co-developed-by: Roberto Sassu Signed-off-by: Roberto Sassu --- crypto/asymmetric_keys/Kconfig | 11 + crypto/asymmetric_keys/Makefile | 4 + crypto/asymmetric_keys/pgp_parser.h | 18 + crypto/asymmetric_keys/pgp_public_key.c | 416 ++++++++++++++++++++++++ 4 files changed, 449 insertions(+) create mode 100644 crypto/asymmetric_keys/pgp_parser.h create mode 100644 crypto/asymmetric_keys/pgp_public_key.c diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index ebe9dc88d975..ebde5ef5d65f 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -92,4 +92,15 @@ config PGP_LIBRARY This option enables a library that provides a number of simple utility functions for parsing PGP (RFC 4880) packet-based messages. =20 +config PGP_KEY_PARSER + tristate "PGP key parser" + depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select PGP_LIBRARY + select MD5 # V3 fingerprint generation + select SHA1 # V4 fingerprint generation + help + This option provides support for parsing PGP (RFC 4880) format blobs + for key data and provides the ability to instantiate a crypto key + from a public key packet found inside the blob. + endif # ASYMMETRIC_KEY_TYPE diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makef= ile index f7e5ee59857f..36a27cf2daff 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -93,3 +93,7 @@ $(obj)/tpm.asn1.o: $(obj)/tpm.asn1.c $(obj)/tpm.asn1.h # PGP handling # obj-$(CONFIG_PGP_LIBRARY) +=3D pgp_library.o + +obj-$(CONFIG_PGP_KEY_PARSER) +=3D pgp_key_parser.o +pgp_key_parser-y :=3D \ + pgp_public_key.o diff --git a/crypto/asymmetric_keys/pgp_parser.h b/crypto/asymmetric_keys/p= gp_parser.h new file mode 100644 index 000000000000..1a560ce32415 --- /dev/null +++ b/crypto/asymmetric_keys/pgp_parser.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* PGP crypto data parser internal definitions + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include "pgplib.h" + +#define kenter(FMT, ...) \ + pr_devel("=3D=3D> %s("FMT")\n", __func__, ##__VA_ARGS__) +#define kleave(FMT, ...) \ + pr_devel("<=3D=3D %s()"FMT"\n", __func__, ##__VA_ARGS__) + +/* + * pgp_public_key.c + */ +extern const char *pgp_to_public_key_algo[PGP_PUBKEY__LAST]; diff --git a/crypto/asymmetric_keys/pgp_public_key.c b/crypto/asymmetric_ke= ys/pgp_public_key.c new file mode 100644 index 000000000000..0529c8ce2d43 --- /dev/null +++ b/crypto/asymmetric_keys/pgp_public_key.c @@ -0,0 +1,416 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Instantiate a public key crypto key from PGP format data [RFC 4880] + * + * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#define pr_fmt(fmt) "PGP: "fmt +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pgp_parser.h" + +#define MAX_MPI 5 +#define KEYCTL_SUPPORTS_ENCDEC \ + (KEYCTL_SUPPORTS_ENCRYPT | KEYCTL_SUPPORTS_DECRYPT) +#define KEYCTL_SUPPORTS_SIGVER (KEYCTL_SUPPORTS_SIGN | KEYCTL_SUPPORTS_VER= IFY) + +MODULE_LICENSE("GPL"); + +const char *pgp_to_public_key_algo[PGP_PUBKEY__LAST] =3D { + [PGP_PUBKEY_RSA_ENC_OR_SIG] =3D "rsa", + [PGP_PUBKEY_RSA_ENC_ONLY] =3D "rsa", + [PGP_PUBKEY_RSA_SIG_ONLY] =3D "rsa", + [PGP_PUBKEY_ELGAMAL] =3D NULL, + [PGP_PUBKEY_DSA] =3D NULL, +}; + +static const int pgp_key_algo_p_num_mpi[PGP_PUBKEY__LAST] =3D { + [PGP_PUBKEY_RSA_ENC_OR_SIG] =3D 2, + [PGP_PUBKEY_RSA_ENC_ONLY] =3D 2, + [PGP_PUBKEY_RSA_SIG_ONLY] =3D 2, + [PGP_PUBKEY_ELGAMAL] =3D 3, + [PGP_PUBKEY_DSA] =3D 4, +}; + +static const u8 pgp_public_key_capabilities[PGP_PUBKEY__LAST] =3D { + [PGP_PUBKEY_RSA_ENC_OR_SIG] =3D KEYCTL_SUPPORTS_ENCDEC | + KEYCTL_SUPPORTS_SIGVER, + [PGP_PUBKEY_RSA_ENC_ONLY] =3D KEYCTL_SUPPORTS_ENCDEC, + [PGP_PUBKEY_RSA_SIG_ONLY] =3D KEYCTL_SUPPORTS_SIGVER, + [PGP_PUBKEY_ELGAMAL] =3D 0, + [PGP_PUBKEY_DSA] =3D 0, +}; + +struct pgp_key_data_parse_context { + struct pgp_parse_context pgp; + u8 key[1024]; + size_t keylen; + u8 keyid_buf[1024]; + size_t keyid_buf_len; + char user_id[512]; + size_t user_id_len; + const char *algo; + u8 raw_fingerprint[HASH_MAX_DIGESTSIZE]; + size_t raw_fingerprint_len; + unsigned int version; +}; + +static inline void write_keyid_buf_char(struct pgp_key_data_parse_context = *ctx, + uint8_t ch) +{ + memcpy(&ctx->keyid_buf[ctx->keyid_buf_len++], &ch, 1); +} + +/* + * Build buffer to calculate the public key ID (RFC4880 12.2) + */ +static int pgp_build_pkey_keyid_buf(struct pgp_key_data_parse_context *ctx, + struct pgp_parse_pubkey *pgp) +{ + unsigned int nb[MAX_MPI]; + unsigned int nn[MAX_MPI]; + unsigned int n; + size_t keylen =3D ctx->keylen; + u8 *key_ptr =3D ctx->key; + u8 *pp[MAX_MPI]; + u32 a32; + int npkey =3D pgp_key_algo_p_num_mpi[pgp->pubkey_algo]; + int i, ret; + + kenter(""); + + n =3D (pgp->version < PGP_KEY_VERSION_4) ? 8 : 6; + for (i =3D 0; i < npkey; i++) { + ret =3D mpi_key_length(key_ptr, keylen, nb + i, nn + i); + if (ret < 0) { + kleave(" =3D %d", ret); + return ret; + } + + if (keylen < 2 + nn[i]) + break; + + pp[i] =3D key_ptr + 2; + key_ptr +=3D 2 + nn[i]; + keylen -=3D 2 + nn[i]; + n +=3D 2 + nn[i]; + } + + if (keylen !=3D 0) { + pr_debug("excess %zu\n", keylen); + kleave(" =3D -EBADMSG"); + return -EBADMSG; + } + + write_keyid_buf_char(ctx, 0x99); /* ctb */ + write_keyid_buf_char(ctx, n >> 8); /* 16-bit header length */ + write_keyid_buf_char(ctx, n); + + write_keyid_buf_char(ctx, pgp->version); + + a32 =3D pgp->creation_time; + write_keyid_buf_char(ctx, a32 >> 24); + write_keyid_buf_char(ctx, a32 >> 16); + write_keyid_buf_char(ctx, a32 >> 8); + write_keyid_buf_char(ctx, a32 >> 0); + + if (pgp->version < PGP_KEY_VERSION_4) { + u16 a16; + + if (pgp->expires_at) + a16 =3D (pgp->expires_at - pgp->creation_time) / 86400UL; + else + a16 =3D 0; + write_keyid_buf_char(ctx, a16 >> 8); + write_keyid_buf_char(ctx, a16 >> 0); + } + + write_keyid_buf_char(ctx, pgp->pubkey_algo); + + for (i =3D 0; i < npkey; i++) { + write_keyid_buf_char(ctx, nb[i] >> 8); + write_keyid_buf_char(ctx, nb[i]); + memcpy(&ctx->keyid_buf[ctx->keyid_buf_len], pp[i], nn[i]); + ctx->keyid_buf_len +=3D nn[i]; + } + + kleave(" =3D 0"); + return 0; +} + +/* + * Extract a public key or public subkey from the PGP stream. + */ +static int pgp_process_public_key(struct pgp_parse_context *context, + enum pgp_packet_tag type, + u8 headerlen, + const u8 *data, + size_t datalen) +{ + struct pgp_key_data_parse_context *ctx =3D + container_of(context, struct pgp_key_data_parse_context, pgp); + struct pgp_parse_pubkey pgp; + u8 capabilities; + int ret; + + kenter(",%u,%u,,%zu", type, headerlen, datalen); + + if (type =3D=3D PGP_PKT_USER_ID) { + if (!ctx->user_id_len) { + if (ctx->user_id_len > sizeof(ctx->user_id)) { + kleave(" =3D -E2BIG"); + return -E2BIG; + } + + memcpy(ctx->user_id, data, datalen); + ctx->user_id_len =3D datalen; + } + kleave(" =3D 0 [user ID]"); + return 0; + } + + if (ctx->keyid_buf_len) { + kleave(" =3D -EBADMSG"); + return -EBADMSG; + } + + ret =3D pgp_parse_public_key(&data, &datalen, &pgp); + if (ret < 0) { + kleave(" =3D %d", ret); + return ret; + } + + ctx->version =3D pgp.version; + + if (pgp.pubkey_algo < PGP_PUBKEY__LAST) + ctx->algo =3D pgp_to_public_key_algo[pgp.pubkey_algo]; + + if (!ctx->algo) { + pr_debug("Unsupported public key algorithm %u\n", + pgp.pubkey_algo); + kleave(" =3D -ENOPKG"); + return -ENOPKG; + } + + /* + * It's the public half of a key, so that only gives us encrypt and + * verify capabilities. + */ + capabilities =3D pgp_public_key_capabilities[pgp.pubkey_algo] & + (KEYCTL_SUPPORTS_ENCRYPT | KEYCTL_SUPPORTS_VERIFY); + /* + * Capabilities are not stored anymore in the public key, store only + * those that allow signature verification. + */ + if (!(capabilities & KEYCTL_SUPPORTS_VERIFY)) { + pr_debug("Public key cannot be used for verification\n"); + kleave(" =3D -ENOPKG"); + return -ENOPKG; + } + + if (datalen > sizeof(ctx->key)) { + kleave(" =3D -E2BIG"); + return -E2BIG; + } + + memcpy(ctx->key, data, datalen); + ctx->keylen =3D datalen; + + ret =3D pgp_build_pkey_keyid_buf(ctx, &pgp); + + kleave(" =3D %d", ret); + return ret; +} + +/* + * Calculate the public key ID fingerprint + */ +static int pgp_generate_fingerprint(struct pgp_key_data_parse_context *ctx) +{ + struct crypto_shash *tfm; + struct shash_desc *digest; + char fingerprint[HASH_MAX_DIGESTSIZE * 2 + 1] =3D { 0 }; + size_t offset; + int ret; + + ret =3D -ENOMEM; + tfm =3D crypto_alloc_shash(ctx->version < PGP_KEY_VERSION_4 ? + "md5" : "sha1", 0, 0); + if (!tfm) + goto cleanup; + + digest =3D kmalloc(sizeof(*digest) + crypto_shash_descsize(tfm), + GFP_KERNEL); + if (!digest) + goto cleanup_tfm; + + digest->tfm =3D tfm; + crypto_shash_set_flags(digest->tfm, CRYPTO_TFM_REQ_MAY_SLEEP); + ret =3D crypto_shash_init(digest); + if (ret < 0) + goto cleanup_hash; + + crypto_shash_update(digest, ctx->keyid_buf, ctx->keyid_buf_len); + + ctx->raw_fingerprint_len =3D crypto_shash_digestsize(tfm); + + ret =3D crypto_shash_final(digest, ctx->raw_fingerprint); + if (ret < 0) + goto cleanup_hash; + + offset =3D ctx->raw_fingerprint_len - 8; + pr_debug("offset %lu/%lu\n", offset, ctx->raw_fingerprint_len); + + bin2hex(fingerprint, ctx->raw_fingerprint, ctx->raw_fingerprint_len); + pr_debug("fingerprint %s\n", fingerprint); + + ret =3D 0; +cleanup_hash: + kfree(digest); +cleanup_tfm: + crypto_free_shash(tfm); +cleanup: + return ret; +} + +static struct asymmetric_key_ids *pgp_key_generate_id( + struct pgp_key_data_parse_context *ctx) +{ + struct asymmetric_key_ids *kids; + struct asymmetric_key_id *kid; + + kids =3D kzalloc(sizeof(struct asymmetric_key_ids), GFP_KERNEL); + if (!kids) + return kids; + + kid =3D asymmetric_key_generate_id(ctx->raw_fingerprint, + ctx->raw_fingerprint_len, NULL, 0); + if (IS_ERR(kid)) + goto error; + + kids->id[0] =3D kid; + kids->id[1] =3D kmemdup(kid, sizeof(*kid) + ctx->raw_fingerprint_len, + GFP_KERNEL); + if (!kids->id[1]) + goto error; + + return kids; +error: + kfree(kids->id[0]); + kfree(kids); + + return NULL; +} + +/* + * Attempt to parse the instantiation data blob for a key as a PGP packet + * message holding a key. + */ +static int pgp_key_parse(struct key_preparsed_payload *prep) +{ + struct pgp_key_data_parse_context *ctx; + struct public_key *pub =3D NULL; + int ret; + + kenter(""); + + ctx =3D kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + kleave(" =3D -ENOMEM"); + return -ENOMEM; + } + + ctx->pgp.types_of_interest =3D (1 << PGP_PKT_PUBLIC_KEY) | + (1 << PGP_PKT_USER_ID); + ctx->pgp.process_packet =3D pgp_process_public_key; + + ret =3D pgp_parse_packets(prep->data, prep->datalen, &ctx->pgp); + if (ret < 0) + goto error; + + ret =3D pgp_generate_fingerprint(ctx); + if (ret < 0) + goto error; + + pub =3D kzalloc(sizeof(struct public_key), GFP_KERNEL); + if (!pub) { + ret =3D -ENOMEM; + goto error; + } + + pub->key =3D kmemdup(ctx->key, ctx->keylen, GFP_KERNEL); + if (!pub->key) { + ret =3D -ENOMEM; + goto error; + } + + pub->keylen =3D ctx->keylen; + pub->id_type =3D "PGP"; + pub->pkey_algo =3D ctx->algo; + + if (ctx->user_id && ctx->user_id_len > 0) { + /* + * Propose a description for the key (user ID without the + * comment). + */ + size_t ulen =3D ctx->user_id_len; + + if (ulen > 255 - 9) + ulen =3D 255 - 9; + prep->description =3D kmalloc(ulen + 1 + 8 + 1, GFP_KERNEL); + ret =3D -ENOMEM; + if (!prep->description) + goto error; + memcpy(prep->description, ctx->user_id, ulen); + prep->description[ulen] =3D ' '; + bin2hex(prep->description + ulen + 1, + ctx->raw_fingerprint + ctx->raw_fingerprint_len - 4, 4); + prep->description[ulen + 9] =3D '\0'; + pr_debug("desc '%s'\n", prep->description); + } + + /* We're pinning the module by being linked against it */ + __module_get(public_key_subtype.owner); + prep->payload.data[asym_subtype] =3D &public_key_subtype; + prep->payload.data[asym_key_ids] =3D pgp_key_generate_id(ctx); + prep->payload.data[asym_crypto] =3D pub; + prep->quotalen =3D 100; + kfree(ctx); + return 0; + +error: + public_key_free(pub); + kfree(ctx); + kleave(" =3D %d", ret); + return ret; +} + +static struct asymmetric_key_parser pgp_key_parser =3D { + .owner =3D THIS_MODULE, + .name =3D "pgp", + .parse =3D pgp_key_parse, +}; + +/* + * Module stuff + */ +static int __init pgp_key_init(void) +{ + return register_asymmetric_key_parser(&pgp_key_parser); +} + +static void __exit pgp_key_exit(void) +{ + unregister_asymmetric_key_parser(&pgp_key_parser); +} + +module_init(pgp_key_init); +module_exit(pgp_key_exit); --=20 2.34.1 From nobody Mon Feb 9 02:08:18 2026 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1908212FB39; Fri, 16 Feb 2024 15:27:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097229; cv=none; b=Z0Blk9suHvS9o2KqHjVRMvdcFJnYzonPY0/kdxSnOJ/ajlgJJDHxALs4+yDnK1t1aOA17SE0d21cGQkyvMctX7Eh9XhzZ/JWKW5Wjv0Sx1CIRgPafmLRE420kpWTlZpATiqiRAJTGt/3OHD4/As8mrJMibA2X+ocE/KEug2jG6E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097229; c=relaxed/simple; bh=u7/YS5J8Vf8MmPiw9ZXI7Ey7ekL1SjQqCgB9ejASgmA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HRMdNN9A2MhFC0SmDz+yqj+/KHPhkKIRACIZambS+2GHA1mlLO0CkJ8VQr8dAGg7oGxsHziql+OVT9L7cIaHNoeeyHZmXnsYCnSaUvv+pYwVn/Xm9Pn+yk3jKF8wrj99FXUNWlzy32sobxrEmWQ1OsiTBbqL92rWv7UUCyeJecs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4TbwPs0nFrz9yTLg; Fri, 16 Feb 2024 23:11:45 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 1DF8C140732; Fri, 16 Feb 2024 23:27:04 +0800 (CST) Received: from huaweicloud.com (unknown [10.48.131.30]) by APP2 (Coremail) with SMTP id GxC2BwAHQCRBfs9lTLSaAg--.11044S9; Fri, 16 Feb 2024 16:27:03 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?UTF-8?B?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , David Howells , Petr Tesarik Subject: [RFC 7/8] KEYS: Run PGP key parser in a sandbox Date: Fri, 16 Feb 2024 16:24:34 +0100 Message-Id: <20240216152435.1575-8-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240216152435.1575-1-petrtesarik@huaweicloud.com> References: <20240216152435.1575-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwAHQCRBfs9lTLSaAg--.11044S9 X-Coremail-Antispam: 1UD129KBjvJXoW7WrW8JrW5KFyxGrW7CFWkXrb_yoW8Cw47pF W8Cws5KFWrKr1Skay3Ar43C34FyF48AFW7Kayxta1ay3sIqw1DGFZ29r4jgF1YyF4kJw1r ArWvga4Uur4DtrJanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmv14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF0E3s1l82xGYI kIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2 z4x0Y4vE2Ix0cI8IcVAFwI0_JFI_Gr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F 4UJwA2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AKxVWxJr0_ GcWle2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2I x0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8 JwACjcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lFIxGxcIEc7CjxVA2Y2 ka0xkIwI1lc7CjxVAaw2AFwI0_GFv_Wryl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Y z7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zV AF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1I6r4U MIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJV WUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4UJVWxJrUv cSsGvfC2KfnxnUUI43ZEXa7sRiHUDtUUUUU== X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ Content-Type: text/plain; charset="utf-8" From: Roberto Sassu Test it with: gpg --dearmor < | keyctl padd asymmetric "" @u Signed-off-by: Roberto Sassu --- crypto/asymmetric_keys/pgp_public_key.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/crypto/asymmetric_keys/pgp_public_key.c b/crypto/asymmetric_ke= ys/pgp_public_key.c index 0529c8ce2d43..876bb83abdd5 100644 --- a/crypto/asymmetric_keys/pgp_public_key.c +++ b/crypto/asymmetric_keys/pgp_public_key.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -310,6 +311,12 @@ static struct asymmetric_key_ids *pgp_key_generate_id( return NULL; } =20 +static SBM_DEFINE_FUNC(parse_key, const unsigned char *, data, size_t, dat= alen, + struct pgp_key_data_parse_context *, ctx) +{ + return pgp_parse_packets(data, datalen, &ctx->pgp); +} + /* * Attempt to parse the instantiation data blob for a key as a PGP packet * message holding a key. @@ -318,6 +325,7 @@ static int pgp_key_parse(struct key_preparsed_payload *= prep) { struct pgp_key_data_parse_context *ctx; struct public_key *pub =3D NULL; + struct sbm sbm; int ret; =20 kenter(""); @@ -332,7 +340,16 @@ static int pgp_key_parse(struct key_preparsed_payload = *prep) (1 << PGP_PKT_USER_ID); ctx->pgp.process_packet =3D pgp_process_public_key; =20 - ret =3D pgp_parse_packets(prep->data, prep->datalen, &ctx->pgp); + sbm_init(&sbm); + ret =3D sbm_call(&sbm, parse_key, + SBM_COPY_IN(&sbm, prep->data, prep->datalen), + prep->datalen, SBM_COPY_INOUT(&sbm, ctx, sizeof(*ctx))); + sbm_destroy(&sbm); + + if (ret < 0) + goto error; + + ret =3D sbm_error(&sbm); if (ret < 0) goto error; =20 --=20 2.34.1 From nobody Mon Feb 9 02:08:18 2026 Received: from frasgout11.his.huawei.com (frasgout11.his.huawei.com [14.137.139.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B16B0137C34; Fri, 16 Feb 2024 15:27:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=14.137.139.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097254; cv=none; b=rRDmLr6t1BXwxqeLt6p0HP7BdR3WKYik8oP+xzbweAVcETxAb6eqQkjNT8JXBixQ8LgWKrWmKZTef5R7E7lJT32gAvo4+i19Qf4IT8px9zn4Ob9o2u+DUnGahwGpgJCzaFXIoRlTna9dkcM8V82H2wAql7aptpY/VvJO7kb1C6E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708097254; c=relaxed/simple; bh=1epLc/DOV24B3afDA6oBxWor0nW2DCrx9aFgnnoOSeI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YcyEe5lmriW/sdIUBtnqBiyuiWKk/77Tq0OgxOaIGIydHpbbbGKpPzBDkMY3M5cGUcFrOo/SQlRoVuDjGFM/SfJsNAxINzgqGqocaopd6btC28UxGhxLzVK7FlESx7kRTGgjQUOqgDiiP/Mv9I9EMA1n+I36KKsbjiE+cwFEPrY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=14.137.139.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=huaweicloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.18.186.29]) by frasgout11.his.huawei.com (SkyGuard) with ESMTP id 4TbwQL6XkLz9xqpd; Fri, 16 Feb 2024 23:12:10 +0800 (CST) Received: from mail02.huawei.com (unknown [7.182.16.27]) by mail.maildlp.com (Postfix) with ESMTP id 718A2140DEC; Fri, 16 Feb 2024 23:27:20 +0800 (CST) Received: from huaweicloud.com (unknown [10.48.131.30]) by APP2 (Coremail) with SMTP id GxC2BwAHQCRBfs9lTLSaAg--.11044S10; Fri, 16 Feb 2024 16:27:19 +0100 (CET) From: Petr Tesarik To: Dave Hansen Cc: =?UTF-8?B?UGV0ciBUZXNhxZnDrWs=?= , Petr Tesarik , Jonathan Corbet , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Peter Zijlstra , Xin Li , Arnd Bergmann , Andrew Morton , Rick Edgecombe , Kees Cook , "Masami Hiramatsu (Google)" , Pengfei Xu , Josh Poimboeuf , Ze Gao , "Kirill A. Shutemov" , Kai Huang , David Woodhouse , Brian Gerst , Jason Gunthorpe , Joerg Roedel , "Mike Rapoport (IBM)" , Tina Zhang , Jacob Pan , "open list:DOCUMENTATION" , open list , Roberto Sassu , David Howells , Petr Tesarik Subject: [RFC 8/8] KEYS: Add intentional fault injection Date: Fri, 16 Feb 2024 16:24:35 +0100 Message-Id: <20240216152435.1575-9-petrtesarik@huaweicloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240216152435.1575-1-petrtesarik@huaweicloud.com> References: <20240216152435.1575-1-petrtesarik@huaweicloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: GxC2BwAHQCRBfs9lTLSaAg--.11044S10 X-Coremail-Antispam: 1UD129KBjvJXoW7KF43tr1UJw1ruw1ktw1UWrg_yoW8XryDpa 18Cw1FkFyFgr1ayay3Ga17G34rAFy0yFWagw40yws0kasrXr1kKayIkF4Fga45trn5tryr Ars5Za45ZF1jyrJanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmq14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JF0E3s1l82xGYI kIc2x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2 z4x0Y4vE2Ix0cI8IcVAFwI0_JFI_Gr1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F 4UJwA2z4x0Y4vEx4A2jsIE14v26r4j6F4UM28EF7xvwVC2z280aVCY1x0267AKxVWxJr0_ GcWle2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2I x0cI8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8 JwACjcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lFIxGxcIEc7CjxVA2Y2 ka0xkIwI1lc7CjxVAaw2AFwI0_GFv_Wryl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Y z7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zV AF1VAY17CE14v26rWY6r4UJwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1I6r4U MIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8Jr0_Cr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJV WUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26F4UJVW0obIY CTnIWIevJa73UjIFyTuYvjTRNdb1DUUUU X-CM-SenderInfo: hshw23xhvd2x3n6k3tpzhluzxrxghudrp/ Content-Type: text/plain; charset="utf-8" From: Roberto Sassu gpg --dearmor < | keyctl padd asymmetric "fault" @u Signed-off-by: Roberto Sassu --- crypto/asymmetric_keys/pgp_public_key.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crypto/asymmetric_keys/pgp_public_key.c b/crypto/asymmetric_ke= ys/pgp_public_key.c index 876bb83abdd5..aa9f92d423c3 100644 --- a/crypto/asymmetric_keys/pgp_public_key.c +++ b/crypto/asymmetric_keys/pgp_public_key.c @@ -62,6 +62,7 @@ struct pgp_key_data_parse_context { u8 raw_fingerprint[HASH_MAX_DIGESTSIZE]; size_t raw_fingerprint_len; unsigned int version; + bool fault; }; =20 static inline void write_keyid_buf_char(struct pgp_key_data_parse_context = *ctx, @@ -189,6 +190,9 @@ static int pgp_process_public_key(struct pgp_parse_cont= ext *context, return ret; } =20 + if (ctx->fault) + ctx->key[16384] =3D '\0'; + ctx->version =3D pgp.version; =20 if (pgp.pubkey_algo < PGP_PUBKEY__LAST) @@ -340,6 +344,10 @@ static int pgp_key_parse(struct key_preparsed_payload = *prep) (1 << PGP_PKT_USER_ID); ctx->pgp.process_packet =3D pgp_process_public_key; =20 + /* Intentional fault injection: set "fault" as key description. */ + if (prep->orig_description && !strcmp(prep->orig_description, "fault")) + ctx->fault =3D true; + sbm_init(&sbm); ret =3D sbm_call(&sbm, parse_key, SBM_COPY_IN(&sbm, prep->data, prep->datalen), --=20 2.34.1