mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
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.
This commit is contained in:
parent
1d88e14de7
commit
1a85ee9a43
@ -2935,7 +2935,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
|
||||
|
||||
|
||||
static const char hlp_export_key[] =
|
||||
"EXPORT_KEY [--cache-nonce=<nonce>] [--openpgp] <hexstring_with_keygrip>\n"
|
||||
"EXPORT_KEY [--cache-nonce=<nonce>] [--openpgp|--mode1003] <hexkeygrip>\n"
|
||||
"\n"
|
||||
"Export a secret key from the key store. The key will be encrypted\n"
|
||||
"using the current session's key wrapping key (cf. command KEYWRAP_KEY)\n"
|
||||
@ -2943,9 +2943,10 @@ static const char hlp_export_key[] =
|
||||
"prior to using this command. The function takes the keygrip as argument.\n"
|
||||
"\n"
|
||||
"If --openpgp is used, the secret key material will be exported in RFC 4880\n"
|
||||
"compatible passphrase-protected form. Without --openpgp, the secret key\n"
|
||||
"material will be exported in the clear (after prompting the user to unlock\n"
|
||||
"it, if needed).\n";
|
||||
"compatible passphrase-protected form. If --mode1003 is use the secret key\n"
|
||||
"is exported as s-expression as storred locally. Without those options,\n"
|
||||
"the secret key material will be exported in the clear (after prompting\n"
|
||||
"the user to unlock it, if needed).\n";
|
||||
static gpg_error_t
|
||||
cmd_export_key (assuan_context_t ctx, char *line)
|
||||
{
|
||||
@ -2958,7 +2959,7 @@ cmd_export_key (assuan_context_t ctx, char *line)
|
||||
gcry_cipher_hd_t cipherhd = NULL;
|
||||
unsigned char *wrappedkey = NULL;
|
||||
size_t wrappedkeylen;
|
||||
int openpgp;
|
||||
int openpgp, mode1003;
|
||||
char *cache_nonce;
|
||||
char *passphrase = NULL;
|
||||
unsigned char *shadow_info = NULL;
|
||||
@ -2969,6 +2970,10 @@ cmd_export_key (assuan_context_t ctx, char *line)
|
||||
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
|
||||
|
||||
openpgp = has_option (line, "--openpgp");
|
||||
mode1003 = has_option (line, "--mode1003");
|
||||
if (mode1003)
|
||||
openpgp = 0;
|
||||
|
||||
cache_nonce = option_value (line, "--cache-nonce");
|
||||
if (cache_nonce)
|
||||
{
|
||||
@ -3003,7 +3008,13 @@ cmd_export_key (assuan_context_t ctx, char *line)
|
||||
}
|
||||
|
||||
/* Get the key from the file. With the openpgp flag we also ask for
|
||||
the passphrase so that we can use it to re-encrypt it. */
|
||||
* the passphrase so that we can use it to re-encrypt it. In
|
||||
* mode1003 we return the key as-is. FIXME: if the key is still in
|
||||
* OpenPGP-native mode we should first convert it to our internal
|
||||
* protection. */
|
||||
if (mode1003)
|
||||
err = agent_raw_key_from_file (ctrl, grip, &s_skey, NULL);
|
||||
else
|
||||
err = agent_key_from_file (ctrl, cache_nonce,
|
||||
ctrl->server_local->keydesc, grip,
|
||||
&shadow_info, CACHE_MODE_IGNORE, NULL, &s_skey,
|
||||
@ -4150,6 +4161,11 @@ command_has_option (const char *cmd, const char *cmdopt)
|
||||
if (!strcmp (cmdopt, "newsymkey"))
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp (cmd, "EXPORT_KEY"))
|
||||
{
|
||||
if (!strcmp (cmdopt, "mode1003"))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1504,6 +1504,14 @@ CREATE TABLE signatures (
|
||||
- One octet with the length of the following serial number.
|
||||
- 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 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. Note that the public key aparemters are
|
||||
repeated in th s-expression.
|
||||
|
||||
Note that gpg stores the GNU S2K Extension Number internally as an
|
||||
S2K Specifier with an offset of 1000.
|
||||
|
10
doc/gpg.texi
10
doc/gpg.texi
@ -2721,6 +2721,16 @@ opposite meaning. The options are:
|
||||
each record to allow diverting the records to the corresponding zone
|
||||
file.
|
||||
|
||||
@item mode1003
|
||||
Enable the use of a new secret key export format. This format
|
||||
avoids the re-encryption as required with the current OpenPGP format
|
||||
and also improves the security of the secret key if it has been
|
||||
protected with a passphrase. Note that an unprotected key is
|
||||
exported as-is and thus not secure; the general rule to convey
|
||||
secret keys in an OpenPGP encrypted file still applies with this
|
||||
mode. Versions of GnuPG before 2.4.0 are not able to import such a
|
||||
secret file.
|
||||
|
||||
@end table
|
||||
|
||||
@item --with-colons
|
||||
|
@ -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. */
|
||||
|
@ -2997,13 +2997,15 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
|
||||
keygrip, DESC a prompt to be displayed with the agent's passphrase
|
||||
question (needs to be plus+percent escaped). if OPENPGP_PROTECTED
|
||||
is not zero, ensure that the key material is returned in RFC
|
||||
4880-compatible passphrased-protected form. If CACHE_NONCE_ADDR is
|
||||
not NULL the agent is advised to first try a passphrase associated
|
||||
with that nonce. On success the key is stored as a canonical
|
||||
S-expression at R_RESULT and R_RESULTLEN. */
|
||||
4880-compatible passphrased-protected form; if instead MODE1003 is
|
||||
not zero the raw gpg-agent private key format is requested (either
|
||||
protected or unprotected). If CACHE_NONCE_ADDR is not NULL the
|
||||
agent is advised to first try a passphrase associated with that
|
||||
nonce. On success the key is stored as a canonical S-expression at
|
||||
R_RESULT and R_RESULTLEN. */
|
||||
gpg_error_t
|
||||
agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
||||
int openpgp_protected, char **cache_nonce_addr,
|
||||
int openpgp_protected, int mode1003, char **cache_nonce_addr,
|
||||
unsigned char **r_result, size_t *r_resultlen,
|
||||
u32 *keyid, u32 *mainkeyid, int pubkey_algo)
|
||||
{
|
||||
@ -3028,6 +3030,12 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
/* Check that the gpg-agent supports the --mode1003 option. */
|
||||
if (mode1003 && assuan_transact (agent_ctx,
|
||||
"GETINFO cmd_has_option EXPORT_KEY mode1003",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL))
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
|
||||
if (desc)
|
||||
{
|
||||
snprintf (line, DIM(line), "SETKEYDESC %s", desc);
|
||||
@ -3038,7 +3046,7 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
||||
}
|
||||
|
||||
snprintf (line, DIM(line), "EXPORT_KEY %s%s%s %s",
|
||||
openpgp_protected ? "--openpgp ":"",
|
||||
mode1003? "--mode1003" : openpgp_protected ? "--openpgp ":"",
|
||||
cache_nonce_addr && *cache_nonce_addr? "--cache-nonce=":"",
|
||||
cache_nonce_addr && *cache_nonce_addr? *cache_nonce_addr:"",
|
||||
hexkeygrip);
|
||||
|
@ -231,7 +231,7 @@ gpg_error_t agent_import_key (ctrl_t ctrl, const char *desc,
|
||||
/* Receive a key from the agent. */
|
||||
gpg_error_t agent_export_key (ctrl_t ctrl, const char *keygrip,
|
||||
const char *desc, int openpgp_protected,
|
||||
char **cache_nonce_addr,
|
||||
int mode1003, char **cache_nonce_addr,
|
||||
unsigned char **r_result, size_t *r_resultlen,
|
||||
u32 *keyid, u32 *mainkeyid, int pubkey_algo);
|
||||
|
||||
|
202
g10/export.c
202
g10/export.c
@ -2,6 +2,7 @@
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
* 2005, 2010 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998-2016 Werner Koch
|
||||
* Copyright (C) 2022 g10 Code GmbH
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -140,6 +141,9 @@ parse_export_options(char *str,unsigned int *options,int noisy)
|
||||
N_("use the GnuPG key backup format")},
|
||||
{"export-backup", EXPORT_BACKUP, NULL, NULL },
|
||||
|
||||
{"mode1003", EXPORT_MODE1003, NULL,
|
||||
N_("export secret keys using the GnuPG format") },
|
||||
|
||||
/* Aliases for backward compatibility */
|
||||
{"include-local-sigs",EXPORT_LOCAL_SIGS,NULL,NULL},
|
||||
{"include-attributes",EXPORT_ATTRIBUTES,NULL,NULL},
|
||||
@ -639,6 +643,183 @@ canon_pk_algo (enum gcry_pk_algos algo)
|
||||
}
|
||||
|
||||
|
||||
/* Take an s-expression wit the public and private key and change the
|
||||
* parameter array in PK to include the secret parameters. */
|
||||
static gpg_error_t
|
||||
secret_key_to_mode1003 (gcry_sexp_t s_key, PKT_public_key *pk)
|
||||
{
|
||||
gpg_error_t err;
|
||||
gcry_sexp_t list = NULL;
|
||||
gcry_sexp_t l2;
|
||||
enum gcry_pk_algos pk_algo;
|
||||
struct seckey_info *ski;
|
||||
int idx;
|
||||
char *string;
|
||||
size_t npkey, nskey;
|
||||
gcry_mpi_t pub_params[10] = { NULL };
|
||||
|
||||
/* We look for a private-key, then the first element in it tells us
|
||||
the type */
|
||||
list = gcry_sexp_find_token (s_key, "protected-private-key", 0);
|
||||
if (!list)
|
||||
list = gcry_sexp_find_token (s_key, "private-key", 0);
|
||||
if (!list)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
log_assert (!pk->seckey_info);
|
||||
|
||||
/* Parse the gcrypt PK algo and check that it is okay. */
|
||||
l2 = gcry_sexp_cadr (list);
|
||||
if (!l2)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
gcry_sexp_release (list);
|
||||
list = l2;
|
||||
string = gcry_sexp_nth_string (list, 0);
|
||||
if (!string)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
pk_algo = gcry_pk_map_name (string);
|
||||
xfree (string); string = NULL;
|
||||
if (gcry_pk_algo_info (pk_algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &npkey)
|
||||
|| gcry_pk_algo_info (pk_algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &nskey)
|
||||
|| !npkey || npkey >= nskey)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Check that the pubkey algo and the received parameters matches
|
||||
* those from the public key. */
|
||||
switch (canon_pk_algo (pk_algo))
|
||||
{
|
||||
case GCRY_PK_RSA:
|
||||
if (!is_RSA (pk->pubkey_algo) || npkey != 2)
|
||||
err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Does not match. */
|
||||
else
|
||||
err = gcry_sexp_extract_param (list, NULL, "ne",
|
||||
&pub_params[0],
|
||||
&pub_params[1],
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case GCRY_PK_DSA:
|
||||
if (!is_DSA (pk->pubkey_algo) || npkey != 4)
|
||||
err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Does not match. */
|
||||
else
|
||||
err = gcry_sexp_extract_param (list, NULL, "pqgy",
|
||||
&pub_params[0],
|
||||
&pub_params[1],
|
||||
&pub_params[2],
|
||||
&pub_params[3],
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case GCRY_PK_ELG:
|
||||
if (!is_ELGAMAL (pk->pubkey_algo) || npkey != 3)
|
||||
err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Does not match. */
|
||||
else
|
||||
err = gcry_sexp_extract_param (list, NULL, "pgy",
|
||||
&pub_params[0],
|
||||
&pub_params[1],
|
||||
&pub_params[2],
|
||||
NULL);
|
||||
break;
|
||||
|
||||
case GCRY_PK_ECC:
|
||||
err = 0;
|
||||
if (!(pk->pubkey_algo == PUBKEY_ALGO_ECDSA
|
||||
|| pk->pubkey_algo == PUBKEY_ALGO_ECDH
|
||||
|| pk->pubkey_algo == PUBKEY_ALGO_EDDSA))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Does not match. */
|
||||
goto leave;
|
||||
}
|
||||
npkey = 2;
|
||||
if (pk->pubkey_algo == PUBKEY_ALGO_ECDH)
|
||||
npkey++;
|
||||
/* Dedicated check of the curve. */
|
||||
pub_params[0] = NULL;
|
||||
err = match_curve_skey_pk (list, pk);
|
||||
if (err)
|
||||
goto leave;
|
||||
/* ... and of the Q parameter. */
|
||||
err = sexp_extract_param_sos (list, "q", &pub_params[1]);
|
||||
if (!err && (gcry_mpi_cmp (pk->pkey[1], pub_params[1])))
|
||||
err = gpg_error (GPG_ERR_BAD_PUBKEY);
|
||||
break;
|
||||
|
||||
default:
|
||||
err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Unknown. */
|
||||
break;
|
||||
}
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
nskey = npkey + 1; /* We only have one skey param. */
|
||||
if (nskey > PUBKEY_MAX_NSKEY)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Check that the public key parameters match. For ECC we already
|
||||
* did this in the switch above. */
|
||||
if (canon_pk_algo (pk_algo) != GCRY_PK_ECC)
|
||||
{
|
||||
for (idx=0; idx < npkey; idx++)
|
||||
if (gcry_mpi_cmp (pk->pkey[idx], pub_params[idx]))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_BAD_PUBKEY);
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the maybe protected secret key as an s-expression. */
|
||||
pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
|
||||
if (!ski)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
|
||||
if (!ski)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
ski->is_protected = 1;
|
||||
ski->s2k.mode = 1003;
|
||||
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t buflen;
|
||||
|
||||
err = make_canon_sexp (s_key, &buf, &buflen);
|
||||
if (err)
|
||||
goto leave;
|
||||
pk->pkey[npkey] = gcry_mpi_set_opaque (NULL, buf, buflen*8);
|
||||
for (idx=npkey+1; idx < PUBKEY_MAX_NSKEY; idx++)
|
||||
pk->pkey[idx] = NULL;
|
||||
}
|
||||
|
||||
leave:
|
||||
gcry_sexp_release (list);
|
||||
for (idx=0; idx < DIM(pub_params); idx++)
|
||||
gcry_mpi_release (pub_params[idx]);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Take a cleartext dump of a secret key in PK and change the
|
||||
* parameter array in PK to include the secret parameters. */
|
||||
static gpg_error_t
|
||||
@ -1248,6 +1429,11 @@ print_status_exported (PKT_public_key *pk)
|
||||
* passphrase-protected. Otherwise, store secret key material in the
|
||||
* clear.
|
||||
*
|
||||
* If MODE1003 is set, the key is requested in raw GnuPG format from
|
||||
* the agent. This usually does not require a passphrase unless the
|
||||
* gpg-agent has not yet used the key and needs to convert it to its
|
||||
* internal format first.
|
||||
*
|
||||
* CACHE_NONCE_ADDR is used to share nonce for multiple key retrievals.
|
||||
*
|
||||
* If PK is NULL, the raw key is returned (e.g. for ssh export) at
|
||||
@ -1255,7 +1441,7 @@ print_status_exported (PKT_public_key *pk)
|
||||
*/
|
||||
gpg_error_t
|
||||
receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
|
||||
int cleartext,
|
||||
int cleartext, int mode1003,
|
||||
char **cache_nonce_addr, const char *hexgrip,
|
||||
PKT_public_key *pk, gcry_sexp_t *r_key)
|
||||
{
|
||||
@ -1275,7 +1461,7 @@ receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
|
||||
if (pk)
|
||||
{
|
||||
prompt = gpg_format_keydesc (ctrl, pk, FORMAT_KEYDESC_EXPORT, 1);
|
||||
err = agent_export_key (ctrl, hexgrip, prompt, !cleartext,
|
||||
err = agent_export_key (ctrl, hexgrip, prompt, !cleartext, mode1003,
|
||||
cache_nonce_addr,
|
||||
&wrappedkey, &wrappedkeylen,
|
||||
pk->keyid, pk->main_keyid, pk->pubkey_algo);
|
||||
@ -1283,7 +1469,7 @@ receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
|
||||
else
|
||||
{
|
||||
prompt = gpg_format_keydesc (ctrl, NULL, FORMAT_KEYDESC_KEYGRIP, 1);
|
||||
err = agent_export_key (ctrl, hexgrip, prompt, 0,
|
||||
err = agent_export_key (ctrl, hexgrip, prompt, 0, 0,
|
||||
NULL,
|
||||
&wrappedkey, &wrappedkeylen,
|
||||
NULL, NULL, 0);
|
||||
@ -1314,7 +1500,9 @@ receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
|
||||
err = gcry_sexp_sscan (&s_skey, NULL, key, realkeylen);
|
||||
if (!err)
|
||||
{
|
||||
if (pk && cleartext)
|
||||
if (pk && mode1003)
|
||||
err = secret_key_to_mode1003 (s_skey, pk);
|
||||
else if (pk && cleartext)
|
||||
err = cleartext_secret_key_to_openpgp (s_skey, pk);
|
||||
else if (pk)
|
||||
err = transfer_format_to_openpgp (s_skey, pk);
|
||||
@ -1832,7 +2020,9 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
|
||||
else if (!err)
|
||||
{
|
||||
err = receive_seckey_from_agent (ctrl, cipherhd,
|
||||
cleartext, &cache_nonce,
|
||||
cleartext,
|
||||
!!(options & EXPORT_MODE1003),
|
||||
&cache_nonce,
|
||||
hexgrip, pk, NULL);
|
||||
if (err)
|
||||
{
|
||||
@ -2781,7 +2971,7 @@ export_secret_ssh_key (ctrl_t ctrl, const char *userid)
|
||||
if ((err = get_keywrap_key (ctrl, &cipherhd)))
|
||||
goto leave;
|
||||
|
||||
err = receive_seckey_from_agent (ctrl, cipherhd, 0, NULL, hexgrip, NULL,
|
||||
err = receive_seckey_from_agent (ctrl, cipherhd, 0, 0, NULL, hexgrip, NULL,
|
||||
&skey);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
@ -5286,7 +5286,7 @@ card_store_key_with_backup (ctrl_t ctrl, PKT_public_key *sub_psk,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = receive_seckey_from_agent (ctrl, cipherhd, 0,
|
||||
err = receive_seckey_from_agent (ctrl, cipherhd, 0, 0,
|
||||
&cache_nonce, hexgrip, sk, NULL);
|
||||
if (err)
|
||||
{
|
||||
|
@ -431,7 +431,7 @@ gpg_error_t export_pubkey_buffer (ctrl_t ctrl, const char *keyspec,
|
||||
void **r_data, size_t *r_datalen);
|
||||
|
||||
gpg_error_t receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
|
||||
int cleartext,
|
||||
int cleartext, int mode1003,
|
||||
char **cache_nonce_addr,
|
||||
const char *hexgrip,
|
||||
PKT_public_key *pk, gcry_sexp_t *r_key);
|
||||
|
@ -407,6 +407,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
|
||||
#define EXPORT_DANE_FORMAT (1<<7)
|
||||
#define EXPORT_BACKUP (1<<10)
|
||||
#define EXPORT_REVOCS (1<<11)
|
||||
#define EXPORT_MODE1003 (1<<12)
|
||||
|
||||
#define LIST_SHOW_PHOTOS (1<<0)
|
||||
#define LIST_SHOW_POLICY_URLS (1<<1)
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user