1
0
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:
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> 2010-04-14 Werner Koch <wk@g10code.com>
* cpr.c (myread) [W32CE]: Do not use raise. * cpr.c (myread) [W32CE]: Do not use raise.

View File

@ -1,6 +1,6 @@
/* call-agent.c - Divert GPG operations to the agent. /* call-agent.c - Divert GPG operations to the agent.
* Copyright (C) 2001, 2002, 2003, 2006, 2007, * Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009,
* 2008, 2009 Free Software Foundation, Inc. * 2010 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -69,14 +69,15 @@ struct writekey_parm_s
size_t keydatalen; size_t keydatalen;
}; };
struct genkey_parm_s struct genkey_parm_s
{ {
ctrl_t ctrl;
assuan_context_t ctx; assuan_context_t ctx;
const char *sexp; const char *keyparms;
size_t sexplen;
}; };
static gpg_error_t learn_status_cb (void *opaque, const char *line); static gpg_error_t learn_status_cb (void *opaque, const char *line);
@ -107,10 +108,12 @@ status_sc_op_failure (int rc)
/* Try to connect to the agent via socket or fork it off and work by /* Try to connect to the agent via socket or fork it off and work by
pipes. Handle the server's initial greeting */ pipes. Handle the server's initial greeting */
static int static int
start_agent (int for_card) start_agent (ctrl_t ctrl, int for_card)
{ {
int rc; int rc;
(void)ctrl; /* Not yet used. */
/* Fixme: We need a context for each thread or serialize the access /* Fixme: We need a context for each thread or serialize the access
to the agent. */ to the agent. */
if (agent_ctx) if (agent_ctx)
@ -486,7 +489,7 @@ agent_learn (struct agent_card_info_s *info)
{ {
int rc; int rc;
rc = start_agent (1); rc = start_agent (NULL, 1);
if (rc) if (rc)
return rc; return rc;
@ -531,7 +534,7 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
return gpg_error (GPG_ERR_TOO_LARGE); return gpg_error (GPG_ERR_TOO_LARGE);
stpcpy (stpcpy (line, "SCD GETATTR "), name); stpcpy (stpcpy (line, "SCD GETATTR "), name);
rc = start_agent (1); rc = start_agent (NULL, 1);
if (rc) if (rc)
return rc; return rc;
@ -581,7 +584,7 @@ agent_scd_setattr (const char *name,
} }
*p = 0; *p = 0;
rc = start_agent (1); rc = start_agent (NULL, 1);
if (!rc) if (!rc)
{ {
rc = assuan_transact (agent_ctx, line, NULL, NULL, rc = assuan_transact (agent_ctx, line, NULL, NULL,
@ -623,7 +626,7 @@ agent_scd_writecert (const char *certidstr,
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct writecert_parm_s parms; struct writecert_parm_s parms;
rc = start_agent (1); rc = start_agent (NULL, 1);
if (rc) if (rc)
return rc; return rc;
@ -673,7 +676,7 @@ agent_scd_writekey (int keyno, const char *serialno,
(void)serialno; (void)serialno;
rc = start_agent (1); rc = start_agent (NULL, 1);
if (rc) if (rc)
return rc; return rc;
@ -762,7 +765,7 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
(void)serialno; (void)serialno;
rc = start_agent (1); rc = start_agent (NULL, 1);
if (rc) if (rc)
return rc; return rc;
@ -909,7 +912,7 @@ agent_scd_pksign (const char *serialno, int hashalgo,
*r_buf = NULL; *r_buf = NULL;
*r_buflen = 0; *r_buflen = 0;
rc = start_agent (1); rc = start_agent (NULL, 1);
if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT
|| gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED) || gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
rc = 0; /* We check later. */ rc = 0; /* We check later. */
@ -972,7 +975,7 @@ agent_scd_pkdecrypt (const char *serialno,
size_t len; size_t len;
*r_buf = NULL; *r_buf = NULL;
rc = start_agent (1); rc = start_agent (NULL, 1);
if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT
|| gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED) || gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
rc = 0; /* We check later. */ rc = 0; /* We check later. */
@ -1029,7 +1032,7 @@ agent_scd_readcert (const char *certidstr,
size_t len; size_t len;
*r_buf = NULL; *r_buf = NULL;
rc = start_agent (1); rc = start_agent (NULL, 1);
if (rc) if (rc)
return rc; return rc;
@ -1077,7 +1080,7 @@ agent_scd_change_pin (int chvno, const char *serialno)
reset = "--reset"; reset = "--reset";
chvno %= 100; chvno %= 100;
rc = start_agent (1); rc = start_agent (NULL, 1);
if (rc) if (rc)
return rc; return rc;
@ -1099,7 +1102,7 @@ agent_scd_checkpin (const char *serialno)
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
rc = start_agent (1); rc = start_agent (NULL, 1);
if (rc) if (rc)
return rc; return rc;
@ -1146,7 +1149,7 @@ agent_get_passphrase (const char *cache_id,
*r_passphrase = NULL; *r_passphrase = NULL;
rc = start_agent (0); rc = start_agent (NULL, 0);
if (rc) if (rc)
return rc; return rc;
@ -1217,7 +1220,7 @@ agent_clear_passphrase (const char *cache_id)
if (!cache_id || !*cache_id) if (!cache_id || !*cache_id)
return 0; return 0;
rc = start_agent (0); rc = start_agent (NULL, 0);
if (rc) if (rc)
return rc; return rc;
@ -1237,7 +1240,7 @@ gpg_agent_get_confirmation (const char *desc)
char *tmp; char *tmp;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
rc = start_agent (0); rc = start_agent (NULL, 0);
if (rc) if (rc)
return rc; return rc;
@ -1264,7 +1267,7 @@ agent_get_s2k_count (unsigned long *r_count)
*r_count = 0; *r_count = 0;
err = start_agent (0); err = start_agent (NULL, 0);
if (err) if (err)
return err; return err;
@ -1289,3 +1292,291 @@ agent_get_s2k_count (unsigned long *r_count)
return err; return err;
} }
/* Ask the agent whether a secret key with the given keygrip is
known. */
gpg_error_t
agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
{
gpg_error_t err;
char line[ASSUAN_LINELENGTH];
err = start_agent (ctrl, 0);
if (err)
return err;
if (!hexkeygrip || strlen (hexkeygrip) != 40)
return gpg_error (GPG_ERR_INV_VALUE);
snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
line[DIM(line)-1] = 0;
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
return err;
}
static gpg_error_t
keyinfo_status_cb (void *opaque, const char *line)
{
char **serialno = opaque;
const char *s, *s2;
if (!strncmp (line, "KEYINFO ", 8) && !*serialno)
{
s = strchr (line+8, ' ');
if (s && s[1] == 'T' && s[2] == ' ' && s[3])
{
s += 3;
s2 = strchr (s, ' ');
if ( s2 > s )
{
*serialno = xtrymalloc ((s2 - s)+1);
if (*serialno)
{
memcpy (*serialno, s, s2 - s);
(*serialno)[s2 - s] = 0;
}
}
}
}
return 0;
}
/* Return the serial number for a secret key. If the returned serial
number is NULL, the key is not stored on a smartcard. Caller needs
to free R_SERIALNO. */
gpg_error_t
agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip, char **r_serialno)
{
gpg_error_t err;
char line[ASSUAN_LINELENGTH];
char *serialno = NULL;
*r_serialno = NULL;
err = start_agent (ctrl, 0);
if (err)
return err;
if (!hexkeygrip || strlen (hexkeygrip) != 40)
return gpg_error (GPG_ERR_INV_VALUE);
snprintf (line, DIM(line)-1, "KEYINFO %s", hexkeygrip);
line[DIM(line)-1] = 0;
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
keyinfo_status_cb, &serialno);
if (!err && serialno)
{
/* Sanity check for bad characters. */
if (strpbrk (serialno, ":\n\r"))
err = GPG_ERR_INV_VALUE;
}
if (err)
xfree (serialno);
else
*r_serialno = serialno;
return err;
}
/* Handle a KEYPARMS inquiry. Note, we only send the data,
assuan_transact takes care of flushing and writing the end */
static gpg_error_t
inq_genkey_parms (void *opaque, const char *line)
{
struct genkey_parm_s *parm = opaque;
gpg_error_t err;
if (!strncmp (line, "KEYPARAM", 8) && (line[8]==' '||!line[8]))
{
err = assuan_send_data (parm->ctx,
parm->keyparms, strlen (parm->keyparms));
}
else
err = default_inq_cb (parm->ctrl, line);
return err;
}
/* Call the agent to generate a new key. KEYPARMS is the usual
S-expression giving the parameters of the key. gpg-agent passes it
gcry_pk_genkey. */
gpg_error_t
agent_genkey (ctrl_t ctrl, const char *keyparms, gcry_sexp_t *r_pubkey)
{
gpg_error_t err;
struct genkey_parm_s gk_parm;
membuf_t data;
size_t len;
unsigned char *buf;
*r_pubkey = NULL;
err = start_agent (ctrl, 0);
if (err)
return err;
err = assuan_transact (agent_ctx, "RESET",
NULL, NULL, NULL, NULL, NULL, NULL);
if (err)
return err;
init_membuf (&data, 1024);
gk_parm.ctrl = ctrl;
gk_parm.ctx = agent_ctx;
gk_parm.keyparms = keyparms;
err = assuan_transact (agent_ctx, "GENKEY",
membuf_data_cb, &data,
inq_genkey_parms, &gk_parm, NULL, NULL);
if (err)
{
xfree (get_membuf (&data, &len));
return err;
}
buf = get_membuf (&data, &len);
if (!buf)
err = gpg_error_from_syserror ();
else
{
err = gcry_sexp_sscan (r_pubkey, NULL, buf, len);
xfree (buf);
}
return err;
}
/* FIXME: Call the agent to read the public key part for a given keygrip. If
FROMCARD is true, the key is directly read from the current
smartcard. In this case HEXKEYGRIP should be the keyID
(e.g. OPENPGP.3). */
/* int */
/* agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip, */
/* ksba_sexp_t *r_pubkey) */
/* { */
/* int rc; */
/* membuf_t data; */
/* size_t len; */
/* unsigned char *buf; */
/* char line[ASSUAN_LINELENGTH]; */
/* *r_pubkey = NULL; */
/* rc = start_agent (ctrl); */
/* if (rc) */
/* return rc; */
/* rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL); */
/* if (rc) */
/* return rc; */
/* snprintf (line, DIM(line)-1, "%sREADKEY %s", */
/* fromcard? "SCD ":"", hexkeygrip); */
/* line[DIM(line)-1] = 0; */
/* init_membuf (&data, 1024); */
/* rc = assuan_transact (agent_ctx, line, */
/* membuf_data_cb, &data, */
/* default_inq_cb, ctrl, NULL, NULL); */
/* if (rc) */
/* { */
/* xfree (get_membuf (&data, &len)); */
/* return rc; */
/* } */
/* buf = get_membuf (&data, &len); */
/* if (!buf) */
/* return gpg_error (GPG_ERR_ENOMEM); */
/* if (!gcry_sexp_canon_len (buf, len, NULL, NULL)) */
/* { */
/* xfree (buf); */
/* return gpg_error (GPG_ERR_INV_SEXP); */
/* } */
/* *r_pubkey = buf; */
/* return 0; */
/* } */
/* Call the agent to do a sign operation using the key identified by
the hex string KEYGRIP. DESC is a description of the key to be
displayed if the agent needs to ask for the PIN. DIGEST and
DIGESTLEN is the hash value to sign and DIGESTALGO the algorithm id
used to compute the digest. */
gpg_error_t
agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
unsigned char *digest, size_t digestlen, int digestalgo,
gcry_sexp_t *r_sigval)
{
gpg_error_t err;
int i;
char *p, line[ASSUAN_LINELENGTH];
membuf_t data;
*r_sigval = NULL;
err = start_agent (ctrl, 0);
if (err)
return err;
if (digestlen*2 + 50 > DIM(line))
return gpg_error (GPG_ERR_GENERAL);
err = assuan_transact (agent_ctx, "RESET",
NULL, NULL, NULL, NULL, NULL, NULL);
if (err)
return err;
snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip);
line[DIM(line)-1] = 0;
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (err)
return err;
if (desc)
{
snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
line[DIM(line)-1] = 0;
err = assuan_transact (agent_ctx, line,
NULL, NULL, NULL, NULL, NULL, NULL);
if (err)
return err;
}
snprintf (line, sizeof line, "SETHASH %d ", digestalgo);
p = line + strlen (line);
for (i=0; i < digestlen ; i++, p += 2 )
sprintf (p, "%02X", digest[i]);
err = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (err)
return err;
init_membuf (&data, 1024);
err = assuan_transact (agent_ctx, "PKSIGN",
membuf_data_cb, &data, default_inq_cb, ctrl,
NULL, NULL);
if (err)
xfree (get_membuf (&data, NULL));
else
{
unsigned char *buf;
size_t len;
buf = get_membuf (&data, &len);
if (!buf)
err = gpg_error_from_syserror ();
else
{
err = gcry_sexp_sscan (r_sigval, NULL, buf, len);
xfree (buf);
}
}
return err;
}

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. */ /* Return the S2K iteration count as computed by gpg-agent. */
gpg_error_t agent_get_s2k_count (unsigned long *r_count); gpg_error_t agent_get_s2k_count (unsigned long *r_count);
/* Check whether a secret key with HEXKEYGRIP is available. */
gpg_error_t agent_havekey (ctrl_t ctrl, const char *hexkeygrip);
/* Return infos about the secret key with HEXKEYGRIP. */
gpg_error_t agent_get_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
char **r_serialno);
/* Generate a new key. */
gpg_error_t agent_genkey (ctrl_t ctrl, const char *keyparms,
gcry_sexp_t *r_pubkey);
/* Create a sigtnature. */
gpg_error_t agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
unsigned char *digest, size_t digestlen,
int digestalgo,
gcry_sexp_t *r_sigval);
#endif /*GNUPG_G10_CALL_AGENT_H*/ #endif /*GNUPG_G10_CALL_AGENT_H*/

View File

@ -1495,8 +1495,8 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
the serialnumber and thus it won't harm. */ the serialnumber and thus it won't harm. */
} }
okay = generate_card_subkeypair (pub_keyblock, sec_keyblock, /* xxx = generate_card_subkeypair (pub_keyblock, sec_keyblock, */
keyno, info.serialno); /* keyno, info.serialno); */
leave: leave:
agent_release_card_info (&info); agent_release_card_info (&info);
@ -1612,17 +1612,18 @@ card_store_subkey (KBNODE node, int use)
} }
/* We better copy the key before we unprotect it. */ /* We better copy the key before we unprotect it. */
copied_sk = sk = copy_secret_key (NULL, sk); copied_sk = sk = copy_secret_key (NULL, sk);
rc = check_secret_key (sk, 0); rc = 0/*check_secret_key (sk, 0)*/;
if (rc) if (rc)
goto leave; goto leave;
} }
rc = save_unprotected_key_to_card (sk, keyno); #warning code save_unprotected_key_to_card
if (rc) /* rc = save_unprotected_key_to_card (sk, keyno); */
{ /* if (rc) */
log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); /* { */
goto leave; /* log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); */
} /* goto leave; */
/* } */
/* Get back to the maybe protected original secret key. */ /* Get back to the maybe protected original secret key. */
if (copied_sk) if (copied_sk)

View File

@ -550,7 +550,7 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
; /* Card key stub. */ ; /* Card key stub. */
else else
{ {
rc = check_secret_key( sk, 0 ); /* rc = check_secret_key( sk, 0 ); */
} }
break; break;
} }

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 /* Check the secret key (this may prompt for a passprase to
* unlock the secret key. */ * unlock the secret key. */
rc = check_secret_key (sk, 0); /* rc = check_secret_key (sk, 0); */
} }
return rc; return rc;
@ -1111,8 +1111,8 @@ get_seckey_byname2 (GETKEY_CTX * retctx,
free_strlist (namelist); free_strlist (namelist);
if (!rc && unprotect) /* if (!rc && unprotect) */
rc = check_secret_key (sk, 0); /* rc = check_secret_key (sk, 0); */
return rc; return rc;
} }

View File

@ -108,7 +108,7 @@ struct server_control_s
#define G10ERR_RENAME_FILE GPG_ERR_RENAME_FILE #define G10ERR_RENAME_FILE GPG_ERR_RENAME_FILE
#define G10ERR_RESOURCE_LIMIT GPG_ERR_RESOURCE_LIMIT #define G10ERR_RESOURCE_LIMIT GPG_ERR_RESOURCE_LIMIT
#define G10ERR_SIG_CLASS GPG_ERR_SIG_CLASS #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_TRUSTDB GPG_ERR_TRUSTDB
#define G10ERR_UNEXPECTED GPG_ERR_UNEXPECTED #define G10ERR_UNEXPECTED GPG_ERR_UNEXPECTED
#define G10ERR_UNKNOWN_PACKET GPG_ERR_UNKNOWN_PACKET #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 * We don't use secret keys, but getkey.c links to this
*/ */
int int
check_secret_key (PKT_secret_key *sk, int n) check_secret_key (PKT_public_key *pk, int n)
{ {
(void)sk; (void)pk;
(void)n; (void)n;
return G10ERR_GENERAL; return G10ERR_GENERAL;
} }

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 ); byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
char *serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen, char *serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
PKT_secret_key *sk); PKT_secret_key *sk);
gpg_error_t keygrip_from_pk (PKT_public_key *pk, unsigned char *array);
gpg_error_t hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip);
/*-- kbnode.c --*/ /*-- kbnode.c --*/
KBNODE new_kbnode( PACKET *pkt ); KBNODE new_kbnode( PACKET *pkt );

View File

@ -1164,9 +1164,9 @@ change_passphrase (KBNODE keyblock, int *r_err)
keyid_from_sk (sk, keyid); keyid_from_sk (sk, keyid);
passphrase_clear_cache (keyid, NULL, 0); passphrase_clear_cache (keyid, NULL, 0);
rc = check_secret_key( sk, 0 ); /* rc = check_secret_key( sk, 0 ); */
if( !rc ) /* if( !rc ) */
passphrase = get_last_passphrase(); /* passphrase = get_last_passphrase(); */
} }
break; break;
} }
@ -1179,9 +1179,9 @@ change_passphrase (KBNODE keyblock, int *r_err)
&& (subsk->protect.s2k.mode == 1001 && (subsk->protect.s2k.mode == 1001
|| subsk->protect.s2k.mode == 1002))) { || subsk->protect.s2k.mode == 1002))) {
set_next_passphrase( passphrase ); set_next_passphrase( passphrase );
rc = check_secret_key( subsk, 0 ); /* rc = check_secret_key( subsk, 0 ); */
if( !rc && !passphrase ) /* if( !rc && !passphrase ) */
passphrase = get_last_passphrase(); /* passphrase = get_last_passphrase(); */
} }
} }
} }
@ -1227,7 +1227,9 @@ change_passphrase (KBNODE keyblock, int *r_err)
if( !no_primary_secrets ) { if( !no_primary_secrets ) {
sk->protect.algo = dek->algo; sk->protect.algo = dek->algo;
sk->protect.s2k = *s2k; sk->protect.s2k = *s2k;
rc = protect_secret_key( sk, dek ); #warning fixme
rc = 0;
/* rc = protect_secret_key( sk, dek ); */
} }
for(node=keyblock; !rc && node; node = node->next ) { for(node=keyblock; !rc && node; node = node->next ) {
if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) { if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
@ -1237,7 +1239,9 @@ change_passphrase (KBNODE keyblock, int *r_err)
|| subsk->protect.s2k.mode == 1002))) { || subsk->protect.s2k.mode == 1002))) {
subsk->protect.algo = dek->algo; subsk->protect.algo = dek->algo;
subsk->protect.s2k = *s2k; subsk->protect.s2k = *s2k;
rc = protect_secret_key( subsk, dek ); #warning fixme
rc = 0;
/* rc = protect_secret_key( subsk, dek ); */
} }
} }
} }
@ -1892,12 +1896,13 @@ keyedit_menu( const char *username, strlist_t locusr,
break; break;
case cmdADDKEY: case cmdADDKEY:
if( generate_subkeypair( keyblock, sec_keyblock ) ) { if (!generate_subkeypair (keyblock))
{
redisplay = 1; redisplay = 1;
sec_modified = modified = 1; sec_modified = modified = 1;
merge_keys_and_selfsig( sec_keyblock ); merge_keys_and_selfsig( sec_keyblock );
merge_keys_and_selfsig( keyblock ); merge_keys_and_selfsig( keyblock );
} }
break; break;
#ifdef ENABLE_CARD_SUPPORT #ifdef ENABLE_CARD_SUPPORT
@ -2018,8 +2023,8 @@ keyedit_menu( const char *username, strlist_t locusr,
if (sk->protect.s2k.mode == 1002) if (sk->protect.s2k.mode == 1002)
tty_printf (_("Secret parts of key" tty_printf (_("Secret parts of key"
" are stored on-card.\n")); " are stored on-card.\n"));
else /* else */
check_secret_key (sk, 0); /* check_secret_key (sk, 0); */
} }
} }
else /* Store it. */ else /* Store it. */

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* keyid.c - key ID and fingerprint handling /* keyid.c - key ID and fingerprint handling
* Copyright (C) 1998, 1999, 2000, 2001, 2003, * Copyright (C) 1998, 1999, 2000, 2001, 2003,
* 2004, 2006 Free Software Foundation, Inc. * 2004, 2006, 2010 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -828,3 +828,90 @@ serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
return buffer; return buffer;
} }
/* Return the so called KEYGRIP which is the SHA-1 hash of the public
key parameters expressed as an canoncial encoded S-Exp. ARRAY must
be 20 bytes long. Returns 0 on sucess or an error code. */
gpg_error_t
keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
{
gpg_error_t err;
gcry_sexp_t s_pkey;
if (DBG_PACKET)
log_debug ("get_keygrip for public key\n");
switch (pk->pubkey_algo)
{
case GCRY_PK_DSA:
err = gcry_sexp_build (&s_pkey, NULL,
"(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
pk->pkey[0], pk->pkey[1],
pk->pkey[2], pk->pkey[3]);
break;
case GCRY_PK_ELG:
case GCRY_PK_ELG_E:
err = gcry_sexp_build (&s_pkey, NULL,
"(public-key(elg(p%m)(g%m)(y%m)))",
pk->pkey[0], pk->pkey[1], pk->pkey[2]);
break;
case GCRY_PK_RSA:
case GCRY_PK_RSA_S:
case GCRY_PK_RSA_E:
err = gcry_sexp_build (&s_pkey, NULL,
"(public-key(rsa(n%m)(e%m)))",
pk->pkey[0], pk->pkey[1]);
break;
default:
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
break;
}
if (err)
return err;
if (!gcry_pk_get_keygrip (s_pkey, array))
{
log_error ("error computing keygrip\n");
err = gpg_error (GPG_ERR_GENERAL);
}
else
{
if (DBG_PACKET)
log_printhex ("keygrip=", array, 20);
/* FIXME: Save the keygrip in PK. */
}
gcry_sexp_release (s_pkey);
return 0;
}
/* Store an allocated buffer with the keygrip of PK encoded as a
hexstring at r_GRIP. Returns 0 on success. */
gpg_error_t
hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip)
{
gpg_error_t err;
unsigned char grip[20];
*r_grip = NULL;
err = keygrip_from_pk (pk, grip);
if (!err)
{
char * buf = xtrymalloc (20*2+1);
if (!buf)
err = gpg_error_from_syserror ();
else
{
bin2hex (grip, 20, buf);
*r_grip = buf;
}
}
return err;
}

View File

@ -1063,6 +1063,7 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
int trustletter = 0; int trustletter = 0;
int ulti_hack = 0; int ulti_hack = 0;
int i; int i;
char *p;
/* Get the keyid from the keyblock. */ /* Get the keyid from the keyblock. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY); node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
@ -1128,8 +1129,15 @@ list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
if (fpr) if (fpr)
print_fingerprint (pk, NULL, 0); print_fingerprint (pk, NULL, 0);
if (opt.with_key_data) if (opt.with_key_data)
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));) for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
{ {
if (node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode) 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) if (fpr > 1)
print_fingerprint (pk2, NULL, 0); print_fingerprint (pk2, NULL, 0);
if (opt.with_key_data) 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) 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) else if (!opt.fast_list_mode)
{ {
size_t n; size_t n;
char *p = get_user_id (sig->keyid, &n); p = get_user_id (sig->keyid, &n);
es_write_sanitized (es_stdout, p, n, ":", NULL); es_write_sanitized (es_stdout, p, n, ":", NULL);
xfree (p); xfree (p);
} }

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_keyserver_url(PKT_signature *sig, void *opaque);
int keygen_add_notations(PKT_signature *sig,void *opaque); int keygen_add_notations(PKT_signature *sig,void *opaque);
int keygen_add_revkey(PKT_signature *sig, void *opaque); int keygen_add_revkey(PKT_signature *sig, void *opaque);
int make_backsig(PKT_signature *sig,PKT_public_key *pk, gpg_error_t make_backsig (PKT_signature *sig, PKT_public_key *pk,
PKT_public_key *sub_pk,PKT_secret_key *sub_sk, PKT_public_key *sub_pk, PKT_public_key *sub_psk,
u32 timestamp); u32 timestamp);
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock ); gpg_error_t generate_subkeypair (kbnode_t pub_keyblock);
#ifdef ENABLE_CARD_SUPPORT #ifdef ENABLE_CARD_SUPPORT
int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock, int generate_card_subkeypair (KBNODE pub_keyblock, KBNODE sec_keyblock,
int keyno, const char *serialno); int keyno, const char *serialno);
@ -258,7 +258,7 @@ void try_make_homedir( const char *fname );
/*-- seskey.c --*/ /*-- seskey.c --*/
void make_session_key( DEK *dek ); void make_session_key( DEK *dek );
gcry_mpi_t encode_session_key( DEK *dek, unsigned nbits ); gcry_mpi_t encode_session_key( DEK *dek, unsigned nbits );
gcry_mpi_t encode_md_value( PKT_public_key *pk, PKT_secret_key *sk, gcry_mpi_t encode_md_value (PKT_public_key *pk,
gcry_md_hd_t md, int hash_algo ); gcry_md_hd_t md, int hash_algo );
/*-- import.c --*/ /*-- import.c --*/

View File

@ -206,7 +206,7 @@ struct revoke_info
/**************** /****************
* Note about the pkey/skey elements: We assume that the secret keys * Note about the pkey/skey elements: We assume that the secret keys
* has the same elemts as the public key at the begin of the array, so * has the same elements as the public key at the begin of the array, so
* that npkey < nskey and it is possible to compare the secret and * that npkey < nskey and it is possible to compare the secret and
* public keys by comparing the first npkey elements of pkey againts skey. * public keys by comparing the first npkey elements of pkey againts skey.
*/ */
@ -477,9 +477,7 @@ int signature_check2( PKT_signature *sig, gcry_md_hd_t digest, u32 *r_expiredate
int *r_expired, int *r_revoked, PKT_public_key *ret_pk ); int *r_expired, int *r_revoked, PKT_public_key *ret_pk );
/*-- seckey-cert.c --*/ /*-- seckey-cert.c --*/
int is_secret_key_protected( PKT_secret_key *sk ); int is_secret_key_protected (PKT_public_key *pk);
int check_secret_key( PKT_secret_key *sk, int retries );
int protect_secret_key( PKT_secret_key *sk, DEK *dek );
/*-- pubkey-enc.c --*/ /*-- pubkey-enc.c --*/
int get_session_key( PKT_pubkey_enc *k, DEK *dek ); int get_session_key( PKT_pubkey_enc *k, DEK *dek );

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 * Emulate our old PK interface here - sometime in the future we might
@ -304,7 +247,7 @@ pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data,
/* Check whether SKEY is a suitable secret key. */ /* Check whether SKEY is a suitable secret key. */
int int
pk_check_secret_key (int algo, gcry_mpi_t *skey) REMOVE_ME_pk_check_secret_key (int algo, gcry_mpi_t *skey)
{ {
gcry_sexp_t s_skey; gcry_sexp_t s_skey;
int rc; int rc;

View File

@ -20,8 +20,6 @@
#ifndef GNUPG_G10_PKGLUE_H #ifndef GNUPG_G10_PKGLUE_H
#define GNUPG_G10_PKGLUE_H #define GNUPG_G10_PKGLUE_H
int pk_sign (int algo, gcry_mpi_t *data, gcry_mpi_t hash,
gcry_mpi_t *skey);
int pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, int pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data,
gcry_mpi_t *pkey); gcry_mpi_t *pkey);
int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data,

View File

@ -114,10 +114,10 @@ get_session_key( PKT_pubkey_enc *k, DEK *dek )
xfree(p); xfree(p);
} }
rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /* ask /* rc = check_secret_key( sk, opt.try_all_secrets?1:-1 ); /\* ask */
only /* only */
once */ /* once *\/ */
if( !rc ) /* if( !rc ) */
{ {
rc = get_it( k, dek, sk, keyid ); rc = get_it( k, dek, sk, keyid );
/* Successfully checked the secret key (either it was /* Successfully checked the secret key (either it was

View File

@ -436,181 +436,144 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
* Generate a revocation certificate for UNAME * Generate a revocation certificate for UNAME
*/ */
int int
gen_revoke( const char *uname ) gen_revoke (const char *uname)
{ {
int rc = 0; int rc = 0;
armor_filter_context_t *afx; armor_filter_context_t *afx;
PACKET pkt; PACKET pkt;
PKT_secret_key *sk; /* used as pointer into a kbnode */ PKT_public_key *psk;
PKT_public_key *pk = NULL; PKT_signature *sig = NULL;
PKT_signature *sig = NULL; u32 keyid[2];
u32 sk_keyid[2]; iobuf_t out = NULL;
IOBUF out = NULL; kbnode_t keyblock = NULL;
KBNODE keyblock = NULL, pub_keyblock = NULL; kbnode_t node;
KBNODE node; KEYDB_HANDLE kdbhd;
KEYDB_HANDLE kdbhd; struct revocation_reason_info *reason = NULL;
struct revocation_reason_info *reason = NULL; KEYDB_SEARCH_DESC desc;
KEYDB_SEARCH_DESC desc;
if( opt.batch ) if( opt.batch )
{ {
log_error(_("can't do this in batch mode\n")); log_error(_("can't do this in batch mode\n"));
return G10ERR_GENERAL; 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;
} }
/* get the keyid from the keyblock */ afx = new_armor_context ();
node = find_kbnode( keyblock, PKT_SECRET_KEY ); init_packet( &pkt );
if( !node )
BUG ();
/* fixme: should make a function out of this stuff, /* Search the userid; we don't want the whole getkey stuff here. */
* it's used all over the source */ kdbhd = keydb_new (1);
sk = node->pkt->pkt.secret_key; rc = classify_user_id (uname, &desc);
keyid_from_sk( sk, sk_keyid ); if (!rc)
print_seckey_info (sk); rc = keydb_search (kdbhd, &desc, 1);
if (rc)
/* FIXME: We should get the public key direct from the secret one */ {
log_error (_("secret key \"%s\" not found: %s\n"),
pub_keyblock=get_pubkeyblock(sk_keyid); uname, g10_errstr (rc));
if(!pub_keyblock) goto leave;
{
log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) );
goto leave;
}
node=find_kbnode(pub_keyblock,PKT_PUBLIC_KEY);
if(!node)
BUG();
pk=node->pkt->pkt.public_key;
if( cmp_public_secret_key( pk, sk ) ) {
log_error(_("public key does not match secret key!\n") );
rc = G10ERR_GENERAL;
goto leave;
} }
tty_printf("\n"); rc = keydb_get_keyblock (kdbhd, &keyblock );
if( !cpr_get_answer_is_yes("gen_revoke.okay", if( rc ) {
_("Create a revocation certificate for this key? (y/N) ")) ) log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
{ goto leave;
rc = 0; }
goto leave;
}
if(sk->version>=4 || opt.force_v4_certs) { /* Get the keyid from the keyblock. */
/* get the reason for the revocation */ node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
reason = ask_revocation_reason( 1, 0, 1 ); if (!node)
if( !reason ) { /* user decided to cancel */ BUG ();
rc = 0;
goto leave; /* 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 ) ) { if (psk->version >= 4 || opt.force_v4_certs)
case -1: {
log_error(_("unknown protection algorithm\n")); /* Get the reason for the revocation. */
rc = G10ERR_PUBKEY_ALGO; reason = ask_revocation_reason (1, 0, 1);
break; if (!reason)
case -3: {
tty_printf (_("Secret parts of primary key are not available.\n")); /* user decided to cancel */
rc = G10ERR_NO_SECKEY; rc = 0;
break; goto leave;
case 0: }
tty_printf(_("NOTE: This key is not protected!\n"));
break;
default:
rc = check_secret_key( sk, 0 );
break;
} }
if( rc )
goto leave; if (!opt.armor)
tty_printf (_("ASCII armored output forced.\n"));
if ((rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )))
goto leave;
if( !opt.armor ) afx->what = 1;
tty_printf(_("ASCII armored output forced.\n")); afx->hdrlines = "Comment: A revocation certificate should follow\n";
push_armor_filter (afx, out);
if( (rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )) ) /* create it */
goto leave; rc = make_keysig_packet (&sig, psk, NULL, NULL, psk, 0x20, 0,
opt.force_v4_certs?4:0, 0, 0,
afx->what = 1; revocation_reason_build_cb, reason );
afx->hdrlines = "Comment: A revocation certificate should follow\n"; if (rc)
push_armor_filter (afx, out); {
log_error (_("make_keysig_packet failed: %s\n"), g10_errstr (rc));
/* create it */ goto leave;
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;
} }
if(PGP2 || PGP6 || PGP7 || PGP8) if (PGP2 || PGP6 || PGP7 || PGP8)
{ {
/* Use a minimal pk for PGPx mode, since PGP can't import bare /* Use a minimal pk for PGPx mode, since PGP can't import bare
revocation certificates. */ revocation certificates. */
rc=export_minimal_pk(out,pub_keyblock,sig,NULL); rc = export_minimal_pk (out, keyblock, sig, NULL);
if(rc) if(rc)
goto leave; goto leave;
} }
else else
{ {
init_packet( &pkt ); init_packet( &pkt );
pkt.pkttype = PKT_SIGNATURE; pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig; pkt.pkt.signature = sig;
rc = build_packet( out, &pkt ); rc = build_packet (out, &pkt);
if( rc ) { if (rc)
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) ); {
goto leave; log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
} goto leave;
} }
}
/* and issue a usage notice */
tty_printf(_("Revocation certificate created.\n\n" /* 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" "Please move it to a medium which you can hide away; if Mallory gets\n"
"access to this certificate he can use it to make your key unusable.\n" "access to this certificate he can use it to make your key unusable.\n"
"It is smart to print this certificate and store it away, just in case\n" "It is smart to print this certificate and store it away, just in case\n"
"your media become unreadable. But have some caution: The print system of\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")); "your machine might store the data and make it available to others!\n"));
leave: leave:
if( sig ) if (sig)
free_seckey_enc( sig ); free_seckey_enc (sig);
release_kbnode( keyblock ); release_kbnode (keyblock);
release_kbnode( pub_keyblock ); keydb_release (kdbhd);
keydb_release (kdbhd); if (rc)
if( rc ) iobuf_cancel(out);
iobuf_cancel(out); else
else iobuf_close(out);
iobuf_close(out); release_revocation_reason_info( reason );
release_revocation_reason_info( reason ); release_armor_context (afx);
release_armor_context (afx); return rc;
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. * check whether the secret key is protected.
* Returns: 0 not protected, -1 on error or the protection algorithm * Returns: 0 not protected, -1 on error or the protection algorithm
@ -318,156 +266,10 @@ check_secret_key( PKT_secret_key *sk, int n )
* -3 indicates a not-online stub. * -3 indicates a not-online stub.
*/ */
int int
is_secret_key_protected( PKT_secret_key *sk ) is_secret_key_protected (PKT_public_key *pk)
{ {
return sk->is_protected? return 0; /* FIXME: use agent_get_keyinfo?*/
sk->protect.s2k.mode == 1002? -2 : /* return sk->is_protected? */
sk->protect.s2k.mode == 1001? -3 : sk->protect.algo : 0; /* sk->protect.s2k.mode == 1002? -2 : */
} /* sk->protect.s2k.mode == 1001? -3 : sk->protect.algo : 0; */
/****************
* Protect the secret key with the passphrase from DEK
*/
int
protect_secret_key( PKT_secret_key *sk, DEK *dek )
{
int i,j, rc = 0;
byte *buffer;
size_t nbytes;
u16 csum;
if( !dek )
return 0;
if( !sk->is_protected ) { /* okay, apply the protection */
gcry_cipher_hd_t cipher_hd=NULL;
if ( openpgp_cipher_test_algo ( sk->protect.algo ) ) {
/* Unsupport protection algorithm. */
rc = gpg_error (GPG_ERR_CIPHER_ALGO);
}
else {
print_cipher_algo_note( sk->protect.algo );
if ( openpgp_cipher_open (&cipher_hd, sk->protect.algo,
GCRY_CIPHER_MODE_CFB,
(GCRY_CIPHER_SECURE
| (sk->protect.algo >= 100 ?
0 : GCRY_CIPHER_ENABLE_SYNC))) )
BUG();
if ( gcry_cipher_setkey ( cipher_hd, dek->key, dek->keylen ) )
log_info(_("WARNING: Weak key detected"
" - please change passphrase again.\n"));
sk->protect.ivlen = openpgp_cipher_get_algo_blklen (sk->protect.algo);
assert( sk->protect.ivlen <= DIM(sk->protect.iv) );
if( sk->protect.ivlen != 8 && sk->protect.ivlen != 16 )
BUG(); /* yes, we are very careful */
gcry_create_nonce (sk->protect.iv, sk->protect.ivlen);
gcry_cipher_setiv (cipher_hd, sk->protect.iv, sk->protect.ivlen);
if( sk->version >= 4 ) {
byte *bufarr[PUBKEY_MAX_NSKEY];
size_t narr[PUBKEY_MAX_NSKEY];
unsigned int nbits[PUBKEY_MAX_NSKEY];
int ndata=0;
byte *p, *data;
for (j=0, i = pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ )
{
assert (!gcry_mpi_get_flag (sk->skey[i],
GCRYMPI_FLAG_OPAQUE));
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, bufarr+j,
narr+j, sk->skey[i]))
BUG();
nbits[j] = gcry_mpi_get_nbits (sk->skey[i]);
ndata += narr[j] + 2;
}
for ( ; j < PUBKEY_MAX_NSKEY; j++ )
bufarr[j] = NULL;
ndata += opt.simple_sk_checksum? 2 : 20; /* for checksum */
data = xmalloc_secure( ndata );
p = data;
for(j=0; j < PUBKEY_MAX_NSKEY && bufarr[j]; j++ ) {
p[0] = nbits[j] >> 8 ;
p[1] = nbits[j];
p += 2;
memcpy(p, bufarr[j], narr[j] );
p += narr[j];
xfree(bufarr[j]);
}
if (opt.simple_sk_checksum) {
log_info (_("generating the deprecated 16-bit checksum"
" for secret key protection\n"));
csum = checksum( data, ndata-2);
sk->csum = csum;
*p++ = csum >> 8;
*p++ = csum;
sk->protect.sha1chk = 0;
}
else {
gcry_md_hd_t h;
if (gcry_md_open (&h, GCRY_MD_SHA1, 1))
BUG(); /* Algo not available. */
gcry_md_write (h, data, ndata - 20);
gcry_md_final (h);
memcpy (p, gcry_md_read (h, DIGEST_ALGO_SHA1), 20);
p += 20;
gcry_md_close (h);
sk->csum = csum = 0;
sk->protect.sha1chk = 1;
}
assert( p == data+ndata );
gcry_cipher_encrypt (cipher_hd, data, ndata, NULL, 0);
for (i = pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ )
{
gcry_mpi_release (sk->skey[i]);
sk->skey[i] = NULL;
}
i = pubkey_get_npkey(sk->pubkey_algo);
sk->skey[i] = gcry_mpi_set_opaque (NULL, data, ndata*8 );
}
else {
csum = 0;
for(i=pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
byte *data;
unsigned int nbits;
csum += checksum_mpi (sk->skey[i]);
if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &buffer,
&nbytes, sk->skey[i] ))
BUG();
gcry_cipher_sync (cipher_hd);
assert (!gcry_mpi_get_flag (sk->skey[i],
GCRYMPI_FLAG_OPAQUE));
data = xmalloc (nbytes+2); /* fixme: need xtrymalloc. */
nbits = gcry_mpi_get_nbits (sk->skey[i]);
assert (nbytes == (nbits + 7)/8);
data[0] = nbits >> 8;
data[1] = nbits;
gcry_cipher_encrypt (cipher_hd, data+2, nbytes,
buffer, nbytes);
xfree( buffer );
gcry_mpi_release (sk->skey[i]);
sk->skey[i] = gcry_mpi_set_opaque (NULL,
data, (nbytes+2)*8 );
}
sk->csum = csum;
}
sk->is_protected = 1;
gcry_cipher_close (cipher_hd);
}
}
return rc;
} }

View File

@ -206,19 +206,18 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits,
* bits. * bits.
*/ */
gcry_mpi_t gcry_mpi_t
encode_md_value (PKT_public_key *pk, PKT_secret_key *sk, encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo)
gcry_md_hd_t md, int hash_algo)
{ {
gcry_mpi_t frame; gcry_mpi_t frame;
assert(hash_algo); assert (hash_algo);
assert(pk || sk); assert (pk);
if((pk?pk->pubkey_algo:sk->pubkey_algo) == GCRY_PK_DSA) if (pk->pubkey_algo == GCRY_PK_DSA)
{ {
/* It's a DSA signature, so find out the size of q. */ /* It's a DSA signature, so find out the size of q. */
size_t qbytes = gcry_mpi_get_nbits (pk?pk->pkey[1]:sk->skey[1]); size_t qbytes = gcry_mpi_get_nbits (pk->pkey[1]);
/* Make sure it is a multiple of 8 bits. */ /* Make sure it is a multiple of 8 bits. */
@ -237,21 +236,19 @@ encode_md_value (PKT_public_key *pk, PKT_secret_key *sk,
DSA. ;) */ DSA. ;) */
if (qbytes < 160) if (qbytes < 160)
{ {
log_error (_("DSA key %s uses an unsafe (%u bit) hash\n"), log_error (_("DSA key %s uses an unsafe (%zu bit) hash\n"),
pk?keystr_from_pk(pk):keystr_from_sk(sk), keystr_from_pk (pk), qbytes);
(unsigned int)qbytes);
return NULL; return NULL;
} }
qbytes/=8; qbytes /= 8;
/* Check if we're too short. Too long is safe as we'll /* Check if we're too short. Too long is safe as we'll
automatically left-truncate. */ automatically left-truncate. */
if (gcry_md_get_algo_dlen (hash_algo) < qbytes) if (gcry_md_get_algo_dlen (hash_algo) < qbytes)
{ {
log_error (_("DSA key %s requires a %u bit or larger hash\n"), log_error (_("DSA key %s requires a %zu bit or larger hash\n"),
pk?keystr_from_pk(pk):keystr_from_sk(sk), keystr_from_pk(pk), qbytes*8);
(unsigned int)(qbytes*8));
return NULL; return NULL;
} }
@ -269,12 +266,13 @@ encode_md_value (PKT_public_key *pk, PKT_secret_key *sk,
if (rc) if (rc)
log_fatal ("can't get OID of digest algorithm %d: %s\n", log_fatal ("can't get OID of digest algorithm %d: %s\n",
hash_algo, gpg_strerror (rc)); hash_algo, gpg_strerror (rc));
asn = xmalloc (asnlen); asn = xtrymalloc (asnlen);
if (!asn)
return NULL;
if ( gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, asn, &asnlen) ) if ( gcry_md_algo_info (hash_algo, GCRYCTL_GET_ASNOID, asn, &asnlen) )
BUG(); BUG();
frame = do_encode_md (md, hash_algo, gcry_md_get_algo_dlen (hash_algo), frame = do_encode_md (md, hash_algo, gcry_md_get_algo_dlen (hash_algo),
gcry_mpi_get_nbits (pk?pk->pkey[0]:sk->skey[0]), gcry_mpi_get_nbits (pk->pkey[0]), asn, asnlen);
asn, asnlen);
xfree (asn); xfree (asn);
} }

View File

@ -315,7 +315,7 @@ do_check( PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest,
} }
gcry_md_final( digest ); gcry_md_final( digest );
result = encode_md_value( pk, NULL, digest, sig->digest_algo ); result = encode_md_value (pk, digest, sig->digest_algo );
if (!result) if (!result)
return G10ERR_GENERAL; return G10ERR_GENERAL;
ctx.sig = sig; ctx.sig = sig;

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 static int
do_sign (PKT_public_key *pksk, PKT_signature *sig, do_sign (PKT_public_key *pksk, PKT_signature *sig,
gcry_md_hd_t md, int digest_algo) gcry_md_hd_t md, int mdalgo)
{ {
gcry_mpi_t frame; gpg_error_t err;
byte *dp; gcry_mpi_t frame;
int rc; byte *dp;
if (pksk->timestamp > sig->timestamp ) { if (pksk->timestamp > sig->timestamp )
ulong d = pksk->timestamp - sig->timestamp; {
log_info( d==1 ? _("key has been created %lu second " ulong d = pksk->timestamp - sig->timestamp;
"in future (time warp or clock problem)\n") log_info (d==1 ? _("key has been created %lu second "
: _("key has been created %lu seconds " "in future (time warp or clock problem)\n")
"in future (time warp or clock problem)\n"), d ); : _("key has been created %lu seconds "
if( !opt.ignore_time_conflict ) "in future (time warp or clock problem)\n"), d );
return G10ERR_TIME_CONFLICT; 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 ) print_digest_algo_note (mdalgo);
digest_algo = gcry_md_get_algo (md); 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 ); #warning fixme: Use the agent for the card
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. */
/* if (pksk->is_protected && pksk->protect.s2k.mode == 1002) */ /* if (pksk->is_protected && pksk->protect.s2k.mode == 1002) */
/* { */ /* { */
/* #ifdef ENABLE_CARD_SUPPORT */ /* #ifdef ENABLE_CARD_SUPPORT */
@ -285,57 +303,89 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
/* #endif /\* ENABLE_CARD_SUPPORT *\/ */ /* #endif /\* ENABLE_CARD_SUPPORT *\/ */
/* } */ /* } */
/* else */ /* else */
{ if (1)
frame = encode_md_value (NULL, pksk, md, digest_algo ); {
if (!frame) char *hexgrip;
return G10ERR_GENERAL;
rc = pk_sign (pksk->pubkey_algo, sig->data, frame, pksk->pkey ); err = hexkeygrip_from_pk (pksk, &hexgrip);
gcry_mpi_release (frame); if (!err)
} {
char *desc;
if (!rc && !opt.no_sig_create_check) { gcry_sexp_t s_sigval;
/* Check that the signature verification worked and nothing is
* fooling us e.g. by a bug in the signature create /* FIXME: desc = gpgsm_format_keydesc (cert); */
* code or by deliberately introduced faults. */ desc = xtrystrdup ("FIXME: Format a decription");
PKT_public_key *pk = xmalloc_clear (sizeof *pk);
err = agent_pksign (NULL/*ctrl*/, hexgrip, desc,
if( get_pubkey( pk, sig->keyid ) ) dp, gcry_md_get_algo_dlen (mdalgo), mdalgo,
rc = G10ERR_NO_PUBKEY; &s_sigval);
else {
frame = encode_md_value (pk, NULL, md, sig->digest_algo ); xfree (desc);
if (!frame)
rc = G10ERR_GENERAL; if (err)
else ;
rc = pk_verify (pk->pubkey_algo, frame, sig->data, pk->pkey ); else if (pksk->pubkey_algo == GCRY_PK_RSA
gcry_mpi_release (frame); || 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) xfree (hexgrip);
log_error (_("checking created signature failed: %s\n"),
g10_errstr (rc));
free_public_key (pk);
} }
if( rc )
log_error(_("signing failed: %s\n"), g10_errstr(rc) ); /* Check that the signature verification worked and nothing is
else { * fooling us e.g. by a bug in the signature create code or by
if( opt.verbose ) { * deliberately introduced faults. */
char *ustr = get_user_id_string_native (sig->keyid); if (!err && !opt.no_sig_create_check)
log_info(_("%s/%s signature from: \"%s\"\n"), {
gcry_pk_algo_name (pksk->pubkey_algo), PKT_public_key *pk = xmalloc_clear (sizeof *pk);
gcry_md_algo_name (sig->digest_algo),
ustr ); if (get_pubkey (pk, sig->keyid ))
xfree(ustr); 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 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; int rc;
if (!(rc = check_secret_key (pksk, 0))) /* if (!(rc = check_secret_key (pksk, 0))) */
rc = do_sign (pksk, sig, md, 0); rc = do_sign (pksk, sig, md, 0);
return rc; return rc;
} }