From 1a85ee9a431bd2243e0ad79ce5eefa78e274a491 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 2 Dec 2022 10:03:36 +0100 Subject: gpg: New export option "mode1003". * agent/command.c (cmd_export_key): Add option --mode1003. (command_has_option): Ditto. * g10/build-packet.c (do_key): Implement mode 1003. * g10/parse-packet.c (parse_key): Ditto. * g10/options.h (EXPORT_MODE1003): New.o * g10/call-agent.c (agent_export_key): Add arg mode1003. * g10/export.c (parse_export_options): Add "mode1003" (secret_key_to_mode1003): New. (receive_seckey_from_agent): Add arg mode1003. (do_export_one_keyblock): Pass option down. -- This option allows to export a secret key in GnuPG's native format. Thus no re-encryption is required and further the public key parameters are also authenticated if a protection passphrase has been used. Note that --import is not yet able to handle this new mode. Although old version of GnuPG will bail out with "invalid packet" if a mode1003 exported secret key is seen. --- g10/build-packet.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'g10/build-packet.c') diff --git a/g10/build-packet.c b/g10/build-packet.c index cc953557d..f33d156b3 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -674,7 +674,8 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) count += 8; /* Salt. */ if (ski->s2k.mode == 3) count++; /* S2K.COUNT */ - if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002) + if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002 + && ski->s2k.mode != 1003) count += ski->ivlen; iobuf_put (a, count); @@ -704,8 +705,9 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) if (ski->s2k.mode == 3) iobuf_put (a, ski->s2k.count); - /* For our special modes 1001, 1002 we do not need an IV. */ - if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002) + /* For our special modes 1001..1003 we do not need an IV. */ + if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002 + && ski->s2k.mode != 1003) iobuf_write (a, ski->iv, ski->ivlen); } @@ -733,6 +735,22 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) /* The serial number gets stored in the IV field. */ iobuf_write (a, ski->iv, ski->ivlen); } + else if (ski->s2k.mode == 1003) + { + /* GnuPG extension - Store raw s-expression. */ + byte *p; + unsigned int ndatabits; + + log_assert (gcry_mpi_get_flag (pk->pkey[npkey], GCRYMPI_FLAG_OPAQUE)); + + p = gcry_mpi_get_opaque (pk->pkey[npkey], &ndatabits); + /* For v5 keys we first write the number of octets of the + * following key material. */ + if (is_v5) + write_32 (a, p? (ndatabits+7)/8 : 0); + if (p) + iobuf_write (a, p, (ndatabits+7)/8 ); + } else if (ski->is_protected) { /* The secret key is protected - write it out as it is. */ -- cgit v1.2.3