mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Generating an OpenPGP key cia gpg-agent basically works.
This commit is contained in:
parent
67934a8c13
commit
21b0a955be
@ -1,3 +1,38 @@
|
|||||||
|
2010-04-20 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* keylist.c (list_keyblock_colon): Print the keygrip.
|
||||||
|
|
||||||
|
* sign.c (do_sign): Call the agent to create the signature.
|
||||||
|
(mpi_from_sexp): New.
|
||||||
|
* keyid.c (keygrip_from_pk, hexkeygrip_from_pk): New.
|
||||||
|
* call-agent.c (agent_pksign): New.
|
||||||
|
* pkglue.c (pk_sign): Remove.
|
||||||
|
|
||||||
|
* keygen.c (generate_keypair): Do not ask for a passphrase.
|
||||||
|
|
||||||
|
2010-04-15 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* keygen.c (gen_dsa, gen_elg, gen_rsa): Remove args SEC_ROOT, DEK,
|
||||||
|
S2K and RET_SK. Change to use the gpg-agent based key generation.
|
||||||
|
Factor common code out to ...
|
||||||
|
(common_gen): New.
|
||||||
|
(do_create): Remove args SEC_ROOT, DEK, S2K and RET_SK.
|
||||||
|
(do_generate_keypair, write_selfsigs, write_direct_sig)
|
||||||
|
(write_keybinding, make_backsig): Adjust for above changes.
|
||||||
|
(generate_subkeypair): Remove arg SEC_KEYBLOCK.
|
||||||
|
(genhelp_protect, genhelp_factors): Remove.
|
||||||
|
(get_parameter_dek, get_parameter_s2k): Remove.
|
||||||
|
|
||||||
|
* call-agent.c (start_agent): Add dummy arg CTRL.
|
||||||
|
(agent_havekey, keyinfo_status_cb, agent_get_keyinfo)
|
||||||
|
(agent_genkey): New.
|
||||||
|
|
||||||
|
* seckey-cert.c (check_secret_key): Remove
|
||||||
|
(is_secret_key_protected): Take a public key as arg.
|
||||||
|
(protect_secret_key): Remove.
|
||||||
|
|
||||||
|
* seskey.c (encode_md_value): Remove SK arg.
|
||||||
|
|
||||||
2010-04-14 Werner Koch <wk@g10code.com>
|
2010-04-14 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* cpr.c (myread) [W32CE]: Do not use raise.
|
* cpr.c (myread) [W32CE]: Do not use raise.
|
||||||
|
331
g10/call-agent.c
331
g10/call-agent.c
@ -1,6 +1,6 @@
|
|||||||
/* call-agent.c - Divert GPG operations to the agent.
|
/* call-agent.c - Divert GPG operations to the agent.
|
||||||
* Copyright (C) 2001, 2002, 2003, 2006, 2007,
|
* Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009,
|
||||||
* 2008, 2009 Free Software Foundation, Inc.
|
* 2010 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -71,12 +71,13 @@ struct writekey_parm_s
|
|||||||
|
|
||||||
struct genkey_parm_s
|
struct genkey_parm_s
|
||||||
{
|
{
|
||||||
|
ctrl_t ctrl;
|
||||||
assuan_context_t ctx;
|
assuan_context_t ctx;
|
||||||
const char *sexp;
|
const char *keyparms;
|
||||||
size_t sexplen;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static gpg_error_t learn_status_cb (void *opaque, const char *line);
|
static gpg_error_t learn_status_cb (void *opaque, const char *line);
|
||||||
|
|
||||||
|
|
||||||
@ -107,10 +108,12 @@ status_sc_op_failure (int rc)
|
|||||||
/* Try to connect to the agent via socket or fork it off and work by
|
/* Try to connect to the agent via socket or fork it off and work by
|
||||||
pipes. Handle the server's initial greeting */
|
pipes. Handle the server's initial greeting */
|
||||||
static int
|
static int
|
||||||
start_agent (int for_card)
|
start_agent (ctrl_t ctrl, int for_card)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
(void)ctrl; /* Not yet used. */
|
||||||
|
|
||||||
/* Fixme: We need a context for each thread or serialize the access
|
/* Fixme: We need a context for each thread or serialize the access
|
||||||
to the agent. */
|
to the agent. */
|
||||||
if (agent_ctx)
|
if (agent_ctx)
|
||||||
@ -486,7 +489,7 @@ agent_learn (struct agent_card_info_s *info)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = start_agent (1);
|
rc = start_agent (NULL, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -531,7 +534,7 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
|
|||||||
return gpg_error (GPG_ERR_TOO_LARGE);
|
return gpg_error (GPG_ERR_TOO_LARGE);
|
||||||
stpcpy (stpcpy (line, "SCD GETATTR "), name);
|
stpcpy (stpcpy (line, "SCD GETATTR "), name);
|
||||||
|
|
||||||
rc = start_agent (1);
|
rc = start_agent (NULL, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -581,7 +584,7 @@ agent_scd_setattr (const char *name,
|
|||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
rc = start_agent (1);
|
rc = start_agent (NULL, 1);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
rc = assuan_transact (agent_ctx, line, NULL, NULL,
|
rc = assuan_transact (agent_ctx, line, NULL, NULL,
|
||||||
@ -623,7 +626,7 @@ agent_scd_writecert (const char *certidstr,
|
|||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
struct writecert_parm_s parms;
|
struct writecert_parm_s parms;
|
||||||
|
|
||||||
rc = start_agent (1);
|
rc = start_agent (NULL, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -673,7 +676,7 @@ agent_scd_writekey (int keyno, const char *serialno,
|
|||||||
|
|
||||||
(void)serialno;
|
(void)serialno;
|
||||||
|
|
||||||
rc = start_agent (1);
|
rc = start_agent (NULL, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -762,7 +765,7 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
|
|||||||
|
|
||||||
(void)serialno;
|
(void)serialno;
|
||||||
|
|
||||||
rc = start_agent (1);
|
rc = start_agent (NULL, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -909,7 +912,7 @@ agent_scd_pksign (const char *serialno, int hashalgo,
|
|||||||
*r_buf = NULL;
|
*r_buf = NULL;
|
||||||
*r_buflen = 0;
|
*r_buflen = 0;
|
||||||
|
|
||||||
rc = start_agent (1);
|
rc = start_agent (NULL, 1);
|
||||||
if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT
|
if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT
|
||||||
|| gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
|
|| gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
|
||||||
rc = 0; /* We check later. */
|
rc = 0; /* We check later. */
|
||||||
@ -972,7 +975,7 @@ agent_scd_pkdecrypt (const char *serialno,
|
|||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
*r_buf = NULL;
|
*r_buf = NULL;
|
||||||
rc = start_agent (1);
|
rc = start_agent (NULL, 1);
|
||||||
if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT
|
if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT
|
||||||
|| gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
|
|| gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
|
||||||
rc = 0; /* We check later. */
|
rc = 0; /* We check later. */
|
||||||
@ -1029,7 +1032,7 @@ agent_scd_readcert (const char *certidstr,
|
|||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
*r_buf = NULL;
|
*r_buf = NULL;
|
||||||
rc = start_agent (1);
|
rc = start_agent (NULL, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -1077,7 +1080,7 @@ agent_scd_change_pin (int chvno, const char *serialno)
|
|||||||
reset = "--reset";
|
reset = "--reset";
|
||||||
chvno %= 100;
|
chvno %= 100;
|
||||||
|
|
||||||
rc = start_agent (1);
|
rc = start_agent (NULL, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -1099,7 +1102,7 @@ agent_scd_checkpin (const char *serialno)
|
|||||||
int rc;
|
int rc;
|
||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
|
||||||
rc = start_agent (1);
|
rc = start_agent (NULL, 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -1146,7 +1149,7 @@ agent_get_passphrase (const char *cache_id,
|
|||||||
|
|
||||||
*r_passphrase = NULL;
|
*r_passphrase = NULL;
|
||||||
|
|
||||||
rc = start_agent (0);
|
rc = start_agent (NULL, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -1217,7 +1220,7 @@ agent_clear_passphrase (const char *cache_id)
|
|||||||
if (!cache_id || !*cache_id)
|
if (!cache_id || !*cache_id)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rc = start_agent (0);
|
rc = start_agent (NULL, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -1237,7 +1240,7 @@ gpg_agent_get_confirmation (const char *desc)
|
|||||||
char *tmp;
|
char *tmp;
|
||||||
char line[ASSUAN_LINELENGTH];
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
|
||||||
rc = start_agent (0);
|
rc = start_agent (NULL, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -1264,7 +1267,7 @@ agent_get_s2k_count (unsigned long *r_count)
|
|||||||
|
|
||||||
*r_count = 0;
|
*r_count = 0;
|
||||||
|
|
||||||
err = start_agent (0);
|
err = start_agent (NULL, 0);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -1289,3 +1292,291 @@ agent_get_s2k_count (unsigned long *r_count)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Ask the agent whether a secret key with the given keygrip is
|
||||||
|
known. */
|
||||||
|
gpg_error_t
|
||||||
|
agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
|
||||||
|
err = start_agent (ctrl, 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (!hexkeygrip || strlen (hexkeygrip) != 40)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
|
||||||
|
line[DIM(line)-1] = 0;
|
||||||
|
|
||||||
|
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static gpg_error_t
|
||||||
|
keyinfo_status_cb (void *opaque, const char *line)
|
||||||
|
{
|
||||||
|
char **serialno = opaque;
|
||||||
|
const char *s, *s2;
|
||||||
|
|
||||||
|
if (!strncmp (line, "KEYINFO ", 8) && !*serialno)
|
||||||
|
{
|
||||||
|
s = strchr (line+8, ' ');
|
||||||
|
if (s && s[1] == 'T' && s[2] == ' ' && s[3])
|
||||||
|
{
|
||||||
|
s += 3;
|
||||||
|
s2 = strchr (s, ' ');
|
||||||
|
if ( s2 > s )
|
||||||
|
{
|
||||||
|
*serialno = xtrymalloc ((s2 - s)+1);
|
||||||
|
if (*serialno)
|
||||||
|
{
|
||||||
|
memcpy (*serialno, s, s2 - s);
|
||||||
|
(*serialno)[s2 - s] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the serial number for a secret key. If the returned serial
|
||||||
|
number is NULL, the key is not stored on a smartcard. Caller needs
|
||||||
|
to free R_SERIALNO. */
|
||||||
|
gpg_error_t
|
||||||
|
agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
char line[ASSUAN_LINELENGTH];
|
||||||
|
char *serialno = NULL;
|
||||||
|
|
||||||
|
*r_serialno = NULL;
|
||||||
|
|
||||||
|
err = start_agent (ctrl, 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (!hexkeygrip || strlen (hexkeygrip) != 40)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
snprintf (line, DIM(line)-1, "KEYINFO %s", hexkeygrip);
|
||||||
|
line[DIM(line)-1] = 0;
|
||||||
|
|
||||||
|
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
|
||||||
|
keyinfo_status_cb, &serialno);
|
||||||
|
if (!err && serialno)
|
||||||
|
{
|
||||||
|
/* Sanity check for bad characters. */
|
||||||
|
if (strpbrk (serialno, ":\n\r"))
|
||||||
|
err = GPG_ERR_INV_VALUE;
|
||||||
|
}
|
||||||
|
if (err)
|
||||||
|
xfree (serialno);
|
||||||
|
else
|
||||||
|
*r_serialno = serialno;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Handle a KEYPARMS inquiry. Note, we only send the data,
|
||||||
|
assuan_transact takes care of flushing and writing the end */
|
||||||
|
static gpg_error_t
|
||||||
|
inq_genkey_parms (void *opaque, const char *line)
|
||||||
|
{
|
||||||
|
struct genkey_parm_s *parm = opaque;
|
||||||
|
gpg_error_t err;
|
||||||
|
|
||||||
|
if (!strncmp (line, "KEYPARAM", 8) && (line[8]==' '||!line[8]))
|
||||||
|
{
|
||||||
|
err = assuan_send_data (parm->ctx,
|
||||||
|
parm->keyparms, strlen (parm->keyparms));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
err = default_inq_cb (parm->ctrl, line);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Call the agent to generate a new key. KEYPARMS is the usual
|
||||||
|
S-expression giving the parameters of the key. gpg-agent passes it
|
||||||
|
gcry_pk_genkey. */
|
||||||
|
gpg_error_t
|
||||||
|
agent_genkey (ctrl_t ctrl, const char *keyparms, gcry_sexp_t *r_pubkey)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
struct genkey_parm_s gk_parm;
|
||||||
|
membuf_t data;
|
||||||
|
size_t len;
|
||||||
|
unsigned char *buf;
|
||||||
|
|
||||||
|
*r_pubkey = NULL;
|
||||||
|
err = start_agent (ctrl, 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = assuan_transact (agent_ctx, "RESET",
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
init_membuf (&data, 1024);
|
||||||
|
gk_parm.ctrl = ctrl;
|
||||||
|
gk_parm.ctx = agent_ctx;
|
||||||
|
gk_parm.keyparms = keyparms;
|
||||||
|
err = assuan_transact (agent_ctx, "GENKEY",
|
||||||
|
membuf_data_cb, &data,
|
||||||
|
inq_genkey_parms, &gk_parm, NULL, NULL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
xfree (get_membuf (&data, &len));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = get_membuf (&data, &len);
|
||||||
|
if (!buf)
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = gcry_sexp_sscan (r_pubkey, NULL, buf, len);
|
||||||
|
xfree (buf);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME: Call the agent to read the public key part for a given keygrip. If
|
||||||
|
FROMCARD is true, the key is directly read from the current
|
||||||
|
smartcard. In this case HEXKEYGRIP should be the keyID
|
||||||
|
(e.g. OPENPGP.3). */
|
||||||
|
/* int */
|
||||||
|
/* agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip, */
|
||||||
|
/* ksba_sexp_t *r_pubkey) */
|
||||||
|
/* { */
|
||||||
|
/* int rc; */
|
||||||
|
/* membuf_t data; */
|
||||||
|
/* size_t len; */
|
||||||
|
/* unsigned char *buf; */
|
||||||
|
/* char line[ASSUAN_LINELENGTH]; */
|
||||||
|
|
||||||
|
/* *r_pubkey = NULL; */
|
||||||
|
/* rc = start_agent (ctrl); */
|
||||||
|
/* if (rc) */
|
||||||
|
/* return rc; */
|
||||||
|
|
||||||
|
/* rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL); */
|
||||||
|
/* if (rc) */
|
||||||
|
/* return rc; */
|
||||||
|
|
||||||
|
/* snprintf (line, DIM(line)-1, "%sREADKEY %s", */
|
||||||
|
/* fromcard? "SCD ":"", hexkeygrip); */
|
||||||
|
/* line[DIM(line)-1] = 0; */
|
||||||
|
|
||||||
|
/* init_membuf (&data, 1024); */
|
||||||
|
/* rc = assuan_transact (agent_ctx, line, */
|
||||||
|
/* membuf_data_cb, &data, */
|
||||||
|
/* default_inq_cb, ctrl, NULL, NULL); */
|
||||||
|
/* if (rc) */
|
||||||
|
/* { */
|
||||||
|
/* xfree (get_membuf (&data, &len)); */
|
||||||
|
/* return rc; */
|
||||||
|
/* } */
|
||||||
|
/* buf = get_membuf (&data, &len); */
|
||||||
|
/* if (!buf) */
|
||||||
|
/* return gpg_error (GPG_ERR_ENOMEM); */
|
||||||
|
/* if (!gcry_sexp_canon_len (buf, len, NULL, NULL)) */
|
||||||
|
/* { */
|
||||||
|
/* xfree (buf); */
|
||||||
|
/* return gpg_error (GPG_ERR_INV_SEXP); */
|
||||||
|
/* } */
|
||||||
|
/* *r_pubkey = buf; */
|
||||||
|
/* return 0; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Call the agent to do a sign operation using the key identified by
|
||||||
|
the hex string KEYGRIP. DESC is a description of the key to be
|
||||||
|
displayed if the agent needs to ask for the PIN. DIGEST and
|
||||||
|
DIGESTLEN is the hash value to sign and DIGESTALGO the algorithm id
|
||||||
|
used to compute the digest. */
|
||||||
|
gpg_error_t
|
||||||
|
agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
|
||||||
|
unsigned char *digest, size_t digestlen, int digestalgo,
|
||||||
|
gcry_sexp_t *r_sigval)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
int i;
|
||||||
|
char *p, line[ASSUAN_LINELENGTH];
|
||||||
|
membuf_t data;
|
||||||
|
|
||||||
|
*r_sigval = NULL;
|
||||||
|
err = start_agent (ctrl, 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (digestlen*2 + 50 > DIM(line))
|
||||||
|
return gpg_error (GPG_ERR_GENERAL);
|
||||||
|
|
||||||
|
err = assuan_transact (agent_ctx, "RESET",
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip);
|
||||||
|
line[DIM(line)-1] = 0;
|
||||||
|
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (desc)
|
||||||
|
{
|
||||||
|
snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
|
||||||
|
line[DIM(line)-1] = 0;
|
||||||
|
err = assuan_transact (agent_ctx, line,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf (line, sizeof line, "SETHASH %d ", digestalgo);
|
||||||
|
p = line + strlen (line);
|
||||||
|
for (i=0; i < digestlen ; i++, p += 2 )
|
||||||
|
sprintf (p, "%02X", digest[i]);
|
||||||
|
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
init_membuf (&data, 1024);
|
||||||
|
err = assuan_transact (agent_ctx, "PKSIGN",
|
||||||
|
membuf_data_cb, &data, default_inq_cb, ctrl,
|
||||||
|
NULL, NULL);
|
||||||
|
if (err)
|
||||||
|
xfree (get_membuf (&data, NULL));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned char *buf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
buf = get_membuf (&data, &len);
|
||||||
|
if (!buf)
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = gcry_sexp_sscan (r_sigval, NULL, buf, len);
|
||||||
|
xfree (buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,6 +140,24 @@ gpg_error_t gpg_agent_get_confirmation (const char *desc);
|
|||||||
/* Return the S2K iteration count as computed by gpg-agent. */
|
/* Return the S2K iteration count as computed by gpg-agent. */
|
||||||
gpg_error_t agent_get_s2k_count (unsigned long *r_count);
|
gpg_error_t agent_get_s2k_count (unsigned long *r_count);
|
||||||
|
|
||||||
|
/* Check whether a secret key with HEXKEYGRIP is available. */
|
||||||
|
gpg_error_t agent_havekey (ctrl_t ctrl, const char *hexkeygrip);
|
||||||
|
|
||||||
|
/* Return infos about the secret key with HEXKEYGRIP. */
|
||||||
|
gpg_error_t agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
|
||||||
|
char **r_serialno);
|
||||||
|
|
||||||
|
/* Generate a new key. */
|
||||||
|
gpg_error_t agent_genkey (ctrl_t ctrl, const char *keyparms,
|
||||||
|
gcry_sexp_t *r_pubkey);
|
||||||
|
|
||||||
|
/* Create a sigtnature. */
|
||||||
|
gpg_error_t agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
|
||||||
|
unsigned char *digest, size_t digestlen,
|
||||||
|
int digestalgo,
|
||||||
|
gcry_sexp_t *r_sigval);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_G10_CALL_AGENT_H*/
|
#endif /*GNUPG_G10_CALL_AGENT_H*/
|
||||||
|
|
||||||
|
@ -1495,8 +1495,8 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
|
|||||||
the serialnumber and thus it won't harm. */
|
the serialnumber and thus it won't harm. */
|
||||||
}
|
}
|
||||||
|
|
||||||
okay = generate_card_subkeypair (pub_keyblock, sec_keyblock,
|
/* xxx = generate_card_subkeypair (pub_keyblock, sec_keyblock, */
|
||||||
keyno, info.serialno);
|
/* keyno, info.serialno); */
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
agent_release_card_info (&info);
|
agent_release_card_info (&info);
|
||||||
@ -1612,17 +1612,18 @@ card_store_subkey (KBNODE node, int use)
|
|||||||
}
|
}
|
||||||
/* We better copy the key before we unprotect it. */
|
/* We better copy the key before we unprotect it. */
|
||||||
copied_sk = sk = copy_secret_key (NULL, sk);
|
copied_sk = sk = copy_secret_key (NULL, sk);
|
||||||
rc = check_secret_key (sk, 0);
|
rc = 0/*check_secret_key (sk, 0)*/;
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = save_unprotected_key_to_card (sk, keyno);
|
#warning code save_unprotected_key_to_card
|
||||||
if (rc)
|
/* rc = save_unprotected_key_to_card (sk, keyno); */
|
||||||
{
|
/* if (rc) */
|
||||||
log_error (_("error writing key to card: %s\n"), gpg_strerror (rc));
|
/* { */
|
||||||
goto leave;
|
/* log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); */
|
||||||
}
|
/* goto leave; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
/* Get back to the maybe protected original secret key. */
|
/* Get back to the maybe protected original secret key. */
|
||||||
if (copied_sk)
|
if (copied_sk)
|
||||||
|
@ -550,7 +550,7 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
|
|||||||
; /* Card key stub. */
|
; /* Card key stub. */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rc = check_secret_key( sk, 0 );
|
/* rc = check_secret_key( sk, 0 ); */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -526,7 +526,7 @@ get_seckey (PKT_secret_key * sk, u32 * keyid)
|
|||||||
{
|
{
|
||||||
/* Check the secret key (this may prompt for a passprase to
|
/* Check the secret key (this may prompt for a passprase to
|
||||||
* unlock the secret key. */
|
* unlock the secret key. */
|
||||||
rc = check_secret_key (sk, 0);
|
/* rc = check_secret_key (sk, 0); */
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -1111,8 +1111,8 @@ get_seckey_byname2 (GETKEY_CTX * retctx,
|
|||||||
|
|
||||||
free_strlist (namelist);
|
free_strlist (namelist);
|
||||||
|
|
||||||
if (!rc && unprotect)
|
/* if (!rc && unprotect) */
|
||||||
rc = check_secret_key (sk, 0);
|
/* rc = check_secret_key (sk, 0); */
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -399,9 +399,9 @@ display_online_help (const char *keyword)
|
|||||||
* We don't use secret keys, but getkey.c links to this
|
* We don't use secret keys, but getkey.c links to this
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
check_secret_key (PKT_secret_key *sk, int n)
|
check_secret_key (PKT_public_key *pk, int n)
|
||||||
{
|
{
|
||||||
(void)sk;
|
(void)pk;
|
||||||
(void)n;
|
(void)n;
|
||||||
return G10ERR_GENERAL;
|
return G10ERR_GENERAL;
|
||||||
}
|
}
|
||||||
|
@ -286,6 +286,9 @@ byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf, size_t *ret_len );
|
|||||||
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
|
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
|
||||||
char *serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
|
char *serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
|
||||||
PKT_secret_key *sk);
|
PKT_secret_key *sk);
|
||||||
|
gpg_error_t keygrip_from_pk (PKT_public_key *pk, unsigned char *array);
|
||||||
|
gpg_error_t hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip);
|
||||||
|
|
||||||
|
|
||||||
/*-- kbnode.c --*/
|
/*-- kbnode.c --*/
|
||||||
KBNODE new_kbnode( PACKET *pkt );
|
KBNODE new_kbnode( PACKET *pkt );
|
||||||
|
@ -1164,9 +1164,9 @@ change_passphrase (KBNODE keyblock, int *r_err)
|
|||||||
keyid_from_sk (sk, keyid);
|
keyid_from_sk (sk, keyid);
|
||||||
passphrase_clear_cache (keyid, NULL, 0);
|
passphrase_clear_cache (keyid, NULL, 0);
|
||||||
|
|
||||||
rc = check_secret_key( sk, 0 );
|
/* rc = check_secret_key( sk, 0 ); */
|
||||||
if( !rc )
|
/* if( !rc ) */
|
||||||
passphrase = get_last_passphrase();
|
/* passphrase = get_last_passphrase(); */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1179,9 +1179,9 @@ change_passphrase (KBNODE keyblock, int *r_err)
|
|||||||
&& (subsk->protect.s2k.mode == 1001
|
&& (subsk->protect.s2k.mode == 1001
|
||||||
|| subsk->protect.s2k.mode == 1002))) {
|
|| subsk->protect.s2k.mode == 1002))) {
|
||||||
set_next_passphrase( passphrase );
|
set_next_passphrase( passphrase );
|
||||||
rc = check_secret_key( subsk, 0 );
|
/* rc = check_secret_key( subsk, 0 ); */
|
||||||
if( !rc && !passphrase )
|
/* if( !rc && !passphrase ) */
|
||||||
passphrase = get_last_passphrase();
|
/* passphrase = get_last_passphrase(); */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1227,7 +1227,9 @@ change_passphrase (KBNODE keyblock, int *r_err)
|
|||||||
if( !no_primary_secrets ) {
|
if( !no_primary_secrets ) {
|
||||||
sk->protect.algo = dek->algo;
|
sk->protect.algo = dek->algo;
|
||||||
sk->protect.s2k = *s2k;
|
sk->protect.s2k = *s2k;
|
||||||
rc = protect_secret_key( sk, dek );
|
#warning fixme
|
||||||
|
rc = 0;
|
||||||
|
/* rc = protect_secret_key( sk, dek ); */
|
||||||
}
|
}
|
||||||
for(node=keyblock; !rc && node; node = node->next ) {
|
for(node=keyblock; !rc && node; node = node->next ) {
|
||||||
if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
|
if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
|
||||||
@ -1237,7 +1239,9 @@ change_passphrase (KBNODE keyblock, int *r_err)
|
|||||||
|| subsk->protect.s2k.mode == 1002))) {
|
|| subsk->protect.s2k.mode == 1002))) {
|
||||||
subsk->protect.algo = dek->algo;
|
subsk->protect.algo = dek->algo;
|
||||||
subsk->protect.s2k = *s2k;
|
subsk->protect.s2k = *s2k;
|
||||||
rc = protect_secret_key( subsk, dek );
|
#warning fixme
|
||||||
|
rc = 0;
|
||||||
|
/* rc = protect_secret_key( subsk, dek ); */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1892,7 +1896,8 @@ keyedit_menu( const char *username, strlist_t locusr,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case cmdADDKEY:
|
case cmdADDKEY:
|
||||||
if( generate_subkeypair( keyblock, sec_keyblock ) ) {
|
if (!generate_subkeypair (keyblock))
|
||||||
|
{
|
||||||
redisplay = 1;
|
redisplay = 1;
|
||||||
sec_modified = modified = 1;
|
sec_modified = modified = 1;
|
||||||
merge_keys_and_selfsig( sec_keyblock );
|
merge_keys_and_selfsig( sec_keyblock );
|
||||||
@ -2018,8 +2023,8 @@ keyedit_menu( const char *username, strlist_t locusr,
|
|||||||
if (sk->protect.s2k.mode == 1002)
|
if (sk->protect.s2k.mode == 1002)
|
||||||
tty_printf (_("Secret parts of key"
|
tty_printf (_("Secret parts of key"
|
||||||
" are stored on-card.\n"));
|
" are stored on-card.\n"));
|
||||||
else
|
/* else */
|
||||||
check_secret_key (sk, 0);
|
/* check_secret_key (sk, 0); */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* Store it. */
|
else /* Store it. */
|
||||||
|
958
g10/keygen.c
958
g10/keygen.c
File diff suppressed because it is too large
Load Diff
89
g10/keyid.c
89
g10/keyid.c
@ -1,6 +1,6 @@
|
|||||||
/* keyid.c - key ID and fingerprint handling
|
/* keyid.c - key ID and fingerprint handling
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001, 2003,
|
* Copyright (C) 1998, 1999, 2000, 2001, 2003,
|
||||||
* 2004, 2006 Free Software Foundation, Inc.
|
* 2004, 2006, 2010 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -828,3 +828,90 @@ serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Return the so called KEYGRIP which is the SHA-1 hash of the public
|
||||||
|
key parameters expressed as an canoncial encoded S-Exp. ARRAY must
|
||||||
|
be 20 bytes long. Returns 0 on sucess or an error code. */
|
||||||
|
gpg_error_t
|
||||||
|
keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
gcry_sexp_t s_pkey;
|
||||||
|
|
||||||
|
if (DBG_PACKET)
|
||||||
|
log_debug ("get_keygrip for public key\n");
|
||||||
|
|
||||||
|
switch (pk->pubkey_algo)
|
||||||
|
{
|
||||||
|
case GCRY_PK_DSA:
|
||||||
|
err = gcry_sexp_build (&s_pkey, NULL,
|
||||||
|
"(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
|
||||||
|
pk->pkey[0], pk->pkey[1],
|
||||||
|
pk->pkey[2], pk->pkey[3]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GCRY_PK_ELG:
|
||||||
|
case GCRY_PK_ELG_E:
|
||||||
|
err = gcry_sexp_build (&s_pkey, NULL,
|
||||||
|
"(public-key(elg(p%m)(g%m)(y%m)))",
|
||||||
|
pk->pkey[0], pk->pkey[1], pk->pkey[2]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GCRY_PK_RSA:
|
||||||
|
case GCRY_PK_RSA_S:
|
||||||
|
case GCRY_PK_RSA_E:
|
||||||
|
err = gcry_sexp_build (&s_pkey, NULL,
|
||||||
|
"(public-key(rsa(n%m)(e%m)))",
|
||||||
|
pk->pkey[0], pk->pkey[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (!gcry_pk_get_keygrip (s_pkey, array))
|
||||||
|
{
|
||||||
|
log_error ("error computing keygrip\n");
|
||||||
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (DBG_PACKET)
|
||||||
|
log_printhex ("keygrip=", array, 20);
|
||||||
|
/* FIXME: Save the keygrip in PK. */
|
||||||
|
}
|
||||||
|
gcry_sexp_release (s_pkey);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Store an allocated buffer with the keygrip of PK encoded as a
|
||||||
|
hexstring at r_GRIP. Returns 0 on success. */
|
||||||
|
gpg_error_t
|
||||||
|
hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
unsigned char grip[20];
|
||||||
|
|
||||||
|
*r_grip = NULL;
|
||||||
|
err = keygrip_from_pk (pk, grip);
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
char * buf = xtrymalloc (20*2+1);
|
||||||
|
if (!buf)
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bin2hex (grip, 20, buf);
|
||||||
|
*r_grip = buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1063,6 +1063,7 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
|||||||
int trustletter = 0;
|
int trustletter = 0;
|
||||||
int ulti_hack = 0;
|
int ulti_hack = 0;
|
||||||
int i;
|
int i;
|
||||||
|
char *p;
|
||||||
|
|
||||||
/* Get the keyid from the keyblock. */
|
/* Get the keyid from the keyblock. */
|
||||||
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
||||||
@ -1128,7 +1129,14 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
|||||||
if (fpr)
|
if (fpr)
|
||||||
print_fingerprint (pk, NULL, 0);
|
print_fingerprint (pk, NULL, 0);
|
||||||
if (opt.with_key_data)
|
if (opt.with_key_data)
|
||||||
|
{
|
||||||
|
if (!hexkeygrip_from_pk (pk, &p))
|
||||||
|
{
|
||||||
|
es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
|
||||||
|
xfree (p);
|
||||||
|
}
|
||||||
print_key_data (pk);
|
print_key_data (pk);
|
||||||
|
}
|
||||||
|
|
||||||
for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
|
for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
|
||||||
{
|
{
|
||||||
@ -1226,8 +1234,15 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
|||||||
if (fpr > 1)
|
if (fpr > 1)
|
||||||
print_fingerprint (pk2, NULL, 0);
|
print_fingerprint (pk2, NULL, 0);
|
||||||
if (opt.with_key_data)
|
if (opt.with_key_data)
|
||||||
|
{
|
||||||
|
if (!hexkeygrip_from_pk (pk2, &p))
|
||||||
|
{
|
||||||
|
es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
|
||||||
|
xfree (p);
|
||||||
|
}
|
||||||
print_key_data (pk2);
|
print_key_data (pk2);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE)
|
else if (opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE)
|
||||||
{
|
{
|
||||||
PKT_signature *sig = node->pkt->pkt.signature;
|
PKT_signature *sig = node->pkt->pkt.signature;
|
||||||
@ -1319,7 +1334,7 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
|||||||
else if (!opt.fast_list_mode)
|
else if (!opt.fast_list_mode)
|
||||||
{
|
{
|
||||||
size_t n;
|
size_t n;
|
||||||
char *p = get_user_id (sig->keyid, &n);
|
p = get_user_id (sig->keyid, &n);
|
||||||
es_write_sanitized (es_stdout, p, n, ":", NULL);
|
es_write_sanitized (es_stdout, p, n, ":", NULL);
|
||||||
xfree (p);
|
xfree (p);
|
||||||
}
|
}
|
||||||
|
@ -237,10 +237,10 @@ int keygen_upd_std_prefs( PKT_signature *sig, void *opaque );
|
|||||||
int keygen_add_keyserver_url(PKT_signature *sig, void *opaque);
|
int keygen_add_keyserver_url(PKT_signature *sig, void *opaque);
|
||||||
int keygen_add_notations(PKT_signature *sig,void *opaque);
|
int keygen_add_notations(PKT_signature *sig,void *opaque);
|
||||||
int keygen_add_revkey(PKT_signature *sig, void *opaque);
|
int keygen_add_revkey(PKT_signature *sig, void *opaque);
|
||||||
int make_backsig(PKT_signature *sig,PKT_public_key *pk,
|
gpg_error_t make_backsig (PKT_signature *sig, PKT_public_key *pk,
|
||||||
PKT_public_key *sub_pk,PKT_secret_key *sub_sk,
|
PKT_public_key *sub_pk, PKT_public_key *sub_psk,
|
||||||
u32 timestamp);
|
u32 timestamp);
|
||||||
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
gpg_error_t generate_subkeypair (kbnode_t pub_keyblock);
|
||||||
#ifdef ENABLE_CARD_SUPPORT
|
#ifdef ENABLE_CARD_SUPPORT
|
||||||
int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
|
int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
|
||||||
int keyno, const char *serialno);
|
int keyno, const char *serialno);
|
||||||
@ -258,7 +258,7 @@ void try_make_homedir( const char *fname );
|
|||||||
/*-- seskey.c --*/
|
/*-- seskey.c --*/
|
||||||
void make_session_key( DEK *dek );
|
void make_session_key( DEK *dek );
|
||||||
gcry_mpi_t encode_session_key( DEK *dek, unsigned nbits );
|
gcry_mpi_t encode_session_key( DEK *dek, unsigned nbits );
|
||||||
gcry_mpi_t encode_md_value( PKT_public_key *pk, PKT_secret_key *sk,
|
gcry_mpi_t encode_md_value (PKT_public_key *pk,
|
||||||
gcry_md_hd_t md, int hash_algo );
|
gcry_md_hd_t md, int hash_algo );
|
||||||
|
|
||||||
/*-- import.c --*/
|
/*-- import.c --*/
|
||||||
|
@ -206,7 +206,7 @@ struct revoke_info
|
|||||||
|
|
||||||
/****************
|
/****************
|
||||||
* Note about the pkey/skey elements: We assume that the secret keys
|
* Note about the pkey/skey elements: We assume that the secret keys
|
||||||
* has the same elemts as the public key at the begin of the array, so
|
* has the same elements as the public key at the begin of the array, so
|
||||||
* that npkey < nskey and it is possible to compare the secret and
|
* that npkey < nskey and it is possible to compare the secret and
|
||||||
* public keys by comparing the first npkey elements of pkey againts skey.
|
* public keys by comparing the first npkey elements of pkey againts skey.
|
||||||
*/
|
*/
|
||||||
@ -477,9 +477,7 @@ int signature_check2( PKT_signature *sig, gcry_md_hd_t digest, u32 *r_expiredate
|
|||||||
int *r_expired, int *r_revoked, PKT_public_key *ret_pk );
|
int *r_expired, int *r_revoked, PKT_public_key *ret_pk );
|
||||||
|
|
||||||
/*-- seckey-cert.c --*/
|
/*-- seckey-cert.c --*/
|
||||||
int is_secret_key_protected( PKT_secret_key *sk );
|
int is_secret_key_protected (PKT_public_key *pk);
|
||||||
int check_secret_key( PKT_secret_key *sk, int retries );
|
|
||||||
int protect_secret_key( PKT_secret_key *sk, DEK *dek );
|
|
||||||
|
|
||||||
/*-- pubkey-enc.c --*/
|
/*-- pubkey-enc.c --*/
|
||||||
int get_session_key( PKT_pubkey_enc *k, DEK *dek );
|
int get_session_key( PKT_pubkey_enc *k, DEK *dek );
|
||||||
|
59
g10/pkglue.c
59
g10/pkglue.c
@ -44,63 +44,6 @@ mpi_from_sexp (gcry_sexp_t sexp, const char * item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Emulate our old PK interface here - sometime in the future we might
|
|
||||||
* change the internal design to directly fit to libgcrypt.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey)
|
|
||||||
{
|
|
||||||
gcry_sexp_t s_sig, s_hash, s_skey;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/* make a sexp from skey */
|
|
||||||
if (algo == GCRY_PK_DSA)
|
|
||||||
{
|
|
||||||
rc = gcry_sexp_build (&s_skey, NULL,
|
|
||||||
"(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
|
|
||||||
skey[0], skey[1], skey[2], skey[3], skey[4]);
|
|
||||||
}
|
|
||||||
else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_S)
|
|
||||||
{
|
|
||||||
rc = gcry_sexp_build (&s_skey, NULL,
|
|
||||||
"(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
|
|
||||||
skey[0], skey[1], skey[2], skey[3], skey[4],
|
|
||||||
skey[5]);
|
|
||||||
}
|
|
||||||
else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E)
|
|
||||||
{
|
|
||||||
rc = gcry_sexp_build (&s_skey, NULL,
|
|
||||||
"(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
|
|
||||||
skey[0], skey[1], skey[2], skey[3]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return GPG_ERR_PUBKEY_ALGO;
|
|
||||||
|
|
||||||
if (rc)
|
|
||||||
BUG ();
|
|
||||||
|
|
||||||
/* put hash into a S-Exp s_hash */
|
|
||||||
if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
|
|
||||||
BUG ();
|
|
||||||
|
|
||||||
rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
|
|
||||||
gcry_sexp_release (s_hash);
|
|
||||||
gcry_sexp_release (s_skey);
|
|
||||||
|
|
||||||
if (rc)
|
|
||||||
;
|
|
||||||
else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_S)
|
|
||||||
data[0] = mpi_from_sexp (s_sig, "s");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data[0] = mpi_from_sexp (s_sig, "r");
|
|
||||||
data[1] = mpi_from_sexp (s_sig, "s");
|
|
||||||
}
|
|
||||||
|
|
||||||
gcry_sexp_release (s_sig);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
* Emulate our old PK interface here - sometime in the future we might
|
* Emulate our old PK interface here - sometime in the future we might
|
||||||
@ -304,7 +247,7 @@ pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data,
|
|||||||
|
|
||||||
/* Check whether SKEY is a suitable secret key. */
|
/* Check whether SKEY is a suitable secret key. */
|
||||||
int
|
int
|
||||||
pk_check_secret_key (int algo, gcry_mpi_t *skey)
|
REMOVE_ME_pk_check_secret_key (int algo, gcry_mpi_t *skey)
|
||||||
{
|
{
|
||||||
gcry_sexp_t s_skey;
|
gcry_sexp_t s_skey;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -20,8 +20,6 @@
|
|||||||
#ifndef GNUPG_G10_PKGLUE_H
|
#ifndef GNUPG_G10_PKGLUE_H
|
||||||
#define GNUPG_G10_PKGLUE_H
|
#define GNUPG_G10_PKGLUE_H
|
||||||
|
|
||||||
int pk_sign (int algo, gcry_mpi_t *data, gcry_mpi_t hash,
|
|
||||||
gcry_mpi_t *skey);
|
|
||||||
int pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data,
|
int pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data,
|
||||||
gcry_mpi_t *pkey);
|
gcry_mpi_t *pkey);
|
||||||
int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
|
int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,
|
||||||
|
@ -114,10 +114,10 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
|
|||||||
xfree(p);
|
xfree(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /* ask
|
/* rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /\* ask */
|
||||||
only
|
/* only */
|
||||||
once */
|
/* once *\/ */
|
||||||
if( !rc )
|
/* if( !rc ) */
|
||||||
{
|
{
|
||||||
rc = get_it( k, dek, sk, keyid );
|
rc = get_it( k, dek, sk, keyid );
|
||||||
/* Successfully checked the secret key (either it was
|
/* Successfully checked the secret key (either it was
|
||||||
|
89
g10/revoke.c
89
g10/revoke.c
@ -441,13 +441,12 @@ gen_revoke( const char *uname )
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
armor_filter_context_t *afx;
|
armor_filter_context_t *afx;
|
||||||
PACKET pkt;
|
PACKET pkt;
|
||||||
PKT_secret_key *sk; /* used as pointer into a kbnode */
|
PKT_public_key *psk;
|
||||||
PKT_public_key *pk = NULL;
|
|
||||||
PKT_signature *sig = NULL;
|
PKT_signature *sig = NULL;
|
||||||
u32 sk_keyid[2];
|
u32 keyid[2];
|
||||||
IOBUF out = NULL;
|
iobuf_t out = NULL;
|
||||||
KBNODE keyblock = NULL, pub_keyblock = NULL;
|
kbnode_t keyblock = NULL;
|
||||||
KBNODE node;
|
kbnode_t node;
|
||||||
KEYDB_HANDLE kdbhd;
|
KEYDB_HANDLE kdbhd;
|
||||||
struct revocation_reason_info *reason = NULL;
|
struct revocation_reason_info *reason = NULL;
|
||||||
KEYDB_SEARCH_DESC desc;
|
KEYDB_SEARCH_DESC desc;
|
||||||
@ -461,9 +460,7 @@ gen_revoke( const char *uname )
|
|||||||
afx = new_armor_context ();
|
afx = new_armor_context ();
|
||||||
init_packet( &pkt );
|
init_packet( &pkt );
|
||||||
|
|
||||||
/* search the userid:
|
/* Search the userid; we don't want the whole getkey stuff here. */
|
||||||
* We don't want the whole getkey stuff here but the entire keyblock
|
|
||||||
*/
|
|
||||||
kdbhd = keydb_new (1);
|
kdbhd = keydb_new (1);
|
||||||
rc = classify_user_id (uname, &desc);
|
rc = classify_user_id (uname, &desc);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
@ -481,37 +478,18 @@ gen_revoke( const char *uname )
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the keyid from the keyblock */
|
/* Get the keyid from the keyblock. */
|
||||||
node = find_kbnode( keyblock, PKT_SECRET_KEY );
|
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
||||||
if (!node)
|
if (!node)
|
||||||
BUG ();
|
BUG ();
|
||||||
|
|
||||||
/* fixme: should make a function out of this stuff,
|
/* fixme: should make a function out of this stuff,
|
||||||
* it's used all over the source */
|
* it's used all over the source */
|
||||||
sk = node->pkt->pkt.secret_key;
|
psk = node->pkt->pkt.public_key;
|
||||||
keyid_from_sk( sk, sk_keyid );
|
keyid_from_pk (psk, keyid );
|
||||||
print_seckey_info (sk);
|
print_seckey_info (psk);
|
||||||
|
|
||||||
/* FIXME: We should get the public key direct from the secret one */
|
#warning add code to check that the secret key is available
|
||||||
|
|
||||||
pub_keyblock=get_pubkeyblock(sk_keyid);
|
|
||||||
if(!pub_keyblock)
|
|
||||||
{
|
|
||||||
log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) );
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
node=find_kbnode(pub_keyblock,PKT_PUBLIC_KEY);
|
|
||||||
if(!node)
|
|
||||||
BUG();
|
|
||||||
|
|
||||||
pk=node->pkt->pkt.public_key;
|
|
||||||
|
|
||||||
if( cmp_public_secret_key( pk, sk ) ) {
|
|
||||||
log_error(_("public key does not match secret key!\n") );
|
|
||||||
rc = G10ERR_GENERAL;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
tty_printf("\n");
|
tty_printf("\n");
|
||||||
if (!cpr_get_answer_is_yes ("gen_revoke.okay",
|
if (!cpr_get_answer_is_yes ("gen_revoke.okay",
|
||||||
@ -521,35 +499,18 @@ gen_revoke( const char *uname )
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sk->version>=4 || opt.force_v4_certs) {
|
if (psk->version >= 4 || opt.force_v4_certs)
|
||||||
/* get the reason for the revocation */
|
{
|
||||||
|
/* Get the reason for the revocation. */
|
||||||
reason = ask_revocation_reason (1, 0, 1);
|
reason = ask_revocation_reason (1, 0, 1);
|
||||||
if( !reason ) { /* user decided to cancel */
|
if (!reason)
|
||||||
|
{
|
||||||
|
/* user decided to cancel */
|
||||||
rc = 0;
|
rc = 0;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( is_secret_key_protected( sk ) ) {
|
|
||||||
case -1:
|
|
||||||
log_error(_("unknown protection algorithm\n"));
|
|
||||||
rc = G10ERR_PUBKEY_ALGO;
|
|
||||||
break;
|
|
||||||
case -3:
|
|
||||||
tty_printf (_("Secret parts of primary key are not available.\n"));
|
|
||||||
rc = G10ERR_NO_SECKEY;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
tty_printf(_("NOTE: This key is not protected!\n"));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rc = check_secret_key( sk, 0 );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if( rc )
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
|
|
||||||
if (!opt.armor)
|
if (!opt.armor)
|
||||||
tty_printf (_("ASCII armored output forced.\n"));
|
tty_printf (_("ASCII armored output forced.\n"));
|
||||||
|
|
||||||
@ -561,10 +522,11 @@ gen_revoke( const char *uname )
|
|||||||
push_armor_filter (afx, out);
|
push_armor_filter (afx, out);
|
||||||
|
|
||||||
/* create it */
|
/* create it */
|
||||||
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
|
rc = make_keysig_packet (&sig, psk, NULL, NULL, psk, 0x20, 0,
|
||||||
opt.force_v4_certs?4:0, 0, 0,
|
opt.force_v4_certs?4:0, 0, 0,
|
||||||
revocation_reason_build_cb, reason );
|
revocation_reason_build_cb, reason );
|
||||||
if( rc ) {
|
if (rc)
|
||||||
|
{
|
||||||
log_error (_("make_keysig_packet failed: %s\n"), g10_errstr (rc));
|
log_error (_("make_keysig_packet failed: %s\n"), g10_errstr (rc));
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -573,7 +535,7 @@ gen_revoke( const char *uname )
|
|||||||
{
|
{
|
||||||
/* Use a minimal pk for PGPx mode, since PGP can't import bare
|
/* Use a minimal pk for PGPx mode, since PGP can't import bare
|
||||||
revocation certificates. */
|
revocation certificates. */
|
||||||
rc=export_minimal_pk(out,pub_keyblock,sig,NULL);
|
rc = export_minimal_pk (out, keyblock, sig, NULL);
|
||||||
if(rc)
|
if(rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -584,14 +546,16 @@ gen_revoke( const char *uname )
|
|||||||
pkt.pkt.signature = sig;
|
pkt.pkt.signature = sig;
|
||||||
|
|
||||||
rc = build_packet (out, &pkt);
|
rc = build_packet (out, &pkt);
|
||||||
if( rc ) {
|
if (rc)
|
||||||
|
{
|
||||||
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
|
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* and issue a usage notice */
|
/* and issue a usage notice */
|
||||||
tty_printf(_("Revocation certificate created.\n\n"
|
tty_printf (_(
|
||||||
|
"Revocation certificate created.\n\n"
|
||||||
"Please move it to a medium which you can hide away; if Mallory gets\n"
|
"Please move it to a medium which you can hide away; if Mallory gets\n"
|
||||||
"access to this certificate he can use it to make your key unusable.\n"
|
"access to this certificate he can use it to make your key unusable.\n"
|
||||||
"It is smart to print this certificate and store it away, just in case\n"
|
"It is smart to print this certificate and store it away, just in case\n"
|
||||||
@ -602,7 +566,6 @@ gen_revoke( const char *uname )
|
|||||||
if (sig)
|
if (sig)
|
||||||
free_seckey_enc (sig);
|
free_seckey_enc (sig);
|
||||||
release_kbnode (keyblock);
|
release_kbnode (keyblock);
|
||||||
release_kbnode( pub_keyblock );
|
|
||||||
keydb_release (kdbhd);
|
keydb_release (kdbhd);
|
||||||
if (rc)
|
if (rc)
|
||||||
iobuf_cancel(out);
|
iobuf_cancel(out);
|
||||||
|
@ -259,58 +259,6 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Check the secret key
|
|
||||||
* Ask up to 3 (or n) times for a correct passphrase
|
|
||||||
* If n is negative, disable the key info prompt and make n=abs(n)
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
check_secret_key( PKT_secret_key *sk, int n )
|
|
||||||
{
|
|
||||||
int rc = gpg_error (GPG_ERR_BAD_PASSPHRASE);
|
|
||||||
int i,mode;
|
|
||||||
|
|
||||||
if (sk && sk->is_protected && sk->protect.s2k.mode == 1002)
|
|
||||||
return 0; /* Let the scdaemon handle this. */
|
|
||||||
|
|
||||||
if(n<0)
|
|
||||||
{
|
|
||||||
n=abs(n);
|
|
||||||
mode=1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mode=0;
|
|
||||||
|
|
||||||
if( n < 1 )
|
|
||||||
n = 3; /* Use the default value */
|
|
||||||
|
|
||||||
for(i=0; i < n && gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE; i++ ) {
|
|
||||||
int canceled = 0;
|
|
||||||
const char *tryagain = NULL;
|
|
||||||
if (i) {
|
|
||||||
tryagain = N_("Invalid passphrase; please try again");
|
|
||||||
log_info (_("%s ...\n"), _(tryagain));
|
|
||||||
}
|
|
||||||
rc = do_check( sk, tryagain, mode, &canceled );
|
|
||||||
if ( gpg_err_code (rc) == GPG_ERR_BAD_PASSPHRASE
|
|
||||||
&& is_status_enabled () ) {
|
|
||||||
u32 kid[2];
|
|
||||||
char buf[50];
|
|
||||||
|
|
||||||
keyid_from_sk( sk, kid );
|
|
||||||
sprintf(buf, "%08lX%08lX", (ulong)kid[0], (ulong)kid[1]);
|
|
||||||
write_status_text( STATUS_BAD_PASSPHRASE, buf );
|
|
||||||
}
|
|
||||||
if( have_static_passphrase() || canceled)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !rc )
|
|
||||||
write_status( STATUS_GOOD_PASSPHRASE );
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
* check whether the secret key is protected.
|
* check whether the secret key is protected.
|
||||||
* Returns: 0 not protected, -1 on error or the protection algorithm
|
* Returns: 0 not protected, -1 on error or the protection algorithm
|
||||||
@ -318,156 +266,10 @@ check_secret_key( PKT_secret_key *sk, int n )
|
|||||||
* -3 indicates a not-online stub.
|
* -3 indicates a not-online stub.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
is_secret_key_protected( PKT_secret_key *sk )
|
is_secret_key_protected (PKT_public_key *pk)
|
||||||
{
|
{
|
||||||
return sk->is_protected?
|
return 0; /* FIXME: use agent_get_keyinfo?*/
|
||||||
sk->protect.s2k.mode == 1002? -2 :
|
/* return sk->is_protected? */
|
||||||
sk->protect.s2k.mode == 1001? -3 : sk->protect.algo : 0;
|
/* sk->protect.s2k.mode == 1002? -2 : */
|
||||||
}
|
/* sk->protect.s2k.mode == 1001? -3 : sk->protect.algo : 0; */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****************
|
|
||||||
* Protect the secret key with the passphrase from DEK
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
protect_secret_key( PKT_secret_key *sk, DEK *dek )
|
|
||||||
{
|
|
||||||
int i,j, rc = 0;
|
|
||||||
byte *buffer;
|
|
||||||
size_t nbytes;
|
|
||||||
u16 csum;
|
|
||||||
|
|
||||||
if( !dek )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if( !sk->is_protected ) { /* okay, apply the protection */
|
|
||||||
gcry_cipher_hd_t cipher_hd=NULL;
|
|
||||||
|
|
||||||
if ( openpgp_cipher_test_algo ( sk->protect.algo ) ) {
|
|
||||||
/* Unsupport protection algorithm. */
|
|
||||||
rc = gpg_error (GPG_ERR_CIPHER_ALGO);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print_cipher_algo_note( sk->protect.algo );
|
|
||||||
|
|
||||||
if ( openpgp_cipher_open (&cipher_hd, sk->protect.algo,
|
|
||||||
GCRY_CIPHER_MODE_CFB,
|
|
||||||
(GCRY_CIPHER_SECURE
|
|
||||||
| (sk->protect.algo >= 100 ?
|
|
||||||
0 : GCRY_CIPHER_ENABLE_SYNC))) )
|
|
||||||
BUG();
|
|
||||||
if ( gcry_cipher_setkey ( cipher_hd, dek->key, dek->keylen ) )
|
|
||||||
log_info(_("WARNING: Weak key detected"
|
|
||||||
" - please change passphrase again.\n"));
|
|
||||||
sk->protect.ivlen = openpgp_cipher_get_algo_blklen (sk->protect.algo);
|
|
||||||
assert( sk->protect.ivlen <= DIM(sk->protect.iv) );
|
|
||||||
if( sk->protect.ivlen != 8 && sk->protect.ivlen != 16 )
|
|
||||||
BUG(); /* yes, we are very careful */
|
|
||||||
gcry_create_nonce (sk->protect.iv, sk->protect.ivlen);
|
|
||||||
gcry_cipher_setiv (cipher_hd, sk->protect.iv, sk->protect.ivlen);
|
|
||||||
if( sk->version >= 4 ) {
|
|
||||||
byte *bufarr[PUBKEY_MAX_NSKEY];
|
|
||||||
size_t narr[PUBKEY_MAX_NSKEY];
|
|
||||||
unsigned int nbits[PUBKEY_MAX_NSKEY];
|
|
||||||
int ndata=0;
|
|
||||||
byte *p, *data;
|
|
||||||
|
|
||||||
for (j=0, i = pubkey_get_npkey(sk->pubkey_algo);
|
|
||||||
i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ )
|
|
||||||
{
|
|
||||||
assert (!gcry_mpi_get_flag (sk->skey[i],
|
|
||||||
GCRYMPI_FLAG_OPAQUE));
|
|
||||||
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, bufarr+j,
|
|
||||||
narr+j, sk->skey[i]))
|
|
||||||
BUG();
|
|
||||||
nbits[j] = gcry_mpi_get_nbits (sk->skey[i]);
|
|
||||||
ndata += narr[j] + 2;
|
|
||||||
}
|
|
||||||
for ( ; j < PUBKEY_MAX_NSKEY; j++ )
|
|
||||||
bufarr[j] = NULL;
|
|
||||||
|
|
||||||
ndata += opt.simple_sk_checksum? 2 : 20; /* for checksum */
|
|
||||||
|
|
||||||
data = xmalloc_secure( ndata );
|
|
||||||
p = data;
|
|
||||||
for(j=0; j < PUBKEY_MAX_NSKEY && bufarr[j]; j++ ) {
|
|
||||||
p[0] = nbits[j] >> 8 ;
|
|
||||||
p[1] = nbits[j];
|
|
||||||
p += 2;
|
|
||||||
memcpy(p, bufarr[j], narr[j] );
|
|
||||||
p += narr[j];
|
|
||||||
xfree(bufarr[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt.simple_sk_checksum) {
|
|
||||||
log_info (_("generating the deprecated 16-bit checksum"
|
|
||||||
" for secret key protection\n"));
|
|
||||||
csum = checksum( data, ndata-2);
|
|
||||||
sk->csum = csum;
|
|
||||||
*p++ = csum >> 8;
|
|
||||||
*p++ = csum;
|
|
||||||
sk->protect.sha1chk = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gcry_md_hd_t h;
|
|
||||||
|
|
||||||
if (gcry_md_open (&h, GCRY_MD_SHA1, 1))
|
|
||||||
BUG(); /* Algo not available. */
|
|
||||||
gcry_md_write (h, data, ndata - 20);
|
|
||||||
gcry_md_final (h);
|
|
||||||
memcpy (p, gcry_md_read (h, DIGEST_ALGO_SHA1), 20);
|
|
||||||
p += 20;
|
|
||||||
gcry_md_close (h);
|
|
||||||
sk->csum = csum = 0;
|
|
||||||
sk->protect.sha1chk = 1;
|
|
||||||
}
|
|
||||||
assert( p == data+ndata );
|
|
||||||
|
|
||||||
gcry_cipher_encrypt (cipher_hd, data, ndata, NULL, 0);
|
|
||||||
for (i = pubkey_get_npkey(sk->pubkey_algo);
|
|
||||||
i < pubkey_get_nskey(sk->pubkey_algo); 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, data, ndata*8 );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
csum = 0;
|
|
||||||
for(i=pubkey_get_npkey(sk->pubkey_algo);
|
|
||||||
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
|
|
||||||
byte *data;
|
|
||||||
unsigned int nbits;
|
|
||||||
|
|
||||||
csum += checksum_mpi (sk->skey[i]);
|
|
||||||
|
|
||||||
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &buffer,
|
|
||||||
&nbytes, sk->skey[i] ))
|
|
||||||
BUG();
|
|
||||||
gcry_cipher_sync (cipher_hd);
|
|
||||||
assert (!gcry_mpi_get_flag (sk->skey[i],
|
|
||||||
GCRYMPI_FLAG_OPAQUE));
|
|
||||||
|
|
||||||
data = xmalloc (nbytes+2); /* fixme: need xtrymalloc. */
|
|
||||||
nbits = gcry_mpi_get_nbits (sk->skey[i]);
|
|
||||||
assert (nbytes == (nbits + 7)/8);
|
|
||||||
data[0] = nbits >> 8;
|
|
||||||
data[1] = nbits;
|
|
||||||
gcry_cipher_encrypt (cipher_hd, data+2, nbytes,
|
|
||||||
buffer, nbytes);
|
|
||||||
xfree( buffer );
|
|
||||||
|
|
||||||
gcry_mpi_release (sk->skey[i]);
|
|
||||||
sk->skey[i] = gcry_mpi_set_opaque (NULL,
|
|
||||||
data, (nbytes+2)*8 );
|
|
||||||
}
|
|
||||||
sk->csum = csum;
|
|
||||||
}
|
|
||||||
sk->is_protected = 1;
|
|
||||||
gcry_cipher_close (cipher_hd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
26
g10/seskey.c
26
g10/seskey.c
@ -206,19 +206,18 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits,
|
|||||||
* bits.
|
* bits.
|
||||||
*/
|
*/
|
||||||
gcry_mpi_t
|
gcry_mpi_t
|
||||||
encode_md_value (PKT_public_key *pk, PKT_secret_key *sk,
|
encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo)
|
||||||
gcry_md_hd_t md, int hash_algo)
|
|
||||||
{
|
{
|
||||||
gcry_mpi_t frame;
|
gcry_mpi_t frame;
|
||||||
|
|
||||||
assert (hash_algo);
|
assert (hash_algo);
|
||||||
assert(pk || sk);
|
assert (pk);
|
||||||
|
|
||||||
if((pk?pk->pubkey_algo:sk->pubkey_algo) == GCRY_PK_DSA)
|
if (pk->pubkey_algo == GCRY_PK_DSA)
|
||||||
{
|
{
|
||||||
/* It's a DSA signature, so find out the size of q. */
|
/* It's a DSA signature, so find out the size of q. */
|
||||||
|
|
||||||
size_t qbytes = gcry_mpi_get_nbits (pk?pk->pkey[1]:sk->skey[1]);
|
size_t qbytes = gcry_mpi_get_nbits (pk->pkey[1]);
|
||||||
|
|
||||||
/* Make sure it is a multiple of 8 bits. */
|
/* Make sure it is a multiple of 8 bits. */
|
||||||
|
|
||||||
@ -237,9 +236,8 @@ encode_md_value (PKT_public_key *pk, PKT_secret_key *sk,
|
|||||||
DSA. ;) */
|
DSA. ;) */
|
||||||
if (qbytes < 160)
|
if (qbytes < 160)
|
||||||
{
|
{
|
||||||
log_error (_("DSA key %s uses an unsafe (%u bit) hash\n"),
|
log_error (_("DSA key %s uses an unsafe (%zu bit) hash\n"),
|
||||||
pk?keystr_from_pk(pk):keystr_from_sk(sk),
|
keystr_from_pk (pk), qbytes);
|
||||||
(unsigned int)qbytes);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,9 +247,8 @@ encode_md_value (PKT_public_key *pk, PKT_secret_key *sk,
|
|||||||
automatically left-truncate. */
|
automatically left-truncate. */
|
||||||
if (gcry_md_get_algo_dlen (hash_algo) < qbytes)
|
if (gcry_md_get_algo_dlen (hash_algo) < qbytes)
|
||||||
{
|
{
|
||||||
log_error (_("DSA key %s requires a %u bit or larger hash\n"),
|
log_error (_("DSA key %s requires a %zu bit or larger hash\n"),
|
||||||
pk?keystr_from_pk(pk):keystr_from_sk(sk),
|
keystr_from_pk(pk), qbytes*8);
|
||||||
(unsigned int)(qbytes*8));
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,12 +266,13 @@ encode_md_value (PKT_public_key *pk, PKT_secret_key *sk,
|
|||||||
if (rc)
|
if (rc)
|
||||||
log_fatal ("can't get OID of digest algorithm %d: %s\n",
|
log_fatal ("can't get OID of digest algorithm %d: %s\n",
|
||||||
hash_algo, gpg_strerror (rc));
|
hash_algo, gpg_strerror (rc));
|
||||||
asn = xmalloc (asnlen);
|
asn = xtrymalloc (asnlen);
|
||||||
|
if (!asn)
|
||||||
|
return NULL;
|
||||||
if ( gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, asn, &asnlen) )
|
if ( gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, asn, &asnlen) )
|
||||||
BUG();
|
BUG();
|
||||||
frame = do_encode_md (md, hash_algo, gcry_md_get_algo_dlen (hash_algo),
|
frame = do_encode_md (md, hash_algo, gcry_md_get_algo_dlen (hash_algo),
|
||||||
gcry_mpi_get_nbits (pk?pk->pkey[0]:sk->skey[0]),
|
gcry_mpi_get_nbits (pk->pkey[0]), asn, asnlen);
|
||||||
asn, asnlen);
|
|
||||||
xfree (asn);
|
xfree (asn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ do_check( PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest,
|
|||||||
}
|
}
|
||||||
gcry_md_final( digest );
|
gcry_md_final( digest );
|
||||||
|
|
||||||
result = encode_md_value( pk, NULL, digest, sig->digest_algo );
|
result = encode_md_value (pk, digest, sig->digest_algo );
|
||||||
if (!result)
|
if (!result)
|
||||||
return G10ERR_GENERAL;
|
return G10ERR_GENERAL;
|
||||||
ctx.sig = sig;
|
ctx.sig = sig;
|
||||||
|
114
g10/sign.c
114
g10/sign.c
@ -228,37 +228,55 @@ hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gcry_mpi_t
|
||||||
|
mpi_from_sexp (gcry_sexp_t sexp, const char * item)
|
||||||
|
{
|
||||||
|
gcry_sexp_t list;
|
||||||
|
gcry_mpi_t data;
|
||||||
|
|
||||||
|
list = gcry_sexp_find_token (sexp, item, 0);
|
||||||
|
assert (list);
|
||||||
|
data = gcry_sexp_nth_mpi (list, 1, 0);
|
||||||
|
assert (data);
|
||||||
|
gcry_sexp_release (list);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_sign (PKT_public_key *pksk, PKT_signature *sig,
|
do_sign (PKT_public_key *pksk, PKT_signature *sig,
|
||||||
gcry_md_hd_t md, int digest_algo)
|
gcry_md_hd_t md, int mdalgo)
|
||||||
{
|
{
|
||||||
|
gpg_error_t err;
|
||||||
gcry_mpi_t frame;
|
gcry_mpi_t frame;
|
||||||
byte *dp;
|
byte *dp;
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (pksk->timestamp > sig->timestamp ) {
|
if (pksk->timestamp > sig->timestamp )
|
||||||
|
{
|
||||||
ulong d = pksk->timestamp - sig->timestamp;
|
ulong d = pksk->timestamp - sig->timestamp;
|
||||||
log_info (d==1 ? _("key has been created %lu second "
|
log_info (d==1 ? _("key has been created %lu second "
|
||||||
"in future (time warp or clock problem)\n")
|
"in future (time warp or clock problem)\n")
|
||||||
: _("key has been created %lu seconds "
|
: _("key has been created %lu seconds "
|
||||||
"in future (time warp or clock problem)\n"), d );
|
"in future (time warp or clock problem)\n"), d );
|
||||||
if (!opt.ignore_time_conflict)
|
if (!opt.ignore_time_conflict)
|
||||||
return G10ERR_TIME_CONFLICT;
|
return gpg_error (GPG_ERR_TIME_CONFLICT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
print_pubkey_algo_note (pksk->pubkey_algo);
|
print_pubkey_algo_note (pksk->pubkey_algo);
|
||||||
|
|
||||||
if( !digest_algo )
|
if (!mdalgo)
|
||||||
digest_algo = gcry_md_get_algo (md);
|
mdalgo = gcry_md_get_algo (md);
|
||||||
|
|
||||||
print_digest_algo_note( digest_algo );
|
print_digest_algo_note (mdalgo);
|
||||||
dp = gcry_md_read ( md, digest_algo );
|
dp = gcry_md_read (md, mdalgo);
|
||||||
sig->digest_algo = digest_algo;
|
sig->digest_algo = mdalgo;
|
||||||
sig->digest_start[0] = dp[0];
|
sig->digest_start[0] = dp[0];
|
||||||
sig->digest_start[1] = dp[1];
|
sig->digest_start[1] = dp[1];
|
||||||
|
sig->data[0] = NULL;
|
||||||
|
sig->data[1] = NULL;
|
||||||
|
|
||||||
/* FIXME: Use agent. */
|
#warning fixme: Use the agent for the card
|
||||||
/* if (pksk->is_protected && pksk->protect.s2k.mode == 1002) */
|
/* if (pksk->is_protected && pksk->protect.s2k.mode == 1002) */
|
||||||
/* { */
|
/* { */
|
||||||
/* #ifdef ENABLE_CARD_SUPPORT */
|
/* #ifdef ENABLE_CARD_SUPPORT */
|
||||||
@ -285,39 +303,71 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
|
|||||||
/* #endif /\* ENABLE_CARD_SUPPORT *\/ */
|
/* #endif /\* ENABLE_CARD_SUPPORT *\/ */
|
||||||
/* } */
|
/* } */
|
||||||
/* else */
|
/* else */
|
||||||
|
if (1)
|
||||||
{
|
{
|
||||||
frame = encode_md_value (NULL, pksk, md, digest_algo );
|
char *hexgrip;
|
||||||
if (!frame)
|
|
||||||
return G10ERR_GENERAL;
|
err = hexkeygrip_from_pk (pksk, &hexgrip);
|
||||||
rc = pk_sign (pksk->pubkey_algo, sig->data, frame, pksk->pkey );
|
if (!err)
|
||||||
gcry_mpi_release (frame);
|
{
|
||||||
|
char *desc;
|
||||||
|
gcry_sexp_t s_sigval;
|
||||||
|
|
||||||
|
/* FIXME: desc = gpgsm_format_keydesc (cert); */
|
||||||
|
desc = xtrystrdup ("FIXME: Format a decription");
|
||||||
|
|
||||||
|
err = agent_pksign (NULL/*ctrl*/, hexgrip, desc,
|
||||||
|
dp, gcry_md_get_algo_dlen (mdalgo), mdalgo,
|
||||||
|
&s_sigval);
|
||||||
|
|
||||||
|
xfree (desc);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
;
|
||||||
|
else if (pksk->pubkey_algo == GCRY_PK_RSA
|
||||||
|
|| pksk->pubkey_algo == GCRY_PK_RSA_S)
|
||||||
|
sig->data[0] = mpi_from_sexp (s_sigval, "s");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sig->data[0] = mpi_from_sexp (s_sigval, "r");
|
||||||
|
sig->data[1] = mpi_from_sexp (s_sigval, "s");
|
||||||
|
}
|
||||||
|
|
||||||
|
gcry_sexp_release (s_sigval);
|
||||||
|
}
|
||||||
|
xfree (hexgrip);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rc && !opt.no_sig_create_check) {
|
|
||||||
/* Check that the signature verification worked and nothing is
|
/* Check that the signature verification worked and nothing is
|
||||||
* fooling us e.g. by a bug in the signature create
|
* fooling us e.g. by a bug in the signature create code or by
|
||||||
* code or by deliberately introduced faults. */
|
* deliberately introduced faults. */
|
||||||
|
if (!err && !opt.no_sig_create_check)
|
||||||
|
{
|
||||||
PKT_public_key *pk = xmalloc_clear (sizeof *pk);
|
PKT_public_key *pk = xmalloc_clear (sizeof *pk);
|
||||||
|
|
||||||
if (get_pubkey (pk, sig->keyid ))
|
if (get_pubkey (pk, sig->keyid ))
|
||||||
rc = G10ERR_NO_PUBKEY;
|
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||||
else {
|
|
||||||
frame = encode_md_value (pk, NULL, md, sig->digest_algo );
|
|
||||||
if (!frame)
|
|
||||||
rc = G10ERR_GENERAL;
|
|
||||||
else
|
else
|
||||||
rc = pk_verify (pk->pubkey_algo, frame, sig->data, pk->pkey );
|
{
|
||||||
|
frame = encode_md_value (pk, md, sig->digest_algo );
|
||||||
|
if (!frame)
|
||||||
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
|
else
|
||||||
|
err = pk_verify (pk->pubkey_algo, frame, sig->data, pk->pkey);
|
||||||
gcry_mpi_release (frame);
|
gcry_mpi_release (frame);
|
||||||
}
|
}
|
||||||
if (rc)
|
if (err)
|
||||||
log_error (_("checking created signature failed: %s\n"),
|
log_error (_("checking created signature failed: %s\n"),
|
||||||
g10_errstr (rc));
|
g10_errstr (err));
|
||||||
free_public_key (pk);
|
free_public_key (pk);
|
||||||
}
|
}
|
||||||
if( rc )
|
|
||||||
log_error(_("signing failed: %s\n"), g10_errstr(rc) );
|
if (err)
|
||||||
else {
|
log_error (_("signing failed: %s\n"), g10_errstr (err));
|
||||||
if( opt.verbose ) {
|
else
|
||||||
|
{
|
||||||
|
if (opt.verbose)
|
||||||
|
{
|
||||||
char *ustr = get_user_id_string_native (sig->keyid);
|
char *ustr = get_user_id_string_native (sig->keyid);
|
||||||
log_info (_("%s/%s signature from: \"%s\"\n"),
|
log_info (_("%s/%s signature from: \"%s\"\n"),
|
||||||
gcry_pk_algo_name (pksk->pubkey_algo),
|
gcry_pk_algo_name (pksk->pubkey_algo),
|
||||||
@ -326,7 +376,7 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
|
|||||||
xfree (ustr);
|
xfree (ustr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -335,7 +385,7 @@ complete_sig( PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md )
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!(rc = check_secret_key (pksk, 0)))
|
/* if (!(rc = check_secret_key (pksk, 0))) */
|
||||||
rc = do_sign (pksk, sig, md, 0);
|
rc = do_sign (pksk, sig, md, 0);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user