All of lore.kernel.org
 help / color / mirror / Atom feed
From: Roberto Sassu <roberto.sassu@huaweicloud.com>
To: dhowells@redhat.com, dwmw2@infradead.org,
	herbert@gondor.apana.org.au, davem@davemloft.net,
	jarkko@kernel.org, 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


  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.