1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

agent: Make --disable-extended-key-format a dummy option.

* agent/agent.h (opt): Remove enable_extended_key_format.
* agent/gpg-agent.c (enum cmd_and_opt_values): Turn
oDisableExtendedKeyFormat and oEnableExtendedKeyFormat into dummy
options.

* agent/protect.c (do_encryption): Remove arg use_ocb and
corresponding code.
(agent_protect): Ditto.  Change all callers.

* agent/findkey.c (agent_write_private_key): Simplify due to the
removal of disable-extended-key-format.
(write_extended_private_key): Fold into agent_write_private_key.
--

This change is related to
GnuPG-bug-id: 6386
but should have no visible effect except for the removal of
option --disable-extended-key-format.
This commit is contained in:
Werner Koch 2023-03-13 08:49:49 +01:00
parent 56ca164684
commit 6d792ae2eb
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
11 changed files with 157 additions and 285 deletions

View File

@ -141,13 +141,6 @@ struct
passphrase change. */ passphrase change. */
int enable_passphrase_history; int enable_passphrase_history;
/* If set the extended key format is used for new keys. Note that
* this may have the value 2 in which case
* --disable-extended-key-format won't have any effect and thus
* effectivley locking it. This is required to support existing
* profiles which lock the use of --enable-extended-key-format. */
int enable_extended_key_format;
int running_detached; /* We are running detached from the tty. */ int running_detached; /* We are running detached from the tty. */
/* If this global option is true, the passphrase cache is ignored /* If this global option is true, the passphrase cache is ignored
@ -566,7 +559,7 @@ unsigned char get_standard_s2k_count_rfc4880 (void);
unsigned long get_standard_s2k_time (void); unsigned long get_standard_s2k_time (void);
int agent_protect (const unsigned char *plainkey, const char *passphrase, int agent_protect (const unsigned char *plainkey, const char *passphrase,
unsigned char **result, size_t *resultlen, unsigned char **result, size_t *resultlen,
unsigned long s2k_count, int use_ocb); unsigned long s2k_count);
gpg_error_t agent_unprotect (ctrl_t ctrl, gpg_error_t agent_unprotect (ctrl_t ctrl,
const unsigned char *protectedkey, const char *passphrase, const unsigned char *protectedkey, const char *passphrase,
gnupg_isotime_t protected_at, gnupg_isotime_t protected_at,

View File

@ -3142,7 +3142,7 @@ ssh_key_to_protected_buffer (gcry_sexp_t key, const char *passphrase,
buffer_new, buffer_new_n); buffer_new, buffer_new_n);
if (*passphrase) if (*passphrase)
err = agent_protect (buffer_new, passphrase, buffer, buffer_n, 0, -1); err = agent_protect (buffer_new, passphrase, buffer, buffer_n, 0);
else else
{ {
/* The key derivation function does not support zero length /* The key derivation function does not support zero length

View File

@ -1218,12 +1218,6 @@ cmd_keyattr (assuan_context_t ctx, char *line)
if (ctrl->restricted) if (ctrl->restricted)
return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN)); return leave_cmd (ctx, gpg_error (GPG_ERR_FORBIDDEN));
if (!opt.enable_extended_key_format)
{
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
goto leave;
}
opt_delete = has_option (line, "--delete"); opt_delete = has_option (line, "--delete");
line = skip_options (line); line = skip_options (line);
@ -2910,7 +2904,7 @@ cmd_import_key (assuan_context_t ctx, char *line)
if (passphrase) if (passphrase)
{ {
err = agent_protect (key, passphrase, &finalkey, &finalkeylen, err = agent_protect (key, passphrase, &finalkey, &finalkeylen,
ctrl->s2k_count, -1); ctrl->s2k_count);
if (!err) if (!err)
err = agent_write_private_key (grip, finalkey, finalkeylen, force, err = agent_write_private_key (grip, finalkey, finalkeylen, force,
NULL, NULL, opt_timestamp); NULL, NULL, opt_timestamp);

View File

@ -1146,7 +1146,7 @@ convert_from_openpgp_native (ctrl_t ctrl,
if (!agent_protect (*r_key, passphrase, if (!agent_protect (*r_key, passphrase,
&protectedkey, &protectedkeylen, &protectedkey, &protectedkeylen,
ctrl->s2k_count, -1)) ctrl->s2k_count))
agent_write_private_key (grip, protectedkey, protectedkeylen, 1, agent_write_private_key (grip, protectedkey, protectedkeylen, 1,
NULL, NULL, 0); NULL, NULL, 0);
xfree (protectedkey); xfree (protectedkey);

View File

@ -2,6 +2,7 @@
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
* 2010, 2011 Free Software Foundation, Inc. * 2010, 2011 Free Software Foundation, Inc.
* Copyright (C) 2014, 2019 Werner Koch * Copyright (C) 2014, 2019 Werner Koch
* Copyright (C) 2023 g10 Code GmbH
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -79,19 +80,114 @@ linefeed_to_percent0A (const char *string)
} }
/* Note: Ownership of FNAME and FP are moved to this function. */ /* Write the S-expression formatted key (BUFFER,LENGTH) to our key
static gpg_error_t * storage. With FORCE passed as true an existing key with the given
write_extended_private_key (char *fname, estream_t fp, int update, int newkey, * GRIP will get overwritten. If SERIALNO and KEYREF are given a
const void *buf, size_t len, * Token line is added to the key if the extended format is used. If
* TIMESTAMP is not zero and the key doies not yet exists it will be
* recorded as creation date. */
int
agent_write_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force,
const char *serialno, const char *keyref, const char *serialno, const char *keyref,
time_t timestamp) time_t timestamp)
{ {
gpg_error_t err; gpg_error_t err;
char *fname;
estream_t fp;
char hexgrip[40+4+1];
int update, newkey;
nvc_t pk = NULL; nvc_t pk = NULL;
gcry_sexp_t key = NULL; gcry_sexp_t key = NULL;
int remove = 0; int remove = 0;
char *token = NULL; char *token = NULL;
bin2hex (grip, 20, hexgrip);
strcpy (hexgrip+40, ".key");
fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
hexgrip, NULL);
/* FIXME: Write to a temp file first so that write failures during
key updates won't lead to a key loss. */
if (!force && !gnupg_access (fname, F_OK))
{
log_error ("secret key file '%s' already exists\n", fname);
xfree (fname);
return gpg_error (GPG_ERR_EEXIST);
}
fp = es_fopen (fname, force? "rb+,mode=-rw" : "wbx,mode=-rw");
if (!fp)
{
gpg_error_t tmperr = gpg_error_from_syserror ();
if (force && gpg_err_code (tmperr) == GPG_ERR_ENOENT)
{
fp = es_fopen (fname, "wbx,mode=-rw");
if (!fp)
tmperr = gpg_error_from_syserror ();
}
if (!fp)
{
log_error ("can't create '%s': %s\n", fname, gpg_strerror (tmperr));
xfree (fname);
return tmperr;
}
update = 0;
newkey = 1;
}
else if (force)
{
gpg_error_t rc;
char first;
/* See if an existing key is in extended format. */
if (es_fread (&first, 1, 1, fp) != 1)
{
rc = gpg_error_from_syserror ();
log_error ("error reading first byte from '%s': %s\n",
fname, strerror (errno));
xfree (fname);
es_fclose (fp);
return rc;
}
rc = es_fseek (fp, 0, SEEK_SET);
if (rc)
{
log_error ("error seeking in '%s': %s\n", fname, strerror (errno));
xfree (fname);
es_fclose (fp);
return rc;
}
if (first == '(')
{
/* Key is still in the old format - force it into extended
* format. We do not request an update here because an
* existing key is not yet in extended key format and no
* extended infos are yet available. */
update = 0;
newkey = 0;
}
else
{
/* Key is already in the extended format. */
update = 1;
newkey = 0;
}
}
else
{
/* The key file did not exist: we assume this is a new key and
* write the Created: entry. */
update = 0;
newkey = 1;
}
if (update) if (update)
{ {
int line; int line;
@ -115,10 +211,11 @@ write_extended_private_key (char *fname, estream_t fp, int update, int newkey,
} }
es_clearerr (fp); es_clearerr (fp);
err = gcry_sexp_sscan (&key, NULL, buf, len); /* Turn (BUFFER,LENGTH) into a gcrypt s-expression and set it into
* our name value container. */
err = gcry_sexp_sscan (&key, NULL, buffer, length);
if (err) if (err)
goto leave; goto leave;
err = nvc_set_private_key (pk, key); err = nvc_set_private_key (pk, key);
if (err) if (err)
goto leave; goto leave;
@ -153,7 +250,7 @@ write_extended_private_key (char *fname, estream_t fp, int update, int newkey,
} }
} }
/* If a timestamp has been supplied and the key is new write a /* If a timestamp has been supplied and the key is new, write a
* creation timestamp. (We douple check that there is no Created * creation timestamp. (We douple check that there is no Created
* item yet.)*/ * item yet.)*/
if (timestamp && newkey && !nvc_lookup (pk, "Created:")) if (timestamp && newkey && !nvc_lookup (pk, "Created:"))
@ -166,7 +263,7 @@ write_extended_private_key (char *fname, estream_t fp, int update, int newkey,
goto leave; goto leave;
} }
/* Back to start and write. */
err = es_fseek (fp, 0, SEEK_SET); err = es_fseek (fp, 0, SEEK_SET);
if (err) if (err)
goto leave; goto leave;
@ -212,133 +309,6 @@ write_extended_private_key (char *fname, estream_t fp, int update, int newkey,
return err; return err;
} }
/* Write an S-expression formatted key to our key storage. With FORCE
* passed as true an existing key with the given GRIP will get
* overwritten. If SERIALNO and KEYREF are given a Token line is
* added to the key if the extended format is used. If TIMESTAMP is
* not zero and the key doies not yet exists it will be recorded as
* creation date. */
int
agent_write_private_key (const unsigned char *grip,
const void *buffer, size_t length, int force,
const char *serialno, const char *keyref,
time_t timestamp)
{
char *fname;
estream_t fp;
char hexgrip[40+4+1];
bin2hex (grip, 20, hexgrip);
strcpy (hexgrip+40, ".key");
fname = make_filename (gnupg_homedir (), GNUPG_PRIVATE_KEYS_DIR,
hexgrip, NULL);
/* FIXME: Write to a temp file first so that write failures during
key updates won't lead to a key loss. */
if (!force && !gnupg_access (fname, F_OK))
{
log_error ("secret key file '%s' already exists\n", fname);
xfree (fname);
return gpg_error (GPG_ERR_EEXIST);
}
fp = es_fopen (fname, force? "rb+,mode=-rw" : "wbx,mode=-rw");
if (!fp)
{
gpg_error_t tmperr = gpg_error_from_syserror ();
if (force && gpg_err_code (tmperr) == GPG_ERR_ENOENT)
{
fp = es_fopen (fname, "wbx,mode=-rw");
if (!fp)
tmperr = gpg_error_from_syserror ();
}
if (!fp)
{
log_error ("can't create '%s': %s\n", fname, gpg_strerror (tmperr));
xfree (fname);
return tmperr;
}
}
else if (force)
{
gpg_error_t rc;
char first;
/* See if an existing key is in extended format. */
if (es_fread (&first, 1, 1, fp) != 1)
{
rc = gpg_error_from_syserror ();
log_error ("error reading first byte from '%s': %s\n",
fname, strerror (errno));
xfree (fname);
es_fclose (fp);
return rc;
}
rc = es_fseek (fp, 0, SEEK_SET);
if (rc)
{
log_error ("error seeking in '%s': %s\n", fname, strerror (errno));
xfree (fname);
es_fclose (fp);
return rc;
}
if (first != '(')
{
/* Key is already in the extended format. */
return write_extended_private_key (fname, fp, 1, 0, buffer, length,
serialno, keyref, timestamp);
}
if (first == '(' && opt.enable_extended_key_format)
{
/* Key is in the old format - but we want the extended format. */
return write_extended_private_key (fname, fp, 0, 0, buffer, length,
serialno, keyref, timestamp);
}
}
if (opt.enable_extended_key_format)
return write_extended_private_key (fname, fp, 0, 1, buffer, length,
serialno, keyref, timestamp);
if (es_fwrite (buffer, length, 1, fp) != 1)
{
gpg_error_t tmperr = gpg_error_from_syserror ();
log_error ("error writing '%s': %s\n", fname, gpg_strerror (tmperr));
es_fclose (fp);
gnupg_remove (fname);
xfree (fname);
return tmperr;
}
/* When force is given, the file might have to be truncated. */
if (force && ftruncate (es_fileno (fp), es_ftello (fp)))
{
gpg_error_t tmperr = gpg_error_from_syserror ();
log_error ("error truncating '%s': %s\n", fname, gpg_strerror (tmperr));
es_fclose (fp);
gnupg_remove (fname);
xfree (fname);
return tmperr;
}
if (es_fclose (fp))
{
gpg_error_t tmperr = gpg_error_from_syserror ();
log_error ("error closing '%s': %s\n", fname, gpg_strerror (tmperr));
gnupg_remove (fname);
xfree (fname);
return tmperr;
}
bump_key_eventcounter ();
xfree (fname);
return 0;
}
gpg_error_t gpg_error_t
agent_update_private_key (const unsigned char *grip, nvc_t pk) agent_update_private_key (const unsigned char *grip, nvc_t pk)
@ -393,6 +363,7 @@ agent_update_private_key (const unsigned char *grip, nvc_t pk)
return err; return err;
} }
/* Callback function to try the unprotection from the passphrase query /* Callback function to try the unprotection from the passphrase query
code. */ code. */
static gpg_error_t static gpg_error_t

View File

@ -57,7 +57,7 @@ store_key (gcry_sexp_t private, const char *passphrase, int force,
{ {
unsigned char *p; unsigned char *p;
rc = agent_protect (buf, passphrase, &p, &len, s2k_count, -1); rc = agent_protect (buf, passphrase, &p, &len, s2k_count);
if (rc) if (rc)
{ {
xfree (buf); xfree (buf);

View File

@ -116,8 +116,6 @@ enum cmd_and_opt_values
oCheckSymPassphrasePattern, oCheckSymPassphrasePattern,
oMaxPassphraseDays, oMaxPassphraseDays,
oEnablePassphraseHistory, oEnablePassphraseHistory,
oDisableExtendedKeyFormat,
oEnableExtendedKeyFormat,
oStealSocket, oStealSocket,
oUseStandardSocket, oUseStandardSocket,
oNoUseStandardSocket, oNoUseStandardSocket,
@ -238,8 +236,6 @@ static gpgrt_opt_t opts[] = {
/* */ "@" /* */ "@"
#endif #endif
), ),
ARGPARSE_s_n (oDisableExtendedKeyFormat, "disable-extended-key-format", "@"),
ARGPARSE_s_n (oEnableExtendedKeyFormat, "enable-extended-key-format", "@"),
ARGPARSE_s_i (oListenBacklog, "listen-backlog", "@"), ARGPARSE_s_i (oListenBacklog, "listen-backlog", "@"),
ARGPARSE_op_u (oAutoExpandSecmem, "auto-expand-secmem", "@"), ARGPARSE_op_u (oAutoExpandSecmem, "auto-expand-secmem", "@"),
ARGPARSE_s_s (oFakedSystemTime, "faked-system-time", "@"), ARGPARSE_s_s (oFakedSystemTime, "faked-system-time", "@"),
@ -315,7 +311,8 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_n (oNoUseStandardSocket, "no-use-standard-socket", "@"), ARGPARSE_s_n (oNoUseStandardSocket, "no-use-standard-socket", "@"),
/* Dummy options. */ /* Dummy options. */
ARGPARSE_s_n (oNoop, "disable-extended-key-format", "@"),
ARGPARSE_s_n (oNoop, "enable-extended-key-format", "@"),
ARGPARSE_end () /* End of list */ ARGPARSE_end () /* End of list */
}; };
@ -885,7 +882,6 @@ parse_rereadable_options (gpgrt_argparse_t *pargs, int reread)
opt.check_sym_passphrase_pattern = NULL; opt.check_sym_passphrase_pattern = NULL;
opt.max_passphrase_days = MAX_PASSPHRASE_DAYS; opt.max_passphrase_days = MAX_PASSPHRASE_DAYS;
opt.enable_passphrase_history = 0; opt.enable_passphrase_history = 0;
opt.enable_extended_key_format = 1;
opt.ignore_cache_for_signing = 0; opt.ignore_cache_for_signing = 0;
opt.allow_mark_trusted = 1; opt.allow_mark_trusted = 1;
opt.sys_trustlist_name = NULL; opt.sys_trustlist_name = NULL;
@ -974,14 +970,6 @@ parse_rereadable_options (gpgrt_argparse_t *pargs, int reread)
opt.enable_passphrase_history = 1; opt.enable_passphrase_history = 1;
break; break;
case oEnableExtendedKeyFormat:
opt.enable_extended_key_format = 2;
break;
case oDisableExtendedKeyFormat:
if (opt.enable_extended_key_format != 2)
opt.enable_extended_key_format = 0;
break;
case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break; case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
case oAllowMarkTrusted: opt.allow_mark_trusted = 1; break; case oAllowMarkTrusted: opt.allow_mark_trusted = 1; break;

View File

@ -97,7 +97,6 @@ static const char *opt_passphrase;
static char *opt_prompt; static char *opt_prompt;
static int opt_status_msg; static int opt_status_msg;
static const char *opt_agent_program; static const char *opt_agent_program;
static int opt_debug_use_ocb;
static char *get_passphrase (int promptno); static char *get_passphrase (int promptno);
static void release_passphrase (char *pw); static void release_passphrase (char *pw);
@ -343,8 +342,7 @@ read_and_protect (const char *fname)
return; return;
pw = get_passphrase (1); pw = get_passphrase (1);
rc = agent_protect (key, pw, &result, &resultlen, 0, rc = agent_protect (key, pw, &result, &resultlen, 0);
opt_debug_use_ocb? 1 : -1);
release_passphrase (pw); release_passphrase (pw);
xfree (key); xfree (key);
if (rc) if (rc)
@ -610,7 +608,7 @@ main (int argc, char **argv )
case oHaveCert: opt_have_cert = 1; break; case oHaveCert: opt_have_cert = 1; break;
case oPrompt: opt_prompt = pargs.r.ret_str; break; case oPrompt: opt_prompt = pargs.r.ret_str; break;
case oStatusMsg: opt_status_msg = 1; break; case oStatusMsg: opt_status_msg = 1; break;
case oDebugUseOCB: opt_debug_use_ocb = 1; break; case oDebugUseOCB: /* dummy */; break;
default: pargs.err = ARGPARSE_PRINT_ERROR; break; default: pargs.err = ARGPARSE_PRINT_ERROR; break;
} }

View File

@ -379,12 +379,11 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
const char *passphrase, const char *passphrase,
const char *timestamp_exp, size_t timestamp_exp_len, const char *timestamp_exp, size_t timestamp_exp_len,
unsigned char **result, size_t *resultlen, unsigned char **result, size_t *resultlen,
unsigned long s2k_count, int use_ocb) unsigned long s2k_count)
{ {
gcry_cipher_hd_t hd; gcry_cipher_hd_t hd;
const char *modestr; const char *modestr;
unsigned char hashvalue[20]; int enclen, outlen;
int blklen, enclen, outlen;
unsigned char *iv = NULL; unsigned char *iv = NULL;
unsigned int ivsize; /* Size of the buffer allocated for IV. */ unsigned int ivsize; /* Size of the buffer allocated for IV. */
const unsigned char *s2ksalt; /* Points into IV. */ const unsigned char *s2ksalt; /* Points into IV. */
@ -398,44 +397,26 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
*resultlen = 0; *resultlen = 0;
*result = NULL; *result = NULL;
modestr = (use_ocb? "openpgp-s2k3-ocb-aes" modestr = "openpgp-s2k3-ocb-aes";
/* */: "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc");
rc = gcry_cipher_open (&hd, PROT_CIPHER, rc = gcry_cipher_open (&hd, PROT_CIPHER,
use_ocb? GCRY_CIPHER_MODE_OCB : GCRY_CIPHER_MODE_OCB,
GCRY_CIPHER_MODE_CBC,
GCRY_CIPHER_SECURE); GCRY_CIPHER_SECURE);
if (rc) if (rc)
return rc; return rc;
/* We need to work on a copy of the data because this makes it /* We need to work on a copy of the data because this makes it
* easier to add the trailer and the padding and more important we * easier to add the trailer and the padding and more important we
* have to prefix the text with 2 parenthesis. In CBC mode we * have to prefix the text with 2 parenthesis. Due to OCB mode we
* have to allocate enough space for:
*
* ((<parameter_list>)(4:hash4:sha120:<hashvalue>)) + padding
*
* we always append a full block of random bytes as padding but
* encrypt only what is needed for a full blocksize. In OCB mode we
* have to allocate enough space for just: * have to allocate enough space for just:
* *
* ((<parameter_list>)) * ((<parameter_list>))
*/ */
blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
if (use_ocb)
{
/* (( )) */ /* (( )) */
outlen = 2 + protlen + 2 ; outlen = 2 + protlen + 2 ;
enclen = outlen + 16 /* taglen */; enclen = outlen + 16 /* taglen */;
outbuf = gcry_malloc_secure (enclen); outbuf = gcry_malloc_secure (enclen);
}
else
{
/* (( )( 4:hash 4:sha1 20:<hash> )) <padding> */
outlen = 2 + protlen + 2 + 6 + 6 + 23 + 2 + blklen;
enclen = outlen/blklen * blklen;
outbuf = gcry_malloc_secure (outlen);
}
if (!outbuf) if (!outbuf)
{ {
rc = out_of_core (); rc = out_of_core ();
@ -445,10 +426,10 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
/* Allocate a buffer for the nonce and the salt. */ /* Allocate a buffer for the nonce and the salt. */
if (!rc) if (!rc)
{ {
/* Allocate random bytes to be used as IV, padding and s2k salt /* Allocate random bytes to be used as nonce and s2k salt. The
* or in OCB mode for a nonce and the s2k salt. The IV/nonce is * nonce is set later because for OCB we need to set the key
* set later because for OCB we need to set the key first. */ * first. */
ivsize = (use_ocb? 12 : (blklen*2)) + 8; ivsize = 12 + 8;
iv = xtrymalloc (ivsize); iv = xtrymalloc (ivsize);
if (!iv) if (!iv)
rc = gpg_error_from_syserror (); rc = gpg_error_from_syserror ();
@ -484,12 +465,10 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
goto leave; goto leave;
/* Set the IV/nonce. */ /* Set the IV/nonce. */
rc = gcry_cipher_setiv (hd, iv, use_ocb? 12 : blklen); rc = gcry_cipher_setiv (hd, iv, 12);
if (rc) if (rc)
goto leave; goto leave;
if (use_ocb)
{
/* In OCB Mode we use only the public key parameters as AAD. */ /* In OCB Mode we use only the public key parameters as AAD. */
rc = gcry_cipher_authenticate (hd, hashbegin, protbegin - hashbegin); rc = gcry_cipher_authenticate (hd, hashbegin, protbegin - hashbegin);
if (!rc) if (!rc)
@ -497,27 +476,6 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
if (!rc) if (!rc)
rc = gcry_cipher_authenticate rc = gcry_cipher_authenticate
(hd, protbegin+protlen, hashlen - (protbegin+protlen - hashbegin)); (hd, protbegin+protlen, hashlen - (protbegin+protlen - hashbegin));
}
else
{
/* Hash the entire expression for CBC mode. Because
* TIMESTAMP_EXP won't get protected, we can't simply hash a
* continuous buffer but need to call md_write several times. */
gcry_md_hd_t md;
rc = gcry_md_open (&md, GCRY_MD_SHA1, 0 );
if (!rc)
{
gcry_md_write (md, hashbegin, protbegin - hashbegin);
gcry_md_write (md, protbegin, protlen);
gcry_md_write (md, timestamp_exp, timestamp_exp_len);
gcry_md_write (md, protbegin+protlen,
hashlen - (protbegin+protlen - hashbegin));
memcpy (hashvalue, gcry_md_read (md, GCRY_MD_SHA1), 20);
gcry_md_close (md);
}
}
/* Encrypt. */ /* Encrypt. */
if (!rc) if (!rc)
@ -527,25 +485,9 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
*p++ = '('; *p++ = '(';
memcpy (p, protbegin, protlen); memcpy (p, protbegin, protlen);
p += protlen; p += protlen;
if (use_ocb)
{
*p++ = ')'; *p++ = ')';
*p++ = ')'; *p++ = ')';
}
else
{
memcpy (p, ")(4:hash4:sha120:", 17);
p += 17;
memcpy (p, hashvalue, 20);
p += 20;
*p++ = ')';
*p++ = ')';
memcpy (p, iv+blklen, blklen); /* Add padding. */
p += blklen;
}
log_assert ( p - outbuf == outlen); log_assert ( p - outbuf == outlen);
if (use_ocb)
{
gcry_cipher_final (hd); gcry_cipher_final (hd);
rc = gcry_cipher_encrypt (hd, outbuf, outlen, NULL, 0); rc = gcry_cipher_encrypt (hd, outbuf, outlen, NULL, 0);
if (!rc) if (!rc)
@ -554,11 +496,6 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
rc = gcry_cipher_gettag (hd, outbuf + outlen, 16); rc = gcry_cipher_gettag (hd, outbuf + outlen, 16);
} }
} }
else
{
rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0);
}
}
if (rc) if (rc)
goto leave; goto leave;
@ -584,7 +521,7 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
(int)strlen (modestr), modestr, (int)strlen (modestr), modestr,
&saltpos, &saltpos,
(unsigned int)strlen (countbuf), countbuf, (unsigned int)strlen (countbuf), countbuf,
use_ocb? 12 : blklen, &ivpos, use_ocb? 12 : blklen, "", 12, &ivpos, 12, "",
enclen, &encpos, enclen, ""); enclen, &encpos, enclen, "");
if (!p) if (!p)
{ {
@ -598,7 +535,7 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
*resultlen = strlen (p); *resultlen = strlen (p);
*result = (unsigned char*)p; *result = (unsigned char*)p;
memcpy (p+saltpos, s2ksalt, 8); memcpy (p+saltpos, s2ksalt, 8);
memcpy (p+ivpos, iv, use_ocb? 12 : blklen); memcpy (p+ivpos, iv, 12);
memcpy (p+encpos, outbuf, enclen); memcpy (p+encpos, outbuf, enclen);
xfree (iv); xfree (iv);
xfree (outbuf); xfree (outbuf);
@ -614,13 +551,11 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
/* Protect the key encoded in canonical format in PLAINKEY. We assume /* Protect the key encoded in canonical format in PLAINKEY. We assume
a valid S-Exp here. With USE_UCB set to -1 the default scheme is * a valid S-Exp here. */
used (ie. either CBC or OCB), set to 0 the old CBC mode is used,
and set to 1 OCB is used. */
int int
agent_protect (const unsigned char *plainkey, const char *passphrase, agent_protect (const unsigned char *plainkey, const char *passphrase,
unsigned char **result, size_t *resultlen, unsigned char **result, size_t *resultlen,
unsigned long s2k_count, int use_ocb) unsigned long s2k_count)
{ {
int rc; int rc;
const char *parmlist; const char *parmlist;
@ -637,9 +572,6 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
unsigned char *p; unsigned char *p;
int have_curve = 0; int have_curve = 0;
if (use_ocb == -1)
use_ocb = !!opt.enable_extended_key_format;
/* Create an S-expression with the protected-at timestamp. */ /* Create an S-expression with the protected-at timestamp. */
memcpy (timestamp_exp, "(12:protected-at15:", 19); memcpy (timestamp_exp, "(12:protected-at15:", 19);
gnupg_get_isotime (timestamp_exp+19); gnupg_get_isotime (timestamp_exp+19);
@ -743,7 +675,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
rc = do_encryption (hash_begin, hash_end - hash_begin + 1, rc = do_encryption (hash_begin, hash_end - hash_begin + 1,
prot_begin, prot_end - prot_begin + 1, prot_begin, prot_end - prot_begin + 1,
passphrase, timestamp_exp, sizeof (timestamp_exp), passphrase, timestamp_exp, sizeof (timestamp_exp),
&protected, &protectedlen, s2k_count, use_ocb); &protected, &protectedlen, s2k_count);
if (rc) if (rc)
return rc; return rc;

View File

@ -196,7 +196,7 @@ test_agent_protect (void)
{ {
ret = agent_protect ((const unsigned char*)specs[i].key, ret = agent_protect ((const unsigned char*)specs[i].key,
specs[i].passphrase, specs[i].passphrase,
&specs[i].result, &specs[i].resultlen, 0, -1); &specs[i].result, &specs[i].resultlen, 0);
if (gpg_err_code (ret) != specs[i].ret_expected) if (gpg_err_code (ret) != specs[i].ret_expected)
{ {
printf ("agent_protect(%d) returned '%i/%s'; expected '%i/%s'\n", printf ("agent_protect(%d) returned '%i/%s'; expected '%i/%s'\n",

View File

@ -615,15 +615,11 @@ remote machine.
@itemx --disable-extended-key-format @itemx --disable-extended-key-format
@opindex enable-extended-key-format @opindex enable-extended-key-format
@opindex disable-extended-key-format @opindex disable-extended-key-format
Since version 2.3 keys are created in the extended private key format. These options are obsolete and have no effect. The extended key format
Changing the passphrase of a key will also convert the key to that new is used for years now and has been supported since 2.1.12. Existing
format. This new key format is supported since GnuPG version 2.1.12 keys in the old format are migrated to the new format as soon as they
and thus there should be no need to disable it. The disable option are touched.
allows to revert to the old behavior for new keys; be aware that keys
are never migrated back to the old format. However if the enable
option has been used the disable option won't have an effect. The
advantage of the extended private key format is that it is text based
and can carry additional meta data.
@anchor{option --enable-ssh-support} @anchor{option --enable-ssh-support}
@item --enable-ssh-support @item --enable-ssh-support