Generating an OpenPGP key cia gpg-agent basically works.

This commit is contained in:
Werner Koch 2010-04-20 17:57:50 +00:00
parent 67934a8c13
commit 21b0a955be
23 changed files with 1233 additions and 1364 deletions

View File

@ -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.

View File

@ -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;
}

View File

@ -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*/

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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 );

View File

@ -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. */

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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 --*/

View File

@ -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 );

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -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; */
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}