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>
|
||||
|
||||
* cpr.c (myread) [W32CE]: Do not use raise.
|
||||
|
333
g10/call-agent.c
333
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 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009,
|
||||
* 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -69,14 +69,15 @@ struct writekey_parm_s
|
||||
size_t keydatalen;
|
||||
};
|
||||
|
||||
struct genkey_parm_s
|
||||
struct genkey_parm_s
|
||||
{
|
||||
ctrl_t ctrl;
|
||||
assuan_context_t ctx;
|
||||
const char *sexp;
|
||||
size_t sexplen;
|
||||
const char *keyparms;
|
||||
};
|
||||
|
||||
|
||||
|
||||
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
|
||||
pipes. Handle the server's initial greeting */
|
||||
static int
|
||||
start_agent (int for_card)
|
||||
start_agent (ctrl_t ctrl, int for_card)
|
||||
{
|
||||
int rc;
|
||||
|
||||
(void)ctrl; /* Not yet used. */
|
||||
|
||||
/* Fixme: We need a context for each thread or serialize the access
|
||||
to the agent. */
|
||||
if (agent_ctx)
|
||||
@ -486,7 +489,7 @@ agent_learn (struct agent_card_info_s *info)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = start_agent (1);
|
||||
rc = start_agent (NULL, 1);
|
||||
if (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);
|
||||
stpcpy (stpcpy (line, "SCD GETATTR "), name);
|
||||
|
||||
rc = start_agent (1);
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -581,7 +584,7 @@ agent_scd_setattr (const char *name,
|
||||
}
|
||||
*p = 0;
|
||||
|
||||
rc = start_agent (1);
|
||||
rc = start_agent (NULL, 1);
|
||||
if (!rc)
|
||||
{
|
||||
rc = assuan_transact (agent_ctx, line, NULL, NULL,
|
||||
@ -623,7 +626,7 @@ agent_scd_writecert (const char *certidstr,
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct writecert_parm_s parms;
|
||||
|
||||
rc = start_agent (1);
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -673,7 +676,7 @@ agent_scd_writekey (int keyno, const char *serialno,
|
||||
|
||||
(void)serialno;
|
||||
|
||||
rc = start_agent (1);
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -762,7 +765,7 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
|
||||
|
||||
(void)serialno;
|
||||
|
||||
rc = start_agent (1);
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -909,7 +912,7 @@ agent_scd_pksign (const char *serialno, int hashalgo,
|
||||
*r_buf = NULL;
|
||||
*r_buflen = 0;
|
||||
|
||||
rc = start_agent (1);
|
||||
rc = start_agent (NULL, 1);
|
||||
if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT
|
||||
|| gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
|
||||
rc = 0; /* We check later. */
|
||||
@ -972,7 +975,7 @@ agent_scd_pkdecrypt (const char *serialno,
|
||||
size_t len;
|
||||
|
||||
*r_buf = NULL;
|
||||
rc = start_agent (1);
|
||||
rc = start_agent (NULL, 1);
|
||||
if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT
|
||||
|| gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
|
||||
rc = 0; /* We check later. */
|
||||
@ -1029,7 +1032,7 @@ agent_scd_readcert (const char *certidstr,
|
||||
size_t len;
|
||||
|
||||
*r_buf = NULL;
|
||||
rc = start_agent (1);
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -1077,7 +1080,7 @@ agent_scd_change_pin (int chvno, const char *serialno)
|
||||
reset = "--reset";
|
||||
chvno %= 100;
|
||||
|
||||
rc = start_agent (1);
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -1099,7 +1102,7 @@ agent_scd_checkpin (const char *serialno)
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
|
||||
rc = start_agent (1);
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -1146,7 +1149,7 @@ agent_get_passphrase (const char *cache_id,
|
||||
|
||||
*r_passphrase = NULL;
|
||||
|
||||
rc = start_agent (0);
|
||||
rc = start_agent (NULL, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -1217,7 +1220,7 @@ agent_clear_passphrase (const char *cache_id)
|
||||
if (!cache_id || !*cache_id)
|
||||
return 0;
|
||||
|
||||
rc = start_agent (0);
|
||||
rc = start_agent (NULL, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -1237,7 +1240,7 @@ gpg_agent_get_confirmation (const char *desc)
|
||||
char *tmp;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
|
||||
rc = start_agent (0);
|
||||
rc = start_agent (NULL, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -1264,7 +1267,7 @@ agent_get_s2k_count (unsigned long *r_count)
|
||||
|
||||
*r_count = 0;
|
||||
|
||||
err = start_agent (0);
|
||||
err = start_agent (NULL, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -1289,3 +1292,291 @@ agent_get_s2k_count (unsigned long *r_count)
|
||||
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. */
|
||||
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*/
|
||||
|
||||
|
@ -1495,8 +1495,8 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
|
||||
the serialnumber and thus it won't harm. */
|
||||
}
|
||||
|
||||
okay = generate_card_subkeypair (pub_keyblock, sec_keyblock,
|
||||
keyno, info.serialno);
|
||||
/* xxx = generate_card_subkeypair (pub_keyblock, sec_keyblock, */
|
||||
/* keyno, info.serialno); */
|
||||
|
||||
leave:
|
||||
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. */
|
||||
copied_sk = sk = copy_secret_key (NULL, sk);
|
||||
rc = check_secret_key (sk, 0);
|
||||
rc = 0/*check_secret_key (sk, 0)*/;
|
||||
if (rc)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
rc = save_unprotected_key_to_card (sk, keyno);
|
||||
if (rc)
|
||||
{
|
||||
log_error (_("error writing key to card: %s\n"), gpg_strerror (rc));
|
||||
goto leave;
|
||||
}
|
||||
#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; */
|
||||
/* } */
|
||||
|
||||
/* Get back to the maybe protected original secret key. */
|
||||
if (copied_sk)
|
||||
|
@ -550,7 +550,7 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
|
||||
; /* Card key stub. */
|
||||
else
|
||||
{
|
||||
rc = check_secret_key( sk, 0 );
|
||||
/* rc = check_secret_key( sk, 0 ); */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -526,7 +526,7 @@ get_seckey (PKT_secret_key * sk, u32 * keyid)
|
||||
{
|
||||
/* Check the secret key (this may prompt for a passprase to
|
||||
* unlock the secret key. */
|
||||
rc = check_secret_key (sk, 0);
|
||||
/* rc = check_secret_key (sk, 0); */
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -1111,8 +1111,8 @@ get_seckey_byname2 (GETKEY_CTX * retctx,
|
||||
|
||||
free_strlist (namelist);
|
||||
|
||||
if (!rc && unprotect)
|
||||
rc = check_secret_key (sk, 0);
|
||||
/* if (!rc && unprotect) */
|
||||
/* rc = check_secret_key (sk, 0); */
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ struct server_control_s
|
||||
#define G10ERR_RENAME_FILE GPG_ERR_RENAME_FILE
|
||||
#define G10ERR_RESOURCE_LIMIT GPG_ERR_RESOURCE_LIMIT
|
||||
#define G10ERR_SIG_CLASS GPG_ERR_SIG_CLASS
|
||||
#define G10ERR_TIME_CONFLICT GPG_ERR_TIME_CONFLICT
|
||||
#define G10ERR_TIME_CONFLICT GPG_ERR_TIME_CONFLICT
|
||||
#define G10ERR_TRUSTDB GPG_ERR_TRUSTDB
|
||||
#define G10ERR_UNEXPECTED GPG_ERR_UNEXPECTED
|
||||
#define G10ERR_UNKNOWN_PACKET GPG_ERR_UNKNOWN_PACKET
|
||||
|
@ -399,9 +399,9 @@ display_online_help (const char *keyword)
|
||||
* We don't use secret keys, but getkey.c links to this
|
||||
*/
|
||||
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;
|
||||
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 );
|
||||
char *serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
|
||||
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 new_kbnode( PACKET *pkt );
|
||||
|
@ -1164,9 +1164,9 @@ change_passphrase (KBNODE keyblock, int *r_err)
|
||||
keyid_from_sk (sk, keyid);
|
||||
passphrase_clear_cache (keyid, NULL, 0);
|
||||
|
||||
rc = check_secret_key( sk, 0 );
|
||||
if( !rc )
|
||||
passphrase = get_last_passphrase();
|
||||
/* rc = check_secret_key( sk, 0 ); */
|
||||
/* if( !rc ) */
|
||||
/* passphrase = get_last_passphrase(); */
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1179,9 +1179,9 @@ change_passphrase (KBNODE keyblock, int *r_err)
|
||||
&& (subsk->protect.s2k.mode == 1001
|
||||
|| subsk->protect.s2k.mode == 1002))) {
|
||||
set_next_passphrase( passphrase );
|
||||
rc = check_secret_key( subsk, 0 );
|
||||
if( !rc && !passphrase )
|
||||
passphrase = get_last_passphrase();
|
||||
/* rc = check_secret_key( subsk, 0 ); */
|
||||
/* if( !rc && !passphrase ) */
|
||||
/* passphrase = get_last_passphrase(); */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1227,7 +1227,9 @@ change_passphrase (KBNODE keyblock, int *r_err)
|
||||
if( !no_primary_secrets ) {
|
||||
sk->protect.algo = dek->algo;
|
||||
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 ) {
|
||||
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.algo = dek->algo;
|
||||
subsk->protect.s2k = *s2k;
|
||||
rc = protect_secret_key( subsk, dek );
|
||||
#warning fixme
|
||||
rc = 0;
|
||||
/* rc = protect_secret_key( subsk, dek ); */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1892,12 +1896,13 @@ keyedit_menu( const char *username, strlist_t locusr,
|
||||
break;
|
||||
|
||||
case cmdADDKEY:
|
||||
if( generate_subkeypair( keyblock, sec_keyblock ) ) {
|
||||
if (!generate_subkeypair (keyblock))
|
||||
{
|
||||
redisplay = 1;
|
||||
sec_modified = modified = 1;
|
||||
merge_keys_and_selfsig( sec_keyblock );
|
||||
merge_keys_and_selfsig( keyblock );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_CARD_SUPPORT
|
||||
@ -2018,8 +2023,8 @@ keyedit_menu( const char *username, strlist_t locusr,
|
||||
if (sk->protect.s2k.mode == 1002)
|
||||
tty_printf (_("Secret parts of key"
|
||||
" are stored on-card.\n"));
|
||||
else
|
||||
check_secret_key (sk, 0);
|
||||
/* else */
|
||||
/* check_secret_key (sk, 0); */
|
||||
}
|
||||
}
|
||||
else /* Store it. */
|
||||
|
1262
g10/keygen.c
1262
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
|
||||
* 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.
|
||||
*
|
||||
@ -828,3 +828,90 @@ serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
|
||||
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 ulti_hack = 0;
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
/* Get the keyid from the keyblock. */
|
||||
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
||||
@ -1128,8 +1129,15 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
||||
if (fpr)
|
||||
print_fingerprint (pk, NULL, 0);
|
||||
if (opt.with_key_data)
|
||||
print_key_data (pk);
|
||||
|
||||
{
|
||||
if (!hexkeygrip_from_pk (pk, &p))
|
||||
{
|
||||
es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
|
||||
xfree (p);
|
||||
}
|
||||
print_key_data (pk);
|
||||
}
|
||||
|
||||
for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
|
||||
{
|
||||
if (node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode)
|
||||
@ -1226,7 +1234,14 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
||||
if (fpr > 1)
|
||||
print_fingerprint (pk2, NULL, 0);
|
||||
if (opt.with_key_data)
|
||||
print_key_data (pk2);
|
||||
{
|
||||
if (!hexkeygrip_from_pk (pk2, &p))
|
||||
{
|
||||
es_fprintf (es_stdout, "grp:::::::::%s:\n", p);
|
||||
xfree (p);
|
||||
}
|
||||
print_key_data (pk2);
|
||||
}
|
||||
}
|
||||
else if (opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE)
|
||||
{
|
||||
@ -1319,7 +1334,7 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
|
||||
else if (!opt.fast_list_mode)
|
||||
{
|
||||
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);
|
||||
xfree (p);
|
||||
}
|
||||
|
10
g10/main.h
10
g10/main.h
@ -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_notations(PKT_signature *sig,void *opaque);
|
||||
int keygen_add_revkey(PKT_signature *sig, void *opaque);
|
||||
int make_backsig(PKT_signature *sig,PKT_public_key *pk,
|
||||
PKT_public_key *sub_pk,PKT_secret_key *sub_sk,
|
||||
u32 timestamp);
|
||||
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||||
gpg_error_t make_backsig (PKT_signature *sig, PKT_public_key *pk,
|
||||
PKT_public_key *sub_pk, PKT_public_key *sub_psk,
|
||||
u32 timestamp);
|
||||
gpg_error_t generate_subkeypair (kbnode_t pub_keyblock);
|
||||
#ifdef ENABLE_CARD_SUPPORT
|
||||
int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
|
||||
int keyno, const char *serialno);
|
||||
@ -258,7 +258,7 @@ void try_make_homedir( const char *fname );
|
||||
/*-- seskey.c --*/
|
||||
void make_session_key( DEK *dek );
|
||||
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 );
|
||||
|
||||
/*-- import.c --*/
|
||||
|
@ -206,7 +206,7 @@ struct revoke_info
|
||||
|
||||
/****************
|
||||
* 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
|
||||
* 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 );
|
||||
|
||||
/*-- seckey-cert.c --*/
|
||||
int is_secret_key_protected( PKT_secret_key *sk );
|
||||
int check_secret_key( PKT_secret_key *sk, int retries );
|
||||
int protect_secret_key( PKT_secret_key *sk, DEK *dek );
|
||||
int is_secret_key_protected (PKT_public_key *pk);
|
||||
|
||||
/*-- pubkey-enc.c --*/
|
||||
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
|
||||
@ -304,7 +247,7 @@ pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data,
|
||||
|
||||
/* Check whether SKEY is a suitable secret key. */
|
||||
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;
|
||||
int rc;
|
||||
|
@ -20,8 +20,6 @@
|
||||
#ifndef 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,
|
||||
gcry_mpi_t *pkey);
|
||||
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);
|
||||
}
|
||||
|
||||
rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /* ask
|
||||
only
|
||||
once */
|
||||
if( !rc )
|
||||
/* rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /\* ask */
|
||||
/* only */
|
||||
/* once *\/ */
|
||||
/* if( !rc ) */
|
||||
{
|
||||
rc = get_it( k, dek, sk, keyid );
|
||||
/* Successfully checked the secret key (either it was
|
||||
|
273
g10/revoke.c
273
g10/revoke.c
@ -436,181 +436,144 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
|
||||
* Generate a revocation certificate for UNAME
|
||||
*/
|
||||
int
|
||||
gen_revoke( const char *uname )
|
||||
gen_revoke (const char *uname)
|
||||
{
|
||||
int rc = 0;
|
||||
armor_filter_context_t *afx;
|
||||
PACKET pkt;
|
||||
PKT_secret_key *sk; /* used as pointer into a kbnode */
|
||||
PKT_public_key *pk = NULL;
|
||||
PKT_signature *sig = NULL;
|
||||
u32 sk_keyid[2];
|
||||
IOBUF out = NULL;
|
||||
KBNODE keyblock = NULL, pub_keyblock = NULL;
|
||||
KBNODE node;
|
||||
KEYDB_HANDLE kdbhd;
|
||||
struct revocation_reason_info *reason = NULL;
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
int rc = 0;
|
||||
armor_filter_context_t *afx;
|
||||
PACKET pkt;
|
||||
PKT_public_key *psk;
|
||||
PKT_signature *sig = NULL;
|
||||
u32 keyid[2];
|
||||
iobuf_t out = NULL;
|
||||
kbnode_t keyblock = NULL;
|
||||
kbnode_t node;
|
||||
KEYDB_HANDLE kdbhd;
|
||||
struct revocation_reason_info *reason = NULL;
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
|
||||
if( opt.batch )
|
||||
{
|
||||
log_error(_("can't do this in batch mode\n"));
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
|
||||
afx = new_armor_context ();
|
||||
init_packet( &pkt );
|
||||
|
||||
/* search the userid:
|
||||
* We don't want the whole getkey stuff here but the entire keyblock
|
||||
*/
|
||||
kdbhd = keydb_new (1);
|
||||
rc = classify_user_id (uname, &desc);
|
||||
if (!rc)
|
||||
rc = keydb_search (kdbhd, &desc, 1);
|
||||
if (rc)
|
||||
{
|
||||
log_error (_("secret key \"%s\" not found: %s\n"),
|
||||
uname, g10_errstr (rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
rc = keydb_get_keyblock (kdbhd, &keyblock );
|
||||
if( rc ) {
|
||||
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
if( opt.batch )
|
||||
{
|
||||
log_error(_("can't do this in batch mode\n"));
|
||||
return G10ERR_GENERAL;
|
||||
}
|
||||
|
||||
/* get the keyid from the keyblock */
|
||||
node = find_kbnode( keyblock, PKT_SECRET_KEY );
|
||||
if( !node )
|
||||
BUG ();
|
||||
afx = new_armor_context ();
|
||||
init_packet( &pkt );
|
||||
|
||||
/* fixme: should make a function out of this stuff,
|
||||
* it's used all over the source */
|
||||
sk = node->pkt->pkt.secret_key;
|
||||
keyid_from_sk( sk, sk_keyid );
|
||||
print_seckey_info (sk);
|
||||
|
||||
/* FIXME: We should get the public key direct from the secret one */
|
||||
|
||||
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;
|
||||
/* Search the userid; we don't want the whole getkey stuff here. */
|
||||
kdbhd = keydb_new (1);
|
||||
rc = classify_user_id (uname, &desc);
|
||||
if (!rc)
|
||||
rc = keydb_search (kdbhd, &desc, 1);
|
||||
if (rc)
|
||||
{
|
||||
log_error (_("secret key \"%s\" not found: %s\n"),
|
||||
uname, g10_errstr (rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
tty_printf("\n");
|
||||
if( !cpr_get_answer_is_yes("gen_revoke.okay",
|
||||
_("Create a revocation certificate for this key? (y/N) ")) )
|
||||
{
|
||||
rc = 0;
|
||||
goto leave;
|
||||
}
|
||||
rc = keydb_get_keyblock (kdbhd, &keyblock );
|
||||
if( rc ) {
|
||||
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if(sk->version>=4 || opt.force_v4_certs) {
|
||||
/* get the reason for the revocation */
|
||||
reason = ask_revocation_reason( 1, 0, 1 );
|
||||
if( !reason ) { /* user decided to cancel */
|
||||
rc = 0;
|
||||
goto leave;
|
||||
}
|
||||
/* Get the keyid from the keyblock. */
|
||||
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
|
||||
if (!node)
|
||||
BUG ();
|
||||
|
||||
/* fixme: should make a function out of this stuff,
|
||||
* it's used all over the source */
|
||||
psk = node->pkt->pkt.public_key;
|
||||
keyid_from_pk (psk, keyid );
|
||||
print_seckey_info (psk);
|
||||
|
||||
#warning add code to check that the secret key is available
|
||||
|
||||
tty_printf("\n");
|
||||
if (!cpr_get_answer_is_yes ("gen_revoke.okay",
|
||||
_("Create a revocation certificate for this key? (y/N) ")))
|
||||
{
|
||||
rc = 0;
|
||||
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 (psk->version >= 4 || opt.force_v4_certs)
|
||||
{
|
||||
/* Get the reason for the revocation. */
|
||||
reason = ask_revocation_reason (1, 0, 1);
|
||||
if (!reason)
|
||||
{
|
||||
/* user decided to cancel */
|
||||
rc = 0;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
if( rc )
|
||||
goto leave;
|
||||
|
||||
if (!opt.armor)
|
||||
tty_printf (_("ASCII armored output forced.\n"));
|
||||
|
||||
if ((rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )))
|
||||
goto leave;
|
||||
|
||||
if( !opt.armor )
|
||||
tty_printf(_("ASCII armored output forced.\n"));
|
||||
afx->what = 1;
|
||||
afx->hdrlines = "Comment: A revocation certificate should follow\n";
|
||||
push_armor_filter (afx, out);
|
||||
|
||||
if( (rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )) )
|
||||
goto leave;
|
||||
|
||||
afx->what = 1;
|
||||
afx->hdrlines = "Comment: A revocation certificate should follow\n";
|
||||
push_armor_filter (afx, out);
|
||||
|
||||
/* create it */
|
||||
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0,
|
||||
opt.force_v4_certs?4:0, 0, 0,
|
||||
revocation_reason_build_cb, reason );
|
||||
if( rc ) {
|
||||
log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
|
||||
goto leave;
|
||||
/* create it */
|
||||
rc = make_keysig_packet (&sig, psk, NULL, NULL, psk, 0x20, 0,
|
||||
opt.force_v4_certs?4:0, 0, 0,
|
||||
revocation_reason_build_cb, reason );
|
||||
if (rc)
|
||||
{
|
||||
log_error (_("make_keysig_packet failed: %s\n"), g10_errstr (rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if(PGP2 || PGP6 || PGP7 || PGP8)
|
||||
{
|
||||
/* Use a minimal pk for PGPx mode, since PGP can't import bare
|
||||
revocation certificates. */
|
||||
rc=export_minimal_pk(out,pub_keyblock,sig,NULL);
|
||||
if(rc)
|
||||
goto leave;
|
||||
}
|
||||
else
|
||||
{
|
||||
init_packet( &pkt );
|
||||
pkt.pkttype = PKT_SIGNATURE;
|
||||
pkt.pkt.signature = sig;
|
||||
|
||||
rc = build_packet( out, &pkt );
|
||||
if( rc ) {
|
||||
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
/* and issue a usage notice */
|
||||
tty_printf(_("Revocation certificate created.\n\n"
|
||||
|
||||
if (PGP2 || PGP6 || PGP7 || PGP8)
|
||||
{
|
||||
/* Use a minimal pk for PGPx mode, since PGP can't import bare
|
||||
revocation certificates. */
|
||||
rc = export_minimal_pk (out, keyblock, sig, NULL);
|
||||
if(rc)
|
||||
goto leave;
|
||||
}
|
||||
else
|
||||
{
|
||||
init_packet( &pkt );
|
||||
pkt.pkttype = PKT_SIGNATURE;
|
||||
pkt.pkt.signature = sig;
|
||||
|
||||
rc = build_packet (out, &pkt);
|
||||
if (rc)
|
||||
{
|
||||
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
/* and issue a usage notice */
|
||||
tty_printf (_(
|
||||
"Revocation certificate created.\n\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"
|
||||
"It is smart to print this certificate and store it away, just in case\n"
|
||||
"your media become unreadable. But have some caution: The print system of\n"
|
||||
"your machine might store the data and make it available to others!\n"));
|
||||
|
||||
leave:
|
||||
if( sig )
|
||||
free_seckey_enc( sig );
|
||||
release_kbnode( keyblock );
|
||||
release_kbnode( pub_keyblock );
|
||||
keydb_release (kdbhd);
|
||||
if( rc )
|
||||
iobuf_cancel(out);
|
||||
else
|
||||
iobuf_close(out);
|
||||
release_revocation_reason_info( reason );
|
||||
release_armor_context (afx);
|
||||
return rc;
|
||||
leave:
|
||||
if (sig)
|
||||
free_seckey_enc (sig);
|
||||
release_kbnode (keyblock);
|
||||
keydb_release (kdbhd);
|
||||
if (rc)
|
||||
iobuf_cancel(out);
|
||||
else
|
||||
iobuf_close(out);
|
||||
release_revocation_reason_info( reason );
|
||||
release_armor_context (afx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
* 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.
|
||||
*/
|
||||
int
|
||||
is_secret_key_protected( PKT_secret_key *sk )
|
||||
is_secret_key_protected (PKT_public_key *pk)
|
||||
{
|
||||
return sk->is_protected?
|
||||
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;
|
||||
return 0; /* FIXME: use agent_get_keyinfo?*/
|
||||
/* return sk->is_protected? */
|
||||
/* sk->protect.s2k.mode == 1002? -2 : */
|
||||
/* sk->protect.s2k.mode == 1001? -3 : sk->protect.algo : 0; */
|
||||
}
|
||||
|
30
g10/seskey.c
30
g10/seskey.c
@ -206,19 +206,18 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits,
|
||||
* bits.
|
||||
*/
|
||||
gcry_mpi_t
|
||||
encode_md_value (PKT_public_key *pk, PKT_secret_key *sk,
|
||||
gcry_md_hd_t md, int hash_algo)
|
||||
encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo)
|
||||
{
|
||||
gcry_mpi_t frame;
|
||||
|
||||
assert(hash_algo);
|
||||
assert(pk || sk);
|
||||
assert (hash_algo);
|
||||
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. */
|
||||
|
||||
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. */
|
||||
|
||||
@ -237,21 +236,19 @@ encode_md_value (PKT_public_key *pk, PKT_secret_key *sk,
|
||||
DSA. ;) */
|
||||
if (qbytes < 160)
|
||||
{
|
||||
log_error (_("DSA key %s uses an unsafe (%u bit) hash\n"),
|
||||
pk?keystr_from_pk(pk):keystr_from_sk(sk),
|
||||
(unsigned int)qbytes);
|
||||
log_error (_("DSA key %s uses an unsafe (%zu bit) hash\n"),
|
||||
keystr_from_pk (pk), qbytes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qbytes/=8;
|
||||
qbytes /= 8;
|
||||
|
||||
/* Check if we're too short. Too long is safe as we'll
|
||||
automatically left-truncate. */
|
||||
if (gcry_md_get_algo_dlen (hash_algo) < qbytes)
|
||||
{
|
||||
log_error (_("DSA key %s requires a %u bit or larger hash\n"),
|
||||
pk?keystr_from_pk(pk):keystr_from_sk(sk),
|
||||
(unsigned int)(qbytes*8));
|
||||
log_error (_("DSA key %s requires a %zu bit or larger hash\n"),
|
||||
keystr_from_pk(pk), qbytes*8);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -269,12 +266,13 @@ encode_md_value (PKT_public_key *pk, PKT_secret_key *sk,
|
||||
if (rc)
|
||||
log_fatal ("can't get OID of digest algorithm %d: %s\n",
|
||||
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) )
|
||||
BUG();
|
||||
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]),
|
||||
asn, asnlen);
|
||||
gcry_mpi_get_nbits (pk->pkey[0]), asn, asnlen);
|
||||
xfree (asn);
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ do_check( PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t 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)
|
||||
return G10ERR_GENERAL;
|
||||
ctx.sig = sig;
|
||||
|
174
g10/sign.c
174
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
|
||||
do_sign (PKT_public_key *pksk, PKT_signature *sig,
|
||||
gcry_md_hd_t md, int digest_algo)
|
||||
gcry_md_hd_t md, int mdalgo)
|
||||
{
|
||||
gcry_mpi_t frame;
|
||||
byte *dp;
|
||||
int rc;
|
||||
gpg_error_t err;
|
||||
gcry_mpi_t frame;
|
||||
byte *dp;
|
||||
|
||||
if (pksk->timestamp > sig->timestamp ) {
|
||||
ulong d = pksk->timestamp - sig->timestamp;
|
||||
log_info( d==1 ? _("key has been created %lu second "
|
||||
"in future (time warp or clock problem)\n")
|
||||
: _("key has been created %lu seconds "
|
||||
"in future (time warp or clock problem)\n"), d );
|
||||
if( !opt.ignore_time_conflict )
|
||||
return G10ERR_TIME_CONFLICT;
|
||||
if (pksk->timestamp > sig->timestamp )
|
||||
{
|
||||
ulong d = pksk->timestamp - sig->timestamp;
|
||||
log_info (d==1 ? _("key has been created %lu second "
|
||||
"in future (time warp or clock problem)\n")
|
||||
: _("key has been created %lu seconds "
|
||||
"in future (time warp or clock problem)\n"), d );
|
||||
if (!opt.ignore_time_conflict)
|
||||
return gpg_error (GPG_ERR_TIME_CONFLICT);
|
||||
}
|
||||
|
||||
|
||||
print_pubkey_algo_note (pksk->pubkey_algo);
|
||||
|
||||
print_pubkey_algo_note (pksk->pubkey_algo);
|
||||
if (!mdalgo)
|
||||
mdalgo = gcry_md_get_algo (md);
|
||||
|
||||
if( !digest_algo )
|
||||
digest_algo = gcry_md_get_algo (md);
|
||||
print_digest_algo_note (mdalgo);
|
||||
dp = gcry_md_read (md, mdalgo);
|
||||
sig->digest_algo = mdalgo;
|
||||
sig->digest_start[0] = dp[0];
|
||||
sig->digest_start[1] = dp[1];
|
||||
sig->data[0] = NULL;
|
||||
sig->data[1] = NULL;
|
||||
|
||||
print_digest_algo_note( digest_algo );
|
||||
dp = gcry_md_read ( md, digest_algo );
|
||||
sig->digest_algo = digest_algo;
|
||||
sig->digest_start[0] = dp[0];
|
||||
sig->digest_start[1] = dp[1];
|
||||
|
||||
/* FIXME: Use agent. */
|
||||
#warning fixme: Use the agent for the card
|
||||
/* if (pksk->is_protected && pksk->protect.s2k.mode == 1002) */
|
||||
/* { */
|
||||
/* #ifdef ENABLE_CARD_SUPPORT */
|
||||
@ -285,57 +303,89 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
|
||||
/* #endif /\* ENABLE_CARD_SUPPORT *\/ */
|
||||
/* } */
|
||||
/* else */
|
||||
{
|
||||
frame = encode_md_value (NULL, pksk, md, digest_algo );
|
||||
if (!frame)
|
||||
return G10ERR_GENERAL;
|
||||
rc = pk_sign (pksk->pubkey_algo, sig->data, frame, pksk->pkey );
|
||||
gcry_mpi_release (frame);
|
||||
}
|
||||
|
||||
if (!rc && !opt.no_sig_create_check) {
|
||||
/* Check that the signature verification worked and nothing is
|
||||
* fooling us e.g. by a bug in the signature create
|
||||
* code or by deliberately introduced faults. */
|
||||
PKT_public_key *pk = xmalloc_clear (sizeof *pk);
|
||||
|
||||
if( get_pubkey( pk, sig->keyid ) )
|
||||
rc = G10ERR_NO_PUBKEY;
|
||||
else {
|
||||
frame = encode_md_value (pk, NULL, md, sig->digest_algo );
|
||||
if (!frame)
|
||||
rc = G10ERR_GENERAL;
|
||||
else
|
||||
rc = pk_verify (pk->pubkey_algo, frame, sig->data, pk->pkey );
|
||||
gcry_mpi_release (frame);
|
||||
if (1)
|
||||
{
|
||||
char *hexgrip;
|
||||
|
||||
err = hexkeygrip_from_pk (pksk, &hexgrip);
|
||||
if (!err)
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (rc)
|
||||
log_error (_("checking created signature failed: %s\n"),
|
||||
g10_errstr (rc));
|
||||
free_public_key (pk);
|
||||
xfree (hexgrip);
|
||||
}
|
||||
if( rc )
|
||||
log_error(_("signing failed: %s\n"), g10_errstr(rc) );
|
||||
else {
|
||||
if( opt.verbose ) {
|
||||
char *ustr = get_user_id_string_native (sig->keyid);
|
||||
log_info(_("%s/%s signature from: \"%s\"\n"),
|
||||
gcry_pk_algo_name (pksk->pubkey_algo),
|
||||
gcry_md_algo_name (sig->digest_algo),
|
||||
ustr );
|
||||
xfree(ustr);
|
||||
|
||||
/* Check that the signature verification worked and nothing is
|
||||
* fooling us e.g. by a bug in the signature create code or by
|
||||
* deliberately introduced faults. */
|
||||
if (!err && !opt.no_sig_create_check)
|
||||
{
|
||||
PKT_public_key *pk = xmalloc_clear (sizeof *pk);
|
||||
|
||||
if (get_pubkey (pk, sig->keyid ))
|
||||
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (err)
|
||||
log_error (_("checking created signature failed: %s\n"),
|
||||
g10_errstr (err));
|
||||
free_public_key (pk);
|
||||
}
|
||||
|
||||
if (err)
|
||||
log_error (_("signing failed: %s\n"), g10_errstr (err));
|
||||
else
|
||||
{
|
||||
if (opt.verbose)
|
||||
{
|
||||
char *ustr = get_user_id_string_native (sig->keyid);
|
||||
log_info (_("%s/%s signature from: \"%s\"\n"),
|
||||
gcry_pk_algo_name (pksk->pubkey_algo),
|
||||
gcry_md_algo_name (sig->digest_algo),
|
||||
ustr);
|
||||
xfree (ustr);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
complete_sig( PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md )
|
||||
complete_sig (PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!(rc = check_secret_key (pksk, 0)))
|
||||
/* if (!(rc = check_secret_key (pksk, 0))) */
|
||||
rc = do_sign (pksk, sig, md, 0);
|
||||
return rc;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user