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/parse-packet.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) (limited to 'g10/parse-packet.c') diff --git a/g10/parse-packet.c b/g10/parse-packet.c index b6aebbb69..a033732ec 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -2752,11 +2752,15 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, break; case 1001: if (list_mode) - es_fprintf (listfp, "\tgnu-dummy S2K"); + es_fprintf (listfp, "\tgnu-dummy"); break; case 1002: if (list_mode) - es_fprintf (listfp, "\tgnu-divert-to-card S2K"); + es_fprintf (listfp, "\tgnu-divert-to-card"); + break; + case 1003: + if (list_mode) + es_fprintf (listfp, "\tgnu-mode1003"); break; default: if (list_mode) @@ -2768,7 +2772,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, } /* Print some info. */ - if (list_mode) + if (list_mode && ski->s2k.mode != 1003) { es_fprintf (listfp, ", algo: %d,%s hash: %d", ski->algo, @@ -2779,8 +2783,9 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, es_fprintf (listfp, ", salt: "); es_write_hexstring (listfp, ski->s2k.salt, 8, 0, NULL); } - es_putc ('\n', listfp); - } + } + if (list_mode) + es_putc ('\n', listfp); /* Read remaining protection parameters. */ if (ski->s2k.mode == 3) @@ -2838,7 +2843,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, ski->ivlen = openpgp_cipher_blocklen (ski->algo); log_assert (ski->ivlen <= sizeof (temp)); - if (ski->s2k.mode == 1001) + if (ski->s2k.mode == 1001 || ski->s2k.mode == 1003) ski->ivlen = 0; else if (ski->s2k.mode == 1002) ski->ivlen = snlen < 16 ? snlen : 16; @@ -2850,7 +2855,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, } for (i = 0; i < ski->ivlen; i++, pktlen--) temp[i] = iobuf_get_noeof (inp); - if (list_mode) + if (list_mode && ski->s2k.mode != 1003) { es_fprintf (listfp, ski->s2k.mode == 1002 ? "\tserial-number: " @@ -2888,6 +2893,35 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, 10 * 8); pktlen = 0; } + else if (ski->s2k.mode == 1003) + { + void *tmpp; + + if (pktlen < 2) /* At least two bytes for parenthesis. */ + { + err = gpg_error (GPG_ERR_INV_PACKET); + goto leave; + } + + tmpp = read_rest (inp, pktlen); + if (list_mode) + { + if (mpi_print_mode) + { + char *tmpsxp = canon_sexp_to_string (tmpp, pktlen); + es_fprintf (listfp, "\tskey[%d]: %s\n", npkey, + tmpsxp? trim_trailing_spaces (tmpsxp) + /* */: "[invalid S-expression]"); + xfree (tmpsxp); + } + else + es_fprintf (listfp, "\tskey[%d]: [s-expression %lu octets]\n", + npkey, pktlen); + } + pk->pkey[npkey] = gcry_mpi_set_opaque (NULL, + tmpp, tmpp? pktlen * 8 : 0); + pktlen = 0; + } else if (ski->is_protected) { void *tmpp; -- cgit v1.2.3