mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-02 22:46:30 +02:00
Merge branch 'master' into key-storage-work
This commit is contained in:
commit
caddeef4a7
43 changed files with 6301 additions and 5133 deletions
294
g10/call-agent.c
294
g10/call-agent.c
|
@ -1,6 +1,6 @@
|
|||
/* call-agent.c - Divert GPG operations to the agent.
|
||||
* Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009,
|
||||
* 2010, 2011 Free Software Foundation, Inc.
|
||||
* 2010, 2011, 2013 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
|
@ -40,47 +40,60 @@
|
|||
#include "sysutils.h"
|
||||
#include "call-agent.h"
|
||||
#include "status.h"
|
||||
#include "../common/shareddefs.h"
|
||||
|
||||
#ifndef DBG_ASSUAN
|
||||
# define DBG_ASSUAN 1
|
||||
#endif
|
||||
|
||||
#define CONTROL_D ('D' - 'A' + 1)
|
||||
|
||||
|
||||
static assuan_context_t agent_ctx = NULL;
|
||||
static int did_early_card_test;
|
||||
|
||||
struct cipher_parm_s
|
||||
struct default_inq_parm_s
|
||||
{
|
||||
ctrl_t ctrl;
|
||||
assuan_context_t ctx;
|
||||
struct {
|
||||
u32 *keyid;
|
||||
u32 *mainkeyid;
|
||||
int pubkey_algo;
|
||||
} keyinfo;
|
||||
};
|
||||
|
||||
struct cipher_parm_s
|
||||
{
|
||||
struct default_inq_parm_s *dflt;
|
||||
assuan_context_t ctx;
|
||||
unsigned char *ciphertext;
|
||||
size_t ciphertextlen;
|
||||
};
|
||||
|
||||
struct writecert_parm_s
|
||||
{
|
||||
assuan_context_t ctx;
|
||||
struct default_inq_parm_s *dflt;
|
||||
const unsigned char *certdata;
|
||||
size_t certdatalen;
|
||||
};
|
||||
|
||||
struct writekey_parm_s
|
||||
{
|
||||
assuan_context_t ctx;
|
||||
struct default_inq_parm_s *dflt;
|
||||
const unsigned char *keydata;
|
||||
size_t keydatalen;
|
||||
};
|
||||
|
||||
struct genkey_parm_s
|
||||
{
|
||||
ctrl_t ctrl;
|
||||
assuan_context_t ctx;
|
||||
struct default_inq_parm_s *dflt;
|
||||
const char *keyparms;
|
||||
};
|
||||
|
||||
struct import_key_parm_s
|
||||
{
|
||||
ctrl_t ctrl;
|
||||
assuan_context_t ctx;
|
||||
struct default_inq_parm_s *dflt;
|
||||
const void *key;
|
||||
size_t keylen;
|
||||
};
|
||||
|
@ -161,6 +174,19 @@ start_agent (ctrl_t ctrl, int for_card)
|
|||
here used to indirectly enable GPG_ERR_FULLY_CANCELED. */
|
||||
assuan_transact (agent_ctx, "OPTION agent-awareness=2.1.0",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
/* Pass on the pinentry mode. */
|
||||
if (opt.pinentry_mode)
|
||||
{
|
||||
char *tmp = xasprintf ("OPTION pinentry-mode=%s",
|
||||
str_pinentry_mode (opt.pinentry_mode));
|
||||
rc = assuan_transact (agent_ctx, tmp,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
xfree (tmp);
|
||||
if (rc)
|
||||
log_error ("setting pinentry mode '%s' failed: %s\n",
|
||||
str_pinentry_mode (opt.pinentry_mode),
|
||||
gpg_strerror (rc));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -307,20 +333,46 @@ get_serialno_cb (void *opaque, const char *line)
|
|||
static gpg_error_t
|
||||
default_inq_cb (void *opaque, const char *line)
|
||||
{
|
||||
(void)opaque;
|
||||
gpg_error_t err = 0;
|
||||
struct default_inq_parm_s *parm = opaque;
|
||||
|
||||
if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
|
||||
{
|
||||
/* There is no working server mode yet thus we use
|
||||
AllowSetForegroundWindow window right here. We might want to
|
||||
do this anyway in case gpg is called on the console. */
|
||||
gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
|
||||
err = gpg_proxy_pinentry_notify (parm->ctrl, line);
|
||||
if (err)
|
||||
log_error (_("failed to proxy %s inquiry to client\n"),
|
||||
"PINENTRY_LAUNCHED");
|
||||
/* We do not pass errors to avoid breaking other code. */
|
||||
}
|
||||
else if (!strncmp (line, "PASSPHRASE", 10) && (line[10]==' '||!line[10])
|
||||
&& opt.pinentry_mode == PINENTRY_MODE_LOOPBACK)
|
||||
{
|
||||
if (have_static_passphrase ())
|
||||
{
|
||||
const char *s = get_static_passphrase ();
|
||||
err = assuan_send_data (parm->ctx, s, strlen (s));
|
||||
}
|
||||
else
|
||||
{
|
||||
char *pw;
|
||||
|
||||
if (parm->keyinfo.keyid)
|
||||
emit_status_need_passphrase (parm->keyinfo.keyid,
|
||||
parm->keyinfo.mainkeyid,
|
||||
parm->keyinfo.pubkey_algo);
|
||||
pw = cpr_get_hidden ("passphrase.enter", _("Enter passphrase: "));
|
||||
cpr_kill_prompt ();
|
||||
if (*pw == CONTROL_D && !pw[1])
|
||||
err = gpg_error (GPG_ERR_CANCELED);
|
||||
else
|
||||
err = assuan_send_data (parm->ctx, pw, strlen (pw));
|
||||
xfree (pw);
|
||||
}
|
||||
}
|
||||
else
|
||||
log_debug ("ignoring gpg-agent inquiry '%s'\n", line);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
@ -515,6 +567,9 @@ int
|
|||
agent_learn (struct agent_card_info_s *info)
|
||||
{
|
||||
int rc;
|
||||
struct default_inq_parm_s parm;
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
|
@ -532,10 +587,10 @@ agent_learn (struct agent_card_info_s *info)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
||||
parm.ctx = agent_ctx;
|
||||
memset (info, 0, sizeof *info);
|
||||
rc = assuan_transact (agent_ctx, "SCD LEARN --force",
|
||||
dummy_data_cb, NULL, default_inq_cb, NULL,
|
||||
dummy_data_cb, NULL, default_inq_cb, &parm,
|
||||
learn_status_cb, info);
|
||||
/* Also try to get the key attributes. */
|
||||
if (!rc)
|
||||
|
@ -544,6 +599,30 @@ agent_learn (struct agent_card_info_s *info)
|
|||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
agent_keytocard (const char *hexgrip, int keyno, int force,
|
||||
const char *serialno, const char *timestamp)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
|
||||
snprintf (line, DIM(line)-1, "KEYTOCARD %s%s %s OPENPGP.%d %s",
|
||||
force?"--force ": "", hexgrip, serialno, keyno, timestamp);
|
||||
line[DIM(line)-1] = 0;
|
||||
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb,
|
||||
NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Call the agent to retrieve a data object. This function returns
|
||||
the data in the same structure as used by the learn command. It is
|
||||
allowed to update such a structure using this commmand. */
|
||||
|
@ -552,6 +631,9 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
|
|||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s parm;
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
|
||||
if (!*name)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
@ -565,7 +647,8 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
|
||||
parm.ctx = agent_ctx;
|
||||
rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, &parm,
|
||||
learn_status_cb, info);
|
||||
|
||||
return rc;
|
||||
|
@ -583,6 +666,9 @@ agent_scd_setattr (const char *name,
|
|||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
char *p;
|
||||
struct default_inq_parm_s parm;
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
|
||||
(void)serialno;
|
||||
|
||||
|
@ -614,8 +700,9 @@ agent_scd_setattr (const char *name,
|
|||
rc = start_agent (NULL, 1);
|
||||
if (!rc)
|
||||
{
|
||||
parm.ctx = agent_ctx;
|
||||
rc = assuan_transact (agent_ctx, line, NULL, NULL,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
default_inq_cb, &parm, NULL, NULL);
|
||||
}
|
||||
|
||||
status_sc_op_failure (rc);
|
||||
|
@ -635,10 +722,11 @@ inq_writecert_parms (void *opaque, const char *line)
|
|||
|
||||
if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
|
||||
{
|
||||
rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
|
||||
rc = assuan_send_data (parm->dflt->ctx,
|
||||
parm->certdata, parm->certdatalen);
|
||||
}
|
||||
else
|
||||
rc = default_inq_cb (opaque, line);
|
||||
rc = default_inq_cb (parm->dflt, line);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -652,6 +740,9 @@ agent_scd_writecert (const char *certidstr,
|
|||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct writecert_parm_s parms;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
|
@ -661,7 +752,8 @@ agent_scd_writecert (const char *certidstr,
|
|||
|
||||
snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
|
||||
line[DIM(line)-1] = 0;
|
||||
parms.ctx = agent_ctx;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
parms.dflt = &dfltparm;
|
||||
parms.certdata = certdata;
|
||||
parms.certdatalen = certdatalen;
|
||||
|
||||
|
@ -683,10 +775,10 @@ inq_writekey_parms (void *opaque, const char *line)
|
|||
|
||||
if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
|
||||
{
|
||||
rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
|
||||
rc = assuan_send_data (parm->dflt->ctx, parm->keydata, parm->keydatalen);
|
||||
}
|
||||
else
|
||||
rc = default_inq_cb (opaque, line);
|
||||
rc = default_inq_cb (parm->dflt, line);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -700,6 +792,9 @@ agent_scd_writekey (int keyno, const char *serialno,
|
|||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct writekey_parm_s parms;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
(void)serialno;
|
||||
|
||||
|
@ -711,7 +806,8 @@ agent_scd_writekey (int keyno, const char *serialno,
|
|||
|
||||
snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
|
||||
line[DIM(line)-1] = 0;
|
||||
parms.ctx = agent_ctx;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
parms.dflt = &dfltparm;
|
||||
parms.keydata = keydata;
|
||||
parms.keydatalen = keydatalen;
|
||||
|
||||
|
@ -836,6 +932,9 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
|
|||
char line[ASSUAN_LINELENGTH];
|
||||
gnupg_isotime_t tbuf;
|
||||
struct scd_genkey_parm_s parms;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
(void)serialno;
|
||||
|
||||
|
@ -857,9 +956,10 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
|
|||
keyno);
|
||||
line[DIM(line)-1] = 0;
|
||||
|
||||
dfltparm.ctx = agent_ctx;
|
||||
memset (info, 0, sizeof *info);
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL, default_inq_cb, NULL,
|
||||
NULL, NULL, default_inq_cb, &dfltparm,
|
||||
scd_genkey_cb, &parms);
|
||||
|
||||
xfree (parms.savedbytes);
|
||||
|
@ -985,19 +1085,25 @@ agent_scd_readcert (const char *certidstr,
|
|||
char line[ASSUAN_LINELENGTH];
|
||||
membuf_t data;
|
||||
size_t len;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
*r_buf = NULL;
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
init_membuf (&data, 2048);
|
||||
|
||||
snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
if (rc)
|
||||
{
|
||||
xfree (get_membuf (&data, &len));
|
||||
|
@ -1028,6 +1134,9 @@ agent_scd_change_pin (int chvno, const char *serialno)
|
|||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
const char *reset = "";
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
(void)serialno;
|
||||
|
||||
|
@ -1038,11 +1147,14 @@ agent_scd_change_pin (int chvno, const char *serialno)
|
|||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (agent_ctx, line, NULL, NULL,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL,
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
status_sc_op_failure (rc);
|
||||
return rc;
|
||||
}
|
||||
|
@ -1056,16 +1168,21 @@ agent_scd_checkpin (const char *serialno)
|
|||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
status_sc_op_failure (rc);
|
||||
return rc;
|
||||
}
|
||||
|
@ -1101,12 +1218,16 @@ agent_get_passphrase (const char *cache_id,
|
|||
char *arg3 = NULL;
|
||||
char *arg4 = NULL;
|
||||
membuf_t data;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
*r_passphrase = NULL;
|
||||
|
||||
rc = start_agent (NULL, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
/* Check that the gpg-agent understands the repeat option. */
|
||||
if (assuan_transact (agent_ctx,
|
||||
|
@ -1144,7 +1265,8 @@ agent_get_passphrase (const char *cache_id,
|
|||
init_membuf_secure (&data, 64);
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
|
||||
if (rc)
|
||||
xfree (get_membuf (&data, NULL));
|
||||
|
@ -1171,6 +1293,9 @@ agent_clear_passphrase (const char *cache_id)
|
|||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
if (!cache_id || !*cache_id)
|
||||
return 0;
|
||||
|
@ -1178,11 +1303,14 @@ agent_clear_passphrase (const char *cache_id)
|
|||
rc = start_agent (NULL, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
|
||||
line[DIM(line)-1] = 0;
|
||||
return assuan_transact (agent_ctx, line, NULL, NULL,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
return assuan_transact (agent_ctx, line,
|
||||
NULL, NULL,
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1194,10 +1322,14 @@ gpg_agent_get_confirmation (const char *desc)
|
|||
int rc;
|
||||
char *tmp;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
rc = start_agent (NULL, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
tmp = percent_plus_escape (desc);
|
||||
if (!tmp)
|
||||
|
@ -1206,8 +1338,10 @@ gpg_agent_get_confirmation (const char *desc)
|
|||
line[DIM(line)-1] = 0;
|
||||
xfree (tmp);
|
||||
|
||||
rc = assuan_transact (agent_ctx, line, NULL, NULL,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL,
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1438,11 +1572,11 @@ inq_genkey_parms (void *opaque, const char *line)
|
|||
|
||||
if (!strncmp (line, "KEYPARAM", 8) && (line[8]==' '||!line[8]))
|
||||
{
|
||||
err = assuan_send_data (parm->ctx,
|
||||
err = assuan_send_data (parm->dflt->ctx,
|
||||
parm->keyparms, strlen (parm->keyparms));
|
||||
}
|
||||
else
|
||||
err = default_inq_cb (parm->ctrl, line);
|
||||
err = default_inq_cb (parm->dflt, line);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -1459,15 +1593,20 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
|
|||
gpg_error_t err;
|
||||
struct genkey_parm_s gk_parm;
|
||||
struct cache_nonce_parm_s cn_parm;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
membuf_t data;
|
||||
size_t len;
|
||||
unsigned char *buf;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
*r_pubkey = NULL;
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
err = assuan_transact (agent_ctx, "RESET",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
@ -1475,8 +1614,7 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
|
|||
return err;
|
||||
|
||||
init_membuf (&data, 1024);
|
||||
gk_parm.ctrl = ctrl;
|
||||
gk_parm.ctx = agent_ctx;
|
||||
gk_parm.dflt = &dfltparm;
|
||||
gk_parm.keyparms = keyparms;
|
||||
snprintf (line, sizeof line, "GENKEY%s%s%s",
|
||||
no_protection? " --no-protection":"",
|
||||
|
@ -1520,11 +1658,16 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
|||
size_t len;
|
||||
unsigned char *buf;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
*r_pubkey = NULL;
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
err = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (err)
|
||||
|
@ -1535,7 +1678,8 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
|||
init_membuf (&data, 1024);
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
xfree (get_membuf (&data, &len));
|
||||
|
@ -1564,17 +1708,26 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
|||
gpg_error_t
|
||||
agent_pksign (ctrl_t ctrl, const char *cache_nonce,
|
||||
const char *keygrip, const char *desc,
|
||||
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
|
||||
unsigned char *digest, size_t digestlen, int digestalgo,
|
||||
gcry_sexp_t *r_sigval)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
membuf_t data;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
dfltparm.keyinfo.keyid = keyid;
|
||||
dfltparm.keyinfo.mainkeyid = mainkeyid;
|
||||
dfltparm.keyinfo.pubkey_algo = pubkey_algo;
|
||||
|
||||
*r_sigval = NULL;
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
if (digestlen*2 + 50 > DIM(line))
|
||||
return gpg_error (GPG_ERR_GENERAL);
|
||||
|
@ -1612,8 +1765,9 @@ agent_pksign (ctrl_t ctrl, const char *cache_nonce,
|
|||
cache_nonce? " -- ":"",
|
||||
cache_nonce? cache_nonce:"");
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data, default_inq_cb, ctrl,
|
||||
NULL, NULL);
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
if (err)
|
||||
xfree (get_membuf (&data, NULL));
|
||||
else
|
||||
|
@ -1646,11 +1800,12 @@ inq_ciphertext_cb (void *opaque, const char *line)
|
|||
if (!strncmp (line, "CIPHERTEXT", 10) && (line[10]==' '||!line[10]))
|
||||
{
|
||||
assuan_begin_confidential (parm->ctx);
|
||||
rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen);
|
||||
rc = assuan_send_data (parm->dflt->ctx,
|
||||
parm->ciphertext, parm->ciphertextlen);
|
||||
assuan_end_confidential (parm->ctx);
|
||||
}
|
||||
else
|
||||
rc = default_inq_cb (parm->ctrl, line);
|
||||
rc = default_inq_cb (parm->dflt, line);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -1659,9 +1814,12 @@ inq_ciphertext_cb (void *opaque, const char *line)
|
|||
/* Call the agent to do a decrypt operation using the key identified
|
||||
by the hex string KEYGRIP and the input data S_CIPHERTEXT. On the
|
||||
success the decoded value is stored verbatim at R_BUF and its
|
||||
length at R_BUF; the callers needs to release it. */
|
||||
length at R_BUF; the callers needs to release it. KEYID, MAINKEYID
|
||||
and PUBKEY_ALGO are used to construct additional promots or status
|
||||
messages. */
|
||||
gpg_error_t
|
||||
agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
|
||||
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
|
||||
gcry_sexp_t s_ciphertext,
|
||||
unsigned char **r_buf, size_t *r_buflen)
|
||||
{
|
||||
|
@ -1670,6 +1828,13 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
|
|||
membuf_t data;
|
||||
size_t n, len;
|
||||
char *p, *buf, *endp;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
dfltparm.keyinfo.keyid = keyid;
|
||||
dfltparm.keyinfo.mainkeyid = mainkeyid;
|
||||
dfltparm.keyinfo.pubkey_algo = pubkey_algo;
|
||||
|
||||
if (!keygrip || strlen(keygrip) != 40 || !s_ciphertext || !r_buf || !r_buflen)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
@ -1678,6 +1843,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
|
|||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
err = assuan_transact (agent_ctx, "RESET",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
@ -1703,7 +1869,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
|
|||
{
|
||||
struct cipher_parm_s parm;
|
||||
|
||||
parm.ctrl = ctrl;
|
||||
parm.dflt = &dfltparm;
|
||||
parm.ctx = agent_ctx;
|
||||
err = make_canon_sexp (s_ciphertext, &parm.ciphertext, &parm.ciphertextlen);
|
||||
if (err)
|
||||
|
@ -1772,11 +1938,16 @@ agent_keywrap_key (ctrl_t ctrl, int forexport, void **r_kek, size_t *r_keklen)
|
|||
size_t len;
|
||||
unsigned char *buf;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
*r_kek = NULL;
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
snprintf (line, DIM(line)-1, "KEYWRAP_KEY %s",
|
||||
forexport? "--export":"--import");
|
||||
|
@ -1784,7 +1955,8 @@ agent_keywrap_key (ctrl_t ctrl, int forexport, void **r_kek, size_t *r_keklen)
|
|||
init_membuf_secure (&data, 64);
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, ctrl, NULL, NULL);
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
xfree (get_membuf (&data, &len));
|
||||
|
@ -1809,10 +1981,10 @@ inq_import_key_parms (void *opaque, const char *line)
|
|||
|
||||
if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
|
||||
{
|
||||
err = assuan_send_data (parm->ctx, parm->key, parm->keylen);
|
||||
err = assuan_send_data (parm->dflt->ctx, parm->key, parm->keylen);
|
||||
}
|
||||
else
|
||||
err = default_inq_cb (parm->ctrl, line);
|
||||
err = default_inq_cb (parm->dflt, line);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -1827,10 +1999,15 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
|
|||
struct import_key_parm_s parm;
|
||||
struct cache_nonce_parm_s cn_parm;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
if (desc)
|
||||
{
|
||||
|
@ -1842,8 +2019,7 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
|
|||
return err;
|
||||
}
|
||||
|
||||
parm.ctrl = ctrl;
|
||||
parm.ctx = agent_ctx;
|
||||
parm.dflt = &dfltparm;
|
||||
parm.key = key;
|
||||
parm.keylen = keylen;
|
||||
|
||||
|
@ -1853,7 +2029,8 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
|
|||
cn_parm.cache_nonce_addr = cache_nonce_addr;
|
||||
cn_parm.passwd_nonce_addr = NULL;
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL, inq_import_key_parms, &parm,
|
||||
NULL, NULL,
|
||||
inq_import_key_parms, &parm,
|
||||
cache_nonce_status_cb, &cn_parm);
|
||||
return err;
|
||||
}
|
||||
|
@ -1875,12 +2052,17 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
|||
size_t len;
|
||||
unsigned char *buf;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
*r_result = NULL;
|
||||
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
if (desc)
|
||||
{
|
||||
|
@ -1901,7 +2083,7 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
|||
cn_parm.passwd_nonce_addr = NULL;
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, ctrl,
|
||||
default_inq_cb, &dfltparm,
|
||||
cache_nonce_status_cb, &cn_parm);
|
||||
if (err)
|
||||
{
|
||||
|
@ -1931,14 +2113,20 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
|||
gpg_error_t err;
|
||||
struct cache_nonce_parm_s cn_parm;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
if (!hexkeygrip || strlen (hexkeygrip) != 40)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
|
||||
if (desc)
|
||||
{
|
||||
snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
|
||||
|
@ -1957,7 +2145,7 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
|||
cn_parm.cache_nonce_addr = cache_nonce_addr;
|
||||
cn_parm.passwd_nonce_addr = passwd_nonce_addr;
|
||||
err = assuan_transact (agent_ctx, line, NULL, NULL,
|
||||
default_inq_cb, ctrl,
|
||||
default_inq_cb, &dfltparm,
|
||||
cache_nonce_status_cb, &cn_parm);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -81,6 +81,10 @@ int agent_learn (struct agent_card_info_s *info);
|
|||
/* Update INFO with the attribute NAME. */
|
||||
int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
|
||||
|
||||
/* Send the KEYTOCARD command. */
|
||||
int agent_keytocard (const char *hexgrip, int keyno, int force,
|
||||
const char *serialno, const char *timestamp);
|
||||
|
||||
/* Send a SETATTR command to the SCdaemon. */
|
||||
int agent_scd_setattr (const char *name,
|
||||
const unsigned char *value, size_t valuelen,
|
||||
|
@ -155,12 +159,14 @@ gpg_error_t agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
|||
/* Create a signature. */
|
||||
gpg_error_t agent_pksign (ctrl_t ctrl, const char *cache_nonce,
|
||||
const char *hexkeygrip, const char *desc,
|
||||
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
|
||||
unsigned char *digest, size_t digestlen,
|
||||
int digestalgo,
|
||||
gcry_sexp_t *r_sigval);
|
||||
|
||||
/* Decrypt a ciphertext. */
|
||||
gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
|
||||
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
|
||||
gcry_sexp_t s_ciphertext,
|
||||
unsigned char **r_buf, size_t *r_buflen);
|
||||
|
||||
|
|
212
g10/card-util.c
212
g10/card-util.c
|
@ -1264,6 +1264,7 @@ replace_existing_key_p (struct agent_card_info_s *info, int keyno)
|
|||
if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_key",
|
||||
_("Replace existing key? (y/N) ")))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1484,7 +1485,7 @@ card_generate_subkey (KBNODE pub_keyblock)
|
|||
tty_printf(_("Invalid selection.\n"));
|
||||
}
|
||||
|
||||
if (replace_existing_key_p (&info, keyno))
|
||||
if (replace_existing_key_p (&info, keyno) < 0)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_CANCELED);
|
||||
goto leave;
|
||||
|
@ -1531,152 +1532,99 @@ card_generate_subkey (KBNODE pub_keyblock)
|
|||
int
|
||||
card_store_subkey (KBNODE node, int use)
|
||||
{
|
||||
log_info ("FIXME: card_store_subkey has not yet been implemented\n");
|
||||
/* struct agent_card_info_s info; */
|
||||
/* int okay = 0; */
|
||||
/* int rc; */
|
||||
/* int keyno, i; */
|
||||
/* PKT_secret_key *copied_sk = NULL; */
|
||||
/* PKT_secret_key *sk; */
|
||||
/* size_t n; */
|
||||
/* const char *s; */
|
||||
/* int allow_keyno[3]; */
|
||||
/* unsigned int nbits; */
|
||||
struct agent_card_info_s info;
|
||||
int okay = 0;
|
||||
unsigned int nbits;
|
||||
int allow_keyno[3];
|
||||
int keyno;
|
||||
PKT_public_key *pk;
|
||||
gpg_error_t err;
|
||||
char *hexgrip;
|
||||
int rc;
|
||||
gnupg_isotime_t timebuf;
|
||||
|
||||
assert (node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
|
||||
|
||||
/* assert (node->pkt->pkttype == PKT_SECRET_KEY */
|
||||
/* || node->pkt->pkttype == PKT_SECRET_SUBKEY); */
|
||||
/* sk = node->pkt->pkt.secret_key; */
|
||||
pk = node->pkt->pkt.public_key;
|
||||
|
||||
/* if (get_info_for_key_operation (&info)) */
|
||||
/* return 0; */
|
||||
if (get_info_for_key_operation (&info))
|
||||
return 0;
|
||||
|
||||
/* if (!info.extcap.ki) */
|
||||
/* { */
|
||||
/* tty_printf ("The card does not support the import of keys\n"); */
|
||||
/* tty_printf ("\n"); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
if (!info.extcap.ki)
|
||||
{
|
||||
tty_printf ("The card does not support the import of keys\n");
|
||||
tty_printf ("\n");
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* show_card_key_info (&info); */
|
||||
nbits = nbits_from_pk (pk);
|
||||
|
||||
/* nbits = nbits_from_sk (sk); */
|
||||
if (!is_RSA (pk->pubkey_algo) || (!info.is_v2 && nbits != 1024) )
|
||||
{
|
||||
tty_printf ("You may only store a 1024 bit RSA key on the card\n");
|
||||
tty_printf ("\n");
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* if (!is_RSA (sk->pubkey_algo) || (!info.is_v2 && nbits != 1024) ) */
|
||||
/* { */
|
||||
/* tty_printf ("You may only store a 1024 bit RSA key on the card\n"); */
|
||||
/* tty_printf ("\n"); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG)));
|
||||
allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC)));
|
||||
allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH)));
|
||||
|
||||
/* allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG))); */
|
||||
/* allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC))); */
|
||||
/* allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH))); */
|
||||
tty_printf (_("Please select where to store the key:\n"));
|
||||
|
||||
/* tty_printf (_("Please select where to store the key:\n")); */
|
||||
if (allow_keyno[0])
|
||||
tty_printf (_(" (1) Signature key\n"));
|
||||
if (allow_keyno[1])
|
||||
tty_printf (_(" (2) Encryption key\n"));
|
||||
if (allow_keyno[2])
|
||||
tty_printf (_(" (3) Authentication key\n"));
|
||||
|
||||
/* if (allow_keyno[0]) */
|
||||
/* tty_printf (_(" (1) Signature key\n")); */
|
||||
/* if (allow_keyno[1]) */
|
||||
/* tty_printf (_(" (2) Encryption key\n")); */
|
||||
/* if (allow_keyno[2]) */
|
||||
/* tty_printf (_(" (3) Authentication key\n")); */
|
||||
for (;;)
|
||||
{
|
||||
char *answer = cpr_get ("cardedit.genkeys.storekeytype",
|
||||
_("Your selection? "));
|
||||
cpr_kill_prompt();
|
||||
if (*answer == CONTROL_D || !*answer)
|
||||
{
|
||||
xfree (answer);
|
||||
goto leave;
|
||||
}
|
||||
keyno = *answer? atoi(answer): 0;
|
||||
xfree(answer);
|
||||
if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1])
|
||||
{
|
||||
if (info.is_v2 && !info.extcap.aac
|
||||
&& info.key_attr[keyno-1].nbits != nbits)
|
||||
{
|
||||
tty_printf ("Key does not match the card's capability.\n");
|
||||
}
|
||||
else
|
||||
break; /* Okay. */
|
||||
}
|
||||
else
|
||||
tty_printf(_("Invalid selection.\n"));
|
||||
}
|
||||
|
||||
/* for (;;) */
|
||||
/* { */
|
||||
/* char *answer = cpr_get ("cardedit.genkeys.storekeytype", */
|
||||
/* _("Your selection? ")); */
|
||||
/* cpr_kill_prompt(); */
|
||||
/* if (*answer == CONTROL_D || !*answer) */
|
||||
/* { */
|
||||
/* xfree (answer); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
/* keyno = *answer? atoi(answer): 0; */
|
||||
/* xfree(answer); */
|
||||
/* if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1]) */
|
||||
/* { */
|
||||
/* if (info.is_v2 && !info.extcap.aac */
|
||||
/* && info.key_attr[keyno-1].nbits != nbits) */
|
||||
/* { */
|
||||
/* tty_printf ("Key does not match the card's capability.\n"); */
|
||||
/* } */
|
||||
/* else */
|
||||
/* break; /\* Okay. *\/ */
|
||||
/* } */
|
||||
/* else */
|
||||
/* tty_printf(_("Invalid selection.\n")); */
|
||||
/* } */
|
||||
if ((rc = replace_existing_key_p (&info, keyno)) < 0)
|
||||
goto leave;
|
||||
|
||||
/* if (replace_existing_key_p (&info, keyno)) */
|
||||
/* goto leave; */
|
||||
err = hexkeygrip_from_pk (pk, &hexgrip);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* /\* Unprotect key. *\/ */
|
||||
/* switch (is_secret_key_protected (sk) ) */
|
||||
/* { */
|
||||
/* case 0: /\* Not protected. *\/ */
|
||||
/* break; */
|
||||
/* case -1: */
|
||||
/* log_error (_("unknown key protection algorithm\n")); */
|
||||
/* goto leave; */
|
||||
/* default: */
|
||||
/* if (sk->protect.s2k.mode == 1001) */
|
||||
/* { */
|
||||
/* log_error (_("secret parts of key are not available\n")); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
/* if (sk->protect.s2k.mode == 1002) */
|
||||
/* { */
|
||||
/* log_error (_("secret key already stored on a card\n")); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
/* /\* We better copy the key before we unprotect it. *\/ */
|
||||
/* copied_sk = sk = copy_secret_key (NULL, sk); */
|
||||
/* rc = 0/\*check_secret_key (sk, 0)*\/; */
|
||||
/* if (rc) */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
epoch2isotime (timebuf, (time_t)pk->timestamp);
|
||||
agent_keytocard (hexgrip, keyno, rc, info.serialno, timebuf);
|
||||
|
||||
/* #warning code save_unprotected_key_to_card */
|
||||
/* /\* rc = save_unprotected_key_to_card (sk, keyno); *\/ */
|
||||
/* /\* if (rc) *\/ */
|
||||
/* /\* { *\/ */
|
||||
/* /\* log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); *\/ */
|
||||
/* /\* goto leave; *\/ */
|
||||
/* /\* } *\/ */
|
||||
if (rc)
|
||||
log_error (_("KEYTOCARD failed: %s\n"), gpg_strerror (rc));
|
||||
else
|
||||
okay = 1;
|
||||
xfree (hexgrip);
|
||||
|
||||
/* /\* Get back to the maybe protected original secret key. *\/ */
|
||||
/* if (copied_sk) */
|
||||
/* { */
|
||||
/* free_secret_key (copied_sk); */
|
||||
/* copied_sk = NULL; */
|
||||
/* } */
|
||||
/* sk = node->pkt->pkt.secret_key; */
|
||||
|
||||
/* /\* Get rid of the secret key parameters and store the serial numer. *\/ */
|
||||
/* n = pubkey_get_nskey (sk->pubkey_algo); */
|
||||
/* for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++) */
|
||||
/* { */
|
||||
/* gcry_mpi_release (sk->skey[i]); */
|
||||
/* sk->skey[i] = NULL; */
|
||||
/* } */
|
||||
/* i = pubkey_get_npkey (sk->pubkey_algo); */
|
||||
/* sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); */
|
||||
/* sk->is_protected = 1; */
|
||||
/* sk->protect.s2k.mode = 1002; */
|
||||
/* s = info.serialno; */
|
||||
/* for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; */
|
||||
/* sk->protect.ivlen++, s += 2) */
|
||||
/* sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); */
|
||||
|
||||
/* okay = 1; */
|
||||
|
||||
/* leave: */
|
||||
/* if (copied_sk) */
|
||||
/* free_secret_key (copied_sk); */
|
||||
/* agent_release_card_info (&info); */
|
||||
/* return okay; */
|
||||
return -1;
|
||||
leave:
|
||||
agent_release_card_info (&info);
|
||||
return okay;
|
||||
}
|
||||
|
||||
|
||||
|
|
14
g10/gpg.c
14
g10/gpg.c
|
@ -56,6 +56,7 @@
|
|||
#include "asshelp.h"
|
||||
#include "call-dirmngr.h"
|
||||
#include "../common/init.h"
|
||||
#include "../common/shareddefs.h"
|
||||
|
||||
#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
|
||||
#define MY_O_BINARY O_BINARY
|
||||
|
@ -217,6 +218,7 @@ enum cmd_and_opt_values
|
|||
oPassphraseFD,
|
||||
oPassphraseFile,
|
||||
oPassphraseRepeat,
|
||||
oPinentryMode,
|
||||
oCommandFD,
|
||||
oCommandFile,
|
||||
oQuickRandom,
|
||||
|
@ -611,6 +613,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||
ARGPARSE_s_i (oPassphraseFD, "passphrase-fd", "@"),
|
||||
ARGPARSE_s_s (oPassphraseFile, "passphrase-file", "@"),
|
||||
ARGPARSE_s_i (oPassphraseRepeat,"passphrase-repeat", "@"),
|
||||
ARGPARSE_s_s (oPinentryMode, "pinentry-mode", "@"),
|
||||
ARGPARSE_s_i (oCommandFD, "command-fd", "@"),
|
||||
ARGPARSE_s_s (oCommandFile, "command-file", "@"),
|
||||
ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"),
|
||||
|
@ -2594,7 +2597,16 @@ main (int argc, char **argv)
|
|||
case oPassphraseFile:
|
||||
pwfd = open_info_file (pargs.r.ret_str, 0, 1);
|
||||
break;
|
||||
case oPassphraseRepeat: opt.passphrase_repeat=pargs.r.ret_int; break;
|
||||
case oPassphraseRepeat:
|
||||
opt.passphrase_repeat = pargs.r.ret_int;
|
||||
break;
|
||||
|
||||
case oPinentryMode:
|
||||
opt.pinentry_mode = parse_pinentry_mode (pargs.r.ret_str);
|
||||
if (opt.pinentry_mode == -1)
|
||||
log_error (_("invalid pinentry mode '%s'\n"), pargs.r.ret_str);
|
||||
break;
|
||||
|
||||
case oCommandFD:
|
||||
opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
|
||||
break;
|
||||
|
|
|
@ -181,6 +181,7 @@ unsigned char encode_s2k_iterations (int iterations);
|
|||
assuan_context_t agent_open (int try, const char *orig_codeset);
|
||||
void agent_close (assuan_context_t ctx);
|
||||
int have_static_passphrase(void);
|
||||
const char *get_static_passphrase (void);
|
||||
void set_passphrase_from_string(const char *pass);
|
||||
void read_passphrase_from_fd( int fd );
|
||||
void passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo );
|
||||
|
@ -196,6 +197,8 @@ void set_next_passphrase( const char *s );
|
|||
char *get_last_passphrase(void);
|
||||
void next_to_last_passphrase(void);
|
||||
|
||||
void emit_status_need_passphrase (u32 *keyid, u32 *mainkeyid, int pubkey_algo);
|
||||
|
||||
char *gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped);
|
||||
|
||||
|
||||
|
|
|
@ -353,6 +353,8 @@ void unblock_all_signals(void);
|
|||
|
||||
/*-- server.c --*/
|
||||
int gpg_server (ctrl_t);
|
||||
gpg_error_t gpg_proxy_pinentry_notify (ctrl_t ctrl,
|
||||
const unsigned char *line);
|
||||
|
||||
#ifdef ENABLE_CARD_SUPPORT
|
||||
/*-- card-util.c --*/
|
||||
|
|
|
@ -242,6 +242,7 @@ struct
|
|||
} *auto_key_locate;
|
||||
|
||||
int passphrase_repeat;
|
||||
int pinentry_mode;
|
||||
} opt;
|
||||
|
||||
/* CTRL is used to keep some global variables we currently can't
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include "i18n.h"
|
||||
#include "status.h"
|
||||
#include "call-agent.h"
|
||||
|
||||
#include "../common/shareddefs.h"
|
||||
|
||||
static char *fd_passwd = NULL;
|
||||
static char *next_pw = NULL;
|
||||
|
@ -104,9 +104,21 @@ encode_s2k_iterations (int iterations)
|
|||
int
|
||||
have_static_passphrase()
|
||||
{
|
||||
return !!fd_passwd && opt.batch;
|
||||
return (!!fd_passwd
|
||||
&& (opt.batch || opt.pinentry_mode == PINENTRY_MODE_LOOPBACK));
|
||||
}
|
||||
|
||||
/* Return a static passphrase. The returned value is only valid as
|
||||
long as no other passphrase related function is called. NULL may
|
||||
be returned if no passphrase has been set; better use
|
||||
have_static_passphrase first. */
|
||||
const char *
|
||||
get_static_passphrase (void)
|
||||
{
|
||||
return fd_passwd;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Set the passphrase to be used for the next query and only for the next
|
||||
* one.
|
||||
|
@ -156,7 +168,7 @@ read_passphrase_from_fd( int fd )
|
|||
int i, len;
|
||||
char *pw;
|
||||
|
||||
if ( !opt.batch )
|
||||
if ( !opt.batch && opt.pinentry_mode != PINENTRY_MODE_LOOPBACK)
|
||||
{ /* Not used but we have to do a dummy read, so that it won't end
|
||||
up at the begin of the message if the quite usual trick to
|
||||
prepend the passphtrase to the message is used. */
|
||||
|
@ -187,7 +199,7 @@ read_passphrase_from_fd( int fd )
|
|||
break;
|
||||
}
|
||||
pw[i] = 0;
|
||||
if (!opt.batch)
|
||||
if (!opt.batch && opt.pinentry_mode != PINENTRY_MODE_LOOPBACK)
|
||||
tty_printf("\b\b\b \n" );
|
||||
|
||||
xfree ( fd_passwd );
|
||||
|
@ -458,30 +470,9 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
|
|||
|
||||
if ( keyid )
|
||||
{
|
||||
u32 used_kid[2];
|
||||
char *us;
|
||||
|
||||
if ( keyid[2] && keyid[3] )
|
||||
{
|
||||
used_kid[0] = keyid[2];
|
||||
used_kid[1] = keyid[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
used_kid[0] = keyid[0];
|
||||
used_kid[1] = keyid[1];
|
||||
}
|
||||
|
||||
us = get_long_user_id_string ( keyid );
|
||||
write_status_text ( STATUS_USERID_HINT, us );
|
||||
xfree(us);
|
||||
|
||||
snprintf (buf, sizeof buf -1, "%08lX%08lX %08lX%08lX %d 0",
|
||||
(ulong)keyid[0], (ulong)keyid[1],
|
||||
(ulong)used_kid[0], (ulong)used_kid[1],
|
||||
pubkey_algo );
|
||||
|
||||
write_status_text ( STATUS_NEED_PASSPHRASE, buf );
|
||||
emit_status_need_passphrase (keyid,
|
||||
keyid[2] && keyid[3]? keyid+2:NULL,
|
||||
pubkey_algo);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -614,6 +605,29 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
|
|||
}
|
||||
|
||||
|
||||
/* Emit the USERID_HINT and the NEED_PASSPHRASE status messages.
|
||||
MAINKEYID may be NULL. */
|
||||
void
|
||||
emit_status_need_passphrase (u32 *keyid, u32 *mainkeyid, int pubkey_algo)
|
||||
{
|
||||
char buf[50];
|
||||
char *us;
|
||||
|
||||
us = get_long_user_id_string (keyid);
|
||||
write_status_text (STATUS_USERID_HINT, us);
|
||||
xfree (us);
|
||||
|
||||
snprintf (buf, sizeof buf -1, "%08lX%08lX %08lX%08lX %d 0",
|
||||
(ulong)keyid[0],
|
||||
(ulong)keyid[1],
|
||||
(ulong)(mainkeyid? mainkeyid[0]:keyid[0]),
|
||||
(ulong)(mainkeyid? mainkeyid[1]:keyid[1]),
|
||||
pubkey_algo);
|
||||
|
||||
write_status_text (STATUS_NEED_PASSPHRASE, buf);
|
||||
}
|
||||
|
||||
|
||||
/* Return an allocated utf-8 string describing the key PK. If ESCAPED
|
||||
is true spaces and control characters are percent or plus escaped.
|
||||
MODE 0 is for the common prompt, MODE 1 for the import prompt. */
|
||||
|
|
|
@ -201,7 +201,9 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
|
|||
|
||||
/* Decrypt. */
|
||||
desc = gpg_format_keydesc (sk, 0, 1);
|
||||
err = agent_pkdecrypt (NULL, keygrip, desc, s_data, &frame, &nframe);
|
||||
err = agent_pkdecrypt (NULL, keygrip,
|
||||
desc, sk->keyid, sk->main_keyid, sk->pubkey_algo,
|
||||
s_data, &frame, &nframe);
|
||||
xfree (desc);
|
||||
gcry_sexp_release (s_data);
|
||||
if (err)
|
||||
|
|
36
g10/server.c
36
g10/server.c
|
@ -50,6 +50,9 @@ struct server_local_s
|
|||
/* List of prepared recipients. */
|
||||
pk_list_t recplist;
|
||||
|
||||
/* Set if pinentry notifications should be passed back to the
|
||||
client. */
|
||||
int allow_pinentry_notify;
|
||||
};
|
||||
|
||||
|
||||
|
@ -105,9 +108,8 @@ has_option (const char *line, const char *name)
|
|||
static gpg_error_t
|
||||
option_handler (assuan_context_t ctx, const char *key, const char *value)
|
||||
{
|
||||
/* ctrl_t ctrl = assuan_get_pointer (ctx); */
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
(void)ctx;
|
||||
(void)value;
|
||||
|
||||
/* Fixme: Implement the tty and locale args. */
|
||||
|
@ -136,6 +138,10 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
|
|||
{
|
||||
/* This is for now a dummy option. */
|
||||
}
|
||||
else if (!strcmp (key, "allow-pinentry-notify"))
|
||||
{
|
||||
ctrl->server_local->allow_pinentry_notify = 1;
|
||||
}
|
||||
else
|
||||
return gpg_error (GPG_ERR_UNKNOWN_OPTION);
|
||||
|
||||
|
@ -768,3 +774,29 @@ gpg_server (ctrl_t ctrl)
|
|||
assuan_release (ctx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Helper to notify the client about Pinentry events. Because that
|
||||
might disturb some older clients, this is only done when enabled
|
||||
via an option. If it is not enabled we tell Windows to allow
|
||||
setting the foreground window right here. Returns an gpg error
|
||||
code. */
|
||||
gpg_error_t
|
||||
gpg_proxy_pinentry_notify (ctrl_t ctrl, const unsigned char *line)
|
||||
{
|
||||
if (!ctrl || !ctrl->server_local
|
||||
|| !ctrl->server_local->allow_pinentry_notify)
|
||||
{
|
||||
gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
|
||||
/* Client might be interested in that event - send as status line. */
|
||||
if (!strncmp (line, "PINENTRY_LAUNCHED", 17)
|
||||
&& (line[17]==' '||!line[17]))
|
||||
{
|
||||
for (line += 17; *line && spacep (line); line++)
|
||||
;
|
||||
write_status_text (STATUS_PINENTRY_LAUNCHED, line);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);
|
||||
}
|
||||
|
|
|
@ -272,6 +272,7 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
|
|||
|
||||
desc = gpg_format_keydesc (pksk, 0, 1);
|
||||
err = agent_pksign (NULL/*ctrl*/, cache_nonce, hexgrip, desc,
|
||||
pksk->keyid, pksk->main_keyid, pksk->pubkey_algo,
|
||||
dp, gcry_md_get_algo_dlen (mdalgo), mdalgo,
|
||||
&s_sigval);
|
||||
xfree (desc);
|
||||
|
@ -1604,6 +1605,8 @@ update_keysig_packet( PKT_signature **ret_sig,
|
|||
/* create a new signature packet */
|
||||
sig = copy_signature (NULL, orig_sig);
|
||||
|
||||
sig->digest_algo=digest_algo;
|
||||
|
||||
/* We need to create a new timestamp so that new sig expiration
|
||||
calculations are done correctly... */
|
||||
sig->timestamp=make_timestamp();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue