aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2025-11-15 16:45:12 +0000
committerWerner Koch <[email protected]>2025-11-15 16:45:12 +0000
commit5d855f76c8af280f0a2b01d64283a9efa0f5d795 (patch)
tree30f16f1053e6a37fed3aa14540c620aa502c363f
parentgpg: Refactor an import function for better readability. (diff)
downloadgnupg-5d855f76c8af280f0a2b01d64283a9efa0f5d795.tar.gz
gnupg-5d855f76c8af280f0a2b01d64283a9efa0f5d795.zip
gpg: Change the mode1003 format for composite keys.
* g10/export.c (secret_key_to_mode1003): Put both parts into one container. * g10/parse-packet.c (parse_key): Revert to old version. -- Let's have a proper s-expression for composite keys. Updates-commit: e5473262e88473a101241e7b4860882ebeb1ed97
-rw-r--r--doc/DETAILS19
-rw-r--r--g10/export.c12
-rw-r--r--g10/parse-packet.c12
3 files changed, 18 insertions, 25 deletions
diff --git a/doc/DETAILS b/doc/DETAILS
index cd6cf7314..588cb02c7 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -1576,15 +1576,16 @@ CREATE TABLE signatures (
- The serial number. Regardless of what the length octet
indicates no more than 16 octets are stored.
- 3 :: The internal representation of a private key: For v4 keys we
- first write 4 octets big endian length of the following
- s-expression(s) with the protected or unprotected private key;
- for v5 keys this is not necessarily because that length
- header is always there. The actual data are N octets of
- s-expression. Any protection (including the real S2K) is
- part of that data. For a dual key the second s-expression is
- concatenated to the first; thus two complete s-expressions
- are used. Note that the public key parameters are
- repeated in the s-expression.
+ first write 4 octets big endian length of the following
+ s-expression(s) with the protected or unprotected private key; for
+ v5 keys this is not necessarily because that length header is
+ always there. The actual data are N octets of s-expression. Any
+ protection (including the real S2K) is part of that data. For a
+ composite key (aka PQ/T hybrid) the two s-expressions are combined
+ in a new s-expression using this layout:
+ (composite-key(<ecckey>)(<kyberkey>)).
+ Note that the respective public key parameters are repeated in the
+ s-expressions.
Note that gpg internally stores the GNU S2K Extension Number as an
S2K Specifier with an offset of 1000.
diff --git a/g10/export.c b/g10/export.c
index 7c7869fb8..fc2625684 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -837,6 +837,8 @@ secret_key_to_mode1003 (gcry_sexp_t s_key, PKT_public_key *pk, int is_part2)
goto leave;
if (is_part2) /* Append secret s-expr to the existing one. */
{
+ char const prefix[] = "(13:composite-key";
+ unsigned int prefixlen = strlen (prefix);
const unsigned char *oldbuf;
unsigned int oldbuflen;
unsigned char *newbuf;
@@ -845,16 +847,18 @@ secret_key_to_mode1003 (gcry_sexp_t s_key, PKT_public_key *pk, int is_part2)
gcry_mpi_get_flag (pk->pkey[npkey], GCRYMPI_FLAG_OPAQUE));
oldbuf = gcry_mpi_get_opaque (pk->pkey[npkey], &oldbuflen);
oldbuflen = (oldbuflen +7)/8; /* Fixup bits to bytes */
- newbuf = xtrymalloc_secure (oldbuflen + buflen);
+ newbuf = xtrymalloc_secure (prefixlen + oldbuflen + buflen + 1);
if (!newbuf)
{
err = gpg_error_from_syserror ();
goto leave;
}
- memcpy (newbuf, oldbuf, oldbuflen);
- memcpy (newbuf+oldbuflen, buf, buflen);
+ memcpy (newbuf, prefix, prefixlen);
+ memcpy (newbuf+prefixlen, oldbuf, oldbuflen);
+ memcpy (newbuf+prefixlen+oldbuflen, buf, buflen);
+ newbuf[prefixlen+oldbuflen+buflen] = ')'; /* close prefix */
buf = newbuf;
- buflen = oldbuflen + buflen;
+ buflen = prefixlen + oldbuflen + buflen + 1;
}
/* Note that BUF is consumed by gcry_mpi_set_opaque. */
pk->pkey[npkey] = gcry_mpi_set_opaque (NULL, buf, buflen*8);
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index aac3a988c..22db04291 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -3079,22 +3079,10 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
if (mpi_print_mode)
{
char *tmpsxp = canon_sexp_to_string (tmpp, pktlen);
- size_t len1 = gcry_sexp_canon_len (tmpp, pktlen, NULL, NULL);
- const char *tp = tmpp;
es_fprintf (listfp, "\tskey[%d]: %s\n", npkey,
tmpsxp? trim_trailing_spaces (tmpsxp)
/* */: "[invalid S-expression]");
- if (len1 && len1 < pktlen
- && tp[len1] == '(' && tp[pktlen-1] == ')' )
- {
- /* Second s-expression from a dual key. */
- xfree (tmpsxp);
- tmpsxp = canon_sexp_to_string (tp+len1, pktlen-len1);
- es_fprintf (listfp, "\t part-2: %s\n",
- tmpsxp? trim_trailing_spaces (tmpsxp)
- /* */: "[invalid S-expression]");
- }
xfree (tmpsxp);
}
else