From: Roberto Sassu <roberto.sassu@huaweicloud.com>
To: dhowells@redhat.com, dwmw2@infradead.org,
herbert@gondor.apana.org.au, davem@davemloft.net,
jarkko@kernel.org, zohar@linux.ibm.com,
dmitry.kasatkin@gmail.com, paul@paul-moore.com,
jmorris@namei.org, serge@hallyn.com
Cc: linux-kernel@vger.kernel.org, keyrings@vger.kernel.org,
linux-crypto@vger.kernel.org, linux-integrity@vger.kernel.org,
linux-security-module@vger.kernel.org, pbrobinson@gmail.com,
zbyszek@in.waw.pl, wiktor@metacode.biz,
devel@lists.sequoia-pgp.org, gnupg-devel@gnupg.org,
ebiggers@kernel.org, Jason@zx2c4.com, mail@maciej.szmigiero.name,
antony@vennard.ch, konstantin@linuxfoundation.org,
James.Bottomley@HansenPartnership.com,
Roberto Sassu <roberto.sassu@huawei.com>
Subject: [RFC][GNUPG][PATCH v3 2/2] Convert PGP signatures to the user asymmetric key signatures format
Date: Thu, 20 Jul 2023 17:32:47 +0200 [thread overview]
Message-ID: <20230720153247.3755856-12-roberto.sassu@huaweicloud.com> (raw)
In-Reply-To: <20230720153247.3755856-1-roberto.sassu@huaweicloud.com>
From: Roberto Sassu <roberto.sassu@huawei.com>
Enhance the gpg command --conv-kernel to also support converting PGP
signatures to the user asymmetric key signatures format.
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
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 8f2fc40b980..be7eb3c80f8 100644
--- a/g10/conv-packet.c
+++ b/g10/conv-packet.c
@@ -28,6 +28,8 @@
#include <linux/uasym_parser.h>
#include <asm/byteorder.h>
#include <linux/pub_key_info.h>
+#include <linux/sig_enc_info.h>
+#include <linux/hash_info.h>
#include "gpg.h"
#include "../common/util.h"
@@ -38,6 +40,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)
@@ -282,3 +294,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 tlv_hdr hdr = { 0 };
+ struct tlv_entry e_key_algo = { 0 };
+ struct tlv_entry e_hash_algo = { 0 };
+ struct tlv_entry e_sig_encoding = { 0 };
+ struct tlv_entry e_sig_kid0 = { 0 };
+ struct tlv_entry e_sig_pub = { 0 };
+ struct tlv_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_be64(SIG_KEY_ALGO);
+ e_key_algo.length = __cpu_to_be64(sizeof(pkey_algo));
+ total_len += sizeof(e_key_algo) + sizeof(pkey_algo);
+
+ /* sig hash algo */
+ e_hash_algo.field = __cpu_to_be64(SIG_HASH_ALGO);
+ e_hash_algo.length = __cpu_to_be64(sizeof(hash_algo));
+ total_len += sizeof(e_hash_algo) + sizeof(hash_algo);
+
+ /* sig encoding */
+ e_sig_encoding.field = __cpu_to_be64(SIG_ENC);
+ e_sig_encoding.length = __cpu_to_be64(sizeof(sig_encoding));
+ total_len += sizeof(e_sig_encoding) + sizeof(sig_encoding);
+
+ /* sig kid0 */
+ e_sig_kid0.field = __cpu_to_be64(SIG_KID0);
+ e_sig_kid0.length = __cpu_to_be64(2 * sizeof(*sig->keyid));
+ total_len += sizeof(e_sig_kid0) + 2 * sizeof(*sig->keyid);
+
+ /* sig data */
+ e_sig_data.field = __cpu_to_be64(SIG_DATA_END);
+ ret = get_sig_data(sig, &sig_data, &sig_data_len);
+ if (ret < 0)
+ goto out;
+
+ e_sig_data.length = __cpu_to_be64(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_be64(SIG_S);
+ e_sig_pub.length = __cpu_to_be64(buffer_len_padded);
+ total_len += sizeof(e_sig_pub) + buffer_len_padded;
+
+ hdr.data_type = __cpu_to_be64(TYPE_SIG);
+ hdr.num_fields = __cpu_to_be64(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);
--
2.34.1
next prev parent reply other threads:[~2023-07-20 15:37 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-20 15:32 [RFC][PATCH v3 0/9] KEYS: Introduce user asymmetric keys and signatures Roberto Sassu
2023-07-20 15:32 ` [RFC][PATCH v3 1/9] lib: Add TLV parser Roberto Sassu
2023-07-20 15:32 ` [RFC][PATCH v3 2/9] crypto: Export public key algorithm information Roberto Sassu
2023-07-20 15:32 ` [RFC][PATCH v3 3/9] crypto: Export signature encoding information Roberto Sassu
2023-07-20 15:32 ` [RFC][PATCH v3 4/9] KEYS: asymmetric: Introduce the user asymmetric key parser Roberto Sassu
2023-07-20 15:32 ` [RFC][PATCH v3 5/9] KEYS: asymmetric: Introduce the user asymmetric key signature parser Roberto Sassu
2023-07-20 15:32 ` [RFC][PATCH v3 6/9] verification: Add verify_uasym_signature() and verify_uasym_sig_message() Roberto Sassu
2023-07-20 15:32 ` [RFC][PATCH v3 7/9] KEYS: asymmetric: Preload user asymmetric keys from a keyring blob Roberto Sassu
2023-07-20 15:32 ` [RFC][PATCH v3 8/9] KEYS: Introduce load_uasym_keyring() Roberto Sassu
2023-07-20 15:32 ` [RFC][PATCH v3 9/9] ima: Support non-PKCS#7 modsig types Roberto Sassu
2023-07-20 15:32 ` [RFC][GNUPG][PATCH v3 1/2] Convert PGP keys to the user asymmetric keys format Roberto Sassu
2023-07-20 15:32 ` Roberto Sassu [this message]
2023-07-20 17:38 ` [RFC][PATCH v3 0/9] KEYS: Introduce user asymmetric keys and signatures Jarkko Sakkinen
2023-07-21 7:04 ` Roberto Sassu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230720153247.3755856-12-roberto.sassu@huaweicloud.com \
--to=roberto.sassu@huaweicloud.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=Jason@zx2c4.com \
--cc=antony@vennard.ch \
--cc=davem@davemloft.net \
--cc=devel@lists.sequoia-pgp.org \
--cc=dhowells@redhat.com \
--cc=dmitry.kasatkin@gmail.com \
--cc=dwmw2@infradead.org \
--cc=ebiggers@kernel.org \
--cc=gnupg-devel@gnupg.org \
--cc=herbert@gondor.apana.org.au \
--cc=jarkko@kernel.org \
--cc=jmorris@namei.org \
--cc=keyrings@vger.kernel.org \
--cc=konstantin@linuxfoundation.org \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=mail@maciej.szmigiero.name \
--cc=paul@paul-moore.com \
--cc=pbrobinson@gmail.com \
--cc=roberto.sassu@huawei.com \
--cc=serge@hallyn.com \
--cc=wiktor@metacode.biz \
--cc=zbyszek@in.waw.pl \
--cc=zohar@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).