1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-05-14 08:13:25 +02:00

Removed more secret key related code.

It builds fine and passes some of the tests but there are quite some
features which don't work yet.
This commit is contained in:
Werner Koch 2010-09-06 19:57:42 +00:00
parent daab9aff3a
commit 299ed4c9e2
20 changed files with 1307 additions and 1946 deletions

View File

@ -1,3 +1,53 @@
2010-09-06 Werner Koch <wk@g10code.com>
* card-util.c (card_status): Remove stub creation fro GnuPG >= 2.
(card_store_subkey): Temporary disable this code.
* keyedit.c (show_key_with_all_names): Merge secret and public key
parts.
(show_basic_key_info): Ditto.
* delkey.c (do_delete_key): Ditto.
* export.c (subkey_in_list_p, exact_subkey_match_p): Ditto.
(new_subkey_list_item): Ditto.
* keyid.c (keystr_from_sk, keystr_from_sk_with_sub)
(keyid_from_sk, nbits_from_sk, datestr_from_sk)
(expirestr_from_sk, colon_datestr_from_sk, fingerprint_from_sk)
(serialno_and_fpr_from_sk, do_fingerprint_md_sk): Remove.
* import.c (print_import_ok): Remove arg SK.
(import_secret_one): Adjust for seckey_info format.
(transfer_secret_keys): Ditto. Use gpg_format_keydesc.
(sec_to_pub_keyblock): Simplify.
(pub_to_sec_keyblock): Remove.
(auto_create_card_key_stub): Remove - not anymore needed.
(update_sec_keyblock_with_cardinfo): Remove.
(import_secret_one): Use arg option instead of the global option.
* free-packet.c (copy_public_key): Adjust for seckey_info format.
(copy_public_parts_to_secret_key, copy_secret_key)
(cmp_secret_keys, cmp_public_secret_key): Remove.
* passphrase.c (gpg_format_keydesc): Add arg MODE and change all
callers.
* keyring.c (keyring_search): Remove special case for secret keys.
* mainproc.c (struct mainproc_context): Remove unused field
LAST_SECKEY.
* parse-packet.c (parse_key): Rewrite to cope with new seckey_info
format.
* build-packet.c (do_public_key, do_secret_key): Merge code into ...
(do_key): .. new. Cope with seckey_info format.
2010-09-03 Werner Koch <wk@g10code.com>
* packet.h (struct seckey_info): New.
(PKT_public_key): Increase size of PKEY to allow storing of secret
keys. Add field SECKEY_INFO.
(PKT_secret_key): Remove.
* free-packet.c (release_public_key_parts): Take care of change.
(release_secret_key_parts, free_secret_key): Remove.
2010-09-02 Werner Koch <wk@g10code.com> 2010-09-02 Werner Koch <wk@g10code.com>
* import.c (transfer_secret_keys, import_secret_one): Enable stats. * import.c (transfer_secret_keys, import_secret_one): Enable stats.

View File

@ -1,6 +1,6 @@
/* build-packet.c - assemble packets and write them /* build-packet.c - assemble packets and write them
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
* 2006 Free Software Foundation, Inc. * 2006, 2010 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -35,8 +35,7 @@
#include "options.h" #include "options.h"
static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid ); static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid );
static int do_public_key( IOBUF out, int ctb, PKT_public_key *pk ); static int do_key (iobuf_t out, int ctb, PKT_public_key *pk);
static int do_secret_key( IOBUF out, int ctb, PKT_secret_key *pk );
static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc ); static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc );
static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ); static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc );
static u32 calc_plaintext( PKT_plaintext *pt ); static u32 calc_plaintext( PKT_plaintext *pt );
@ -107,11 +106,9 @@ build_packet( IOBUF out, PACKET *pkt )
break; break;
case PKT_PUBLIC_SUBKEY: case PKT_PUBLIC_SUBKEY:
case PKT_PUBLIC_KEY: case PKT_PUBLIC_KEY:
rc = do_public_key( out, ctb, pkt->pkt.public_key );
break;
case PKT_SECRET_SUBKEY: case PKT_SECRET_SUBKEY:
case PKT_SECRET_KEY: case PKT_SECRET_KEY:
rc = do_secret_key( out, ctb, pkt->pkt.secret_key ); rc = do_key (out, ctb, pkt->pkt.public_key);
break; break;
case PKT_SYMKEY_ENC: case PKT_SYMKEY_ENC:
rc = do_symkey_enc( out, ctb, pkt->pkt.symkey_enc ); rc = do_symkey_enc( out, ctb, pkt->pkt.symkey_enc );
@ -242,18 +239,22 @@ do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
return 0; return 0;
} }
static int
do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
{
int rc = 0;
int n, i;
IOBUF a = iobuf_temp();
static int
do_key (iobuf_t out, int ctb, PKT_public_key *pk)
{
gpg_error_t err = 0;
int i, nskey, npkey;
iobuf_t a = iobuf_temp(); /* Build in a self-enlarging buffer. */
/* Write the version number - if none is specified, use 3 */
if ( !pk->version ) if ( !pk->version )
iobuf_put( a, 3 ); iobuf_put ( a, 3 );
else else
iobuf_put( a, pk->version ); iobuf_put ( a, pk->version );
write_32(a, pk->timestamp ); write_32 (a, pk->timestamp );
/* v3 needs the expiration time. */
if ( pk->version < 4 ) if ( pk->version < 4 )
{ {
u16 ndays; u16 ndays;
@ -261,144 +262,103 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L); ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L);
else else
ndays = 0; ndays = 0;
write_16(a, ndays );
}
iobuf_put (a, pk->pubkey_algo );
n = pubkey_get_npkey ( pk->pubkey_algo );
if ( !n )
write_fake_data( a, pk->pkey[0] );
for (i=0; i < n && !rc ; i++ )
rc = mpi_write(a, pk->pkey[i] );
if (!rc)
{
write_header2 (out, ctb, iobuf_get_temp_length(a), pk->hdrbytes);
rc = iobuf_write_temp ( out, a );
}
iobuf_close(a);
return rc;
}
static int
do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
{
int rc = 0;
int i, nskey, npkey;
IOBUF a = iobuf_temp(); /* Build in a self-enlarging buffer. */
/* Write the version number - if none is specified, use 3 */
if ( !sk->version )
iobuf_put ( a, 3 );
else
iobuf_put ( a, sk->version );
write_32 (a, sk->timestamp );
/* v3 needs the expiration time. */
if ( sk->version < 4 )
{
u16 ndays;
if ( sk->expiredate )
ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L);
else
ndays = 0;
write_16(a, ndays); write_16(a, ndays);
} }
iobuf_put (a, sk->pubkey_algo ); iobuf_put (a, pk->pubkey_algo );
/* Get number of secret and public parameters. They are held in one /* Get number of secret and public parameters. They are held in one
array first the public ones, then the secret ones. */ array first the public ones, then the secret ones. */
nskey = pubkey_get_nskey ( sk->pubkey_algo ); nskey = pubkey_get_nskey (pk->pubkey_algo);
npkey = pubkey_get_npkey ( sk->pubkey_algo ); npkey = pubkey_get_npkey (pk->pubkey_algo);
/* If we don't have any public parameters - which is the case if we /* If we don't have any public parameters - which is the case if we
don't know the algorithm used - the parameters are stored as one don't know the algorithm used - the parameters are stored as one
blob in a faked (opaque) MPI. */ blob in a faked (opaque) MPI. */
if ( !npkey ) if (!npkey)
{ {
write_fake_data( a, sk->skey[0] ); write_fake_data (a, pk->pkey[0]);
goto leave; goto leave;
} }
assert ( npkey < nskey ); assert (npkey < nskey);
/* Writing the public parameters is easy. */ /* Writing the public parameters is easy. */
for (i=0; i < npkey; i++ ) for (i=0; i < npkey; i++ )
if ((rc = mpi_write (a, sk->skey[i]))) if ((err = mpi_write (a, pk->pkey[i])))
goto leave; goto leave;
/* Build the header for protected (encrypted) secret parameters. */ if (pk->seckey_info)
if ( sk->is_protected )
{ {
if ( is_RSA(sk->pubkey_algo) /* This is a secret key packet. */
&& sk->version < 4 struct seckey_info *ski = pk->seckey_info;
&& !sk->protect.s2k.mode )
/* Build the header for protected (encrypted) secret parameters. */
if (ski->is_protected)
{
if ( is_RSA (pk->pubkey_algo) && pk->version < 4 && !ski->s2k.mode )
{ {
/* The simple rfc1991 (v3) way. */ /* The simple rfc1991 (v3) way. */
iobuf_put (a, sk->protect.algo ); iobuf_put (a, ski->algo );
iobuf_write (a, sk->protect.iv, sk->protect.ivlen ); iobuf_write (a, ski->iv, ski->ivlen);
} }
else else
{ {
/* OpenPGP protection according to rfc2440. */ /* OpenPGP protection according to rfc2440. */
iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff ); iobuf_put (a, ski->sha1chk? 0xfe : 0xff);
iobuf_put(a, sk->protect.algo ); iobuf_put (a, ski->algo);
if ( sk->protect.s2k.mode >= 1000 ) if (ski->s2k.mode >= 1000)
{ {
/* These modes are not possible in OpenPGP, we use them /* These modes are not possible in OpenPGP, we use
to implement our extensions, 101 can be seen as a them to implement our extensions, 101 can be
private/experimental extension (this is not specified viewed as a private/experimental extension (this
in rfc2440 but the same scheme is used for all other is not specified in rfc2440 but the same scheme
algorithm identifiers) */ is used for all other algorithm identifiers). */
iobuf_put(a, 101 ); iobuf_put (a, 101);
iobuf_put(a, sk->protect.s2k.hash_algo ); iobuf_put (a, ski->s2k.hash_algo);
iobuf_write(a, "GNU", 3 ); iobuf_write (a, "GNU", 3 );
iobuf_put(a, sk->protect.s2k.mode - 1000 ); iobuf_put (a, ski->s2k.mode - 1000);
} }
else else
{ {
iobuf_put(a, sk->protect.s2k.mode ); iobuf_put (a, ski->s2k.mode);
iobuf_put(a, sk->protect.s2k.hash_algo ); iobuf_put (a, ski->s2k.hash_algo);
} }
if ( sk->protect.s2k.mode == 1
|| sk->protect.s2k.mode == 3 )
iobuf_write (a, sk->protect.s2k.salt, 8 );
if ( sk->protect.s2k.mode == 3 ) if (ski->s2k.mode == 1 || ski->s2k.mode == 3)
iobuf_put (a, sk->protect.s2k.count ); iobuf_write (a, ski->s2k.salt, 8);
if (ski->s2k.mode == 3)
iobuf_put (a, ski->s2k.count);
/* For our special modes 1001, 1002 we do not need an IV. */ /* For our special modes 1001, 1002 we do not need an IV. */
if ( sk->protect.s2k.mode != 1001 if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002)
&& sk->protect.s2k.mode != 1002 ) iobuf_write (a, ski->iv, ski->ivlen);
iobuf_write (a, sk->protect.iv, sk->protect.ivlen );
} }
} }
else else /* Not protected. */
iobuf_put (a, 0 ); iobuf_put (a, 0 );
if ( sk->protect.s2k.mode == 1001 ) if (ski->s2k.mode == 1001)
; /* GnuPG extension - don't write a secret key at all. */ ; /* GnuPG extension - don't write a secret key at all. */
else if ( sk->protect.s2k.mode == 1002 ) else if (ski->s2k.mode == 1002)
{ {
/* GnuPG extension - divert to OpenPGP smartcard. */ /* GnuPG extension - divert to OpenPGP smartcard. */
iobuf_put(a, sk->protect.ivlen ); /* Length of the serial number /* Length of the serial number or 0 for no serial number. */
or 0 for no serial iobuf_put (a, ski->ivlen );
number. */
/* The serial number gets stored in the IV field. */ /* The serial number gets stored in the IV field. */
iobuf_write(a, sk->protect.iv, sk->protect.ivlen); iobuf_write (a, ski->iv, ski->ivlen);
} }
else if ( sk->is_protected && sk->version >= 4 ) else if (ski->is_protected && pk->version >= 4)
{ {
/* The secret key is protected - write it out as it is. */ /* The secret key is protected - write it out as it is. */
byte *p; byte *p;
unsigned int ndatabits; unsigned int ndatabits;
assert (gcry_mpi_get_flag (sk->skey[npkey], GCRYMPI_FLAG_OPAQUE)); assert (gcry_mpi_get_flag (pk->pkey[npkey], GCRYMPI_FLAG_OPAQUE));
p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits ); p = gcry_mpi_get_opaque (pk->pkey[npkey], &ndatabits);
iobuf_write (a, p, (ndatabits+7)/8 ); iobuf_write (a, p, (ndatabits+7)/8 );
} }
else if ( sk->is_protected ) else if (ski->is_protected)
{ {
/* The secret key is protected the old v4 way. */ /* The secret key is protected the old v4 way. */
for ( ; i < nskey; i++ ) for ( ; i < nskey; i++ )
@ -406,34 +366,35 @@ do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
byte *p; byte *p;
unsigned int ndatabits; unsigned int ndatabits;
assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)); assert (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE));
p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits); p = gcry_mpi_get_opaque (pk->pkey[i], &ndatabits);
iobuf_write (a, p, (ndatabits+7)/8); iobuf_write (a, p, (ndatabits+7)/8);
} }
write_16(a, sk->csum ); write_16 (a, ski->csum );
} }
else else
{ {
/* Non-protected key. */ /* Non-protected key. */
for ( ; i < nskey; i++ ) for ( ; i < nskey; i++ )
if ( (rc = mpi_write (a, sk->skey[i]))) if ( (err = mpi_write (a, pk->pkey[i])))
goto leave; goto leave;
write_16 (a, sk->csum ); write_16 (a, ski->csum );
}
} }
leave: leave:
if (!rc) if (!err)
{ {
/* Build the header of the packet - which we must do after /* Build the header of the packet - which we must do after
writing all the other stuff, so that we know the length of writing all the other stuff, so that we know the length of
the packet */ the packet */
write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes); write_header2 (out, ctb, iobuf_get_temp_length(a), pk->hdrbytes);
/* And finally write it out the real stream */ /* And finally write it out to the real stream. */
rc = iobuf_write_temp( out, a ); err = iobuf_write_temp (out, a);
} }
iobuf_close(a); /* Close the remporary buffer */ iobuf_close (a); /* Close the temporary buffer */
return rc; return err;
} }
static int static int

View File

@ -207,6 +207,9 @@ get_manufacturer (unsigned int no)
case 0x0005: return "ZeitControl"; case 0x0005: return "ZeitControl";
case 0x002A: return "Magrathea"; case 0x002A: return "Magrathea";
case 0xF517: return "FSIJ";
/* 0x00000 and 0xFFFF are defined as test cards per spec, /* 0x00000 and 0xFFFF are defined as test cards per spec,
0xFFF00 to 0xFFFE are assigned for use with randomly created 0xFFF00 to 0xFFFE are assigned for use with randomly created
serial numbers. */ serial numbers. */
@ -581,6 +584,7 @@ card_status (estream_t fp, char *serialno, size_t serialnobuflen)
print_pubkey_info (fp, pk); print_pubkey_info (fp, pk);
#if GNUPG_MAJOR_VERSION == 1
if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) ) if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) )
print_card_key_info (fp, keyblock); print_card_key_info (fp, keyblock);
else if ( !get_keyblock_byfprint (&keyblock, thefpr, 20) ) else if ( !get_keyblock_byfprint (&keyblock, thefpr, 20) )
@ -599,6 +603,7 @@ card_status (estream_t fp, char *serialno, size_t serialnobuflen)
} }
release_kbnode (keyblock); release_kbnode (keyblock);
#endif /* GNUPG_MAJOR_VERSION == 1 */
} }
else else
tty_fprintf (fp, "[none]\n"); tty_fprintf (fp, "[none]\n");
@ -1514,150 +1519,151 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
int int
card_store_subkey (KBNODE node, int use) card_store_subkey (KBNODE node, int use)
{ {
struct agent_card_info_s info; /* struct agent_card_info_s info; */
int okay = 0; /* int okay = 0; */
int rc; /* int rc; */
int keyno, i; /* int keyno, i; */
PKT_secret_key *copied_sk = NULL; /* PKT_secret_key *copied_sk = NULL; */
PKT_secret_key *sk; /* PKT_secret_key *sk; */
size_t n; /* size_t n; */
const char *s; /* const char *s; */
int allow_keyno[3]; /* int allow_keyno[3]; */
unsigned int nbits; /* unsigned int nbits; */
assert (node->pkt->pkttype == PKT_SECRET_KEY /* assert (node->pkt->pkttype == PKT_SECRET_KEY */
|| node->pkt->pkttype == PKT_SECRET_SUBKEY); /* || node->pkt->pkttype == PKT_SECRET_SUBKEY); */
sk = node->pkt->pkt.secret_key; /* sk = node->pkt->pkt.secret_key; */
if (get_info_for_key_operation (&info)) /* if (get_info_for_key_operation (&info)) */
return 0; /* return 0; */
if (!info.extcap.ki) /* if (!info.extcap.ki) */
{ /* { */
tty_printf ("The card does not support the import of keys\n"); /* tty_printf ("The card does not support the import of keys\n"); */
tty_printf ("\n"); /* tty_printf ("\n"); */
goto leave; /* goto leave; */
} /* } */
show_card_key_info (&info); /* show_card_key_info (&info); */
nbits = nbits_from_sk (sk); /* nbits = nbits_from_sk (sk); */
if (!is_RSA (sk->pubkey_algo) || (!info.is_v2 && nbits != 1024) ) /* if (!is_RSA (sk->pubkey_algo) || (!info.is_v2 && nbits != 1024) ) */
{ /* { */
tty_printf ("You may only store a 1024 bit RSA key on the card\n"); /* tty_printf ("You may only store a 1024 bit RSA key on the card\n"); */
tty_printf ("\n"); /* tty_printf ("\n"); */
goto leave; /* goto leave; */
} /* } */
allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG))); /* allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG))); */
allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC))); /* allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC))); */
allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH))); /* allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH))); */
tty_printf (_("Please select where to store the key:\n")); /* tty_printf (_("Please select where to store the key:\n")); */
if (allow_keyno[0]) /* if (allow_keyno[0]) */
tty_printf (_(" (1) Signature key\n")); /* tty_printf (_(" (1) Signature key\n")); */
if (allow_keyno[1]) /* if (allow_keyno[1]) */
tty_printf (_(" (2) Encryption key\n")); /* tty_printf (_(" (2) Encryption key\n")); */
if (allow_keyno[2]) /* if (allow_keyno[2]) */
tty_printf (_(" (3) Authentication key\n")); /* tty_printf (_(" (3) Authentication key\n")); */
for (;;) /* for (;;) */
{ /* { */
char *answer = cpr_get ("cardedit.genkeys.storekeytype", /* char *answer = cpr_get ("cardedit.genkeys.storekeytype", */
_("Your selection? ")); /* _("Your selection? ")); */
cpr_kill_prompt(); /* cpr_kill_prompt(); */
if (*answer == CONTROL_D || !*answer) /* if (*answer == CONTROL_D || !*answer) */
{ /* { */
xfree (answer); /* xfree (answer); */
goto leave; /* goto leave; */
} /* } */
keyno = *answer? atoi(answer): 0; /* keyno = *answer? atoi(answer): 0; */
xfree(answer); /* xfree(answer); */
if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1]) /* if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1]) */
{ /* { */
if (info.is_v2 && !info.extcap.aac /* if (info.is_v2 && !info.extcap.aac */
&& info.key_attr[keyno-1].nbits != nbits) /* && info.key_attr[keyno-1].nbits != nbits) */
{ /* { */
tty_printf ("Key does not match the card's capability.\n"); /* tty_printf ("Key does not match the card's capability.\n"); */
} /* } */
else /* else */
break; /* Okay. */ /* break; /\* Okay. *\/ */
} /* } */
else /* else */
tty_printf(_("Invalid selection.\n")); /* tty_printf(_("Invalid selection.\n")); */
} /* } */
if (replace_existing_key_p (&info, keyno)) /* if (replace_existing_key_p (&info, keyno)) */
goto leave; /* goto leave; */
/* Unprotect key. */ /* /\* Unprotect key. *\/ */
switch (is_secret_key_protected (sk) ) /* switch (is_secret_key_protected (sk) ) */
{ /* { */
case 0: /* Not protected. */ /* case 0: /\* Not protected. *\/ */
break; /* break; */
case -1: /* case -1: */
log_error (_("unknown key protection algorithm\n")); /* log_error (_("unknown key protection algorithm\n")); */
goto leave; /* goto leave; */
default: /* default: */
if (sk->protect.s2k.mode == 1001) /* if (sk->protect.s2k.mode == 1001) */
{ /* { */
log_error (_("secret parts of key are not available\n")); /* log_error (_("secret parts of key are not available\n")); */
goto leave; /* goto leave; */
} /* } */
if (sk->protect.s2k.mode == 1002) /* if (sk->protect.s2k.mode == 1002) */
{ /* { */
log_error (_("secret key already stored on a card\n")); /* log_error (_("secret key already stored on a card\n")); */
goto leave; /* goto leave; */
} /* } */
/* 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 = 0/*check_secret_key (sk, 0)*/; /* rc = 0/\*check_secret_key (sk, 0)*\/; */
if (rc) /* if (rc) */
goto leave; /* goto leave; */
} /* } */
#warning code save_unprotected_key_to_card /* #warning code save_unprotected_key_to_card */
/* rc = save_unprotected_key_to_card (sk, keyno); */ /* /\* rc = save_unprotected_key_to_card (sk, keyno); *\/ */
/* if (rc) */ /* /\* if (rc) *\/ */
/* { */ /* /\* { *\/ */
/* log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); */ /* /\* log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); *\/ */
/* goto leave; */ /* /\* 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) */
{ /* { */
free_secret_key (copied_sk); /* free_secret_key (copied_sk); */
copied_sk = NULL; /* copied_sk = NULL; */
} /* } */
sk = node->pkt->pkt.secret_key; /* sk = node->pkt->pkt.secret_key; */
/* Get rid of the secret key parameters and store the serial numer. */ /* /\* Get rid of the secret key parameters and store the serial numer. *\/ */
n = pubkey_get_nskey (sk->pubkey_algo); /* n = pubkey_get_nskey (sk->pubkey_algo); */
for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++) /* for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++) */
{ /* { */
gcry_mpi_release (sk->skey[i]); /* gcry_mpi_release (sk->skey[i]); */
sk->skey[i] = NULL; /* sk->skey[i] = NULL; */
} /* } */
i = pubkey_get_npkey (sk->pubkey_algo); /* i = pubkey_get_npkey (sk->pubkey_algo); */
sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); /* sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); */
sk->is_protected = 1; /* sk->is_protected = 1; */
sk->protect.s2k.mode = 1002; /* sk->protect.s2k.mode = 1002; */
s = info.serialno; /* s = info.serialno; */
for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; /* for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; */
sk->protect.ivlen++, s += 2) /* sk->protect.ivlen++, s += 2) */
sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); /* sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); */
okay = 1; /* okay = 1; */
leave: /* leave: */
if (copied_sk) /* if (copied_sk) */
free_secret_key (copied_sk); /* free_secret_key (copied_sk); */
agent_release_card_info (&info); /* agent_release_card_info (&info); */
return okay; /* return okay; */
return -1;
} }

View File

@ -54,7 +54,6 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
KBNODE node; KBNODE node;
KEYDB_HANDLE hd = keydb_new (); KEYDB_HANDLE hd = keydb_new ();
PKT_public_key *pk = NULL; PKT_public_key *pk = NULL;
PKT_secret_key *sk = NULL;
u32 keyid[2]; u32 keyid[2];
int okay=0; int okay=0;
int yes; int yes;
@ -91,18 +90,10 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
goto leave; goto leave;
} }
if( secret )
{
sk = node->pkt->pkt.secret_key;
keyid_from_sk( sk, keyid );
}
else
{
/* public */
pk = node->pkt->pkt.public_key; pk = node->pkt->pkt.public_key;
keyid_from_pk( pk, keyid ); keyid_from_pk( pk, keyid );
if(!force) if (!force)
{ {
if (have_secret_key_with_kid (keyid)) if (have_secret_key_with_kid (keyid))
{ {
@ -113,7 +104,6 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
else else
rc = 0; rc = 0;
} }
}
if( rc ) if( rc )
rc = 0; rc = 0;
@ -133,9 +123,9 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
} }
else { else {
if( secret ) if( secret )
print_seckey_info( sk ); print_seckey_info (pk);
else else
print_pubkey_info(NULL, pk ); print_pubkey_info (NULL, pk );
tty_printf( "\n" ); tty_printf( "\n" );
yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay" yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay"

View File

@ -190,10 +190,7 @@ subkey_in_list_p (subkey_list_t list, KBNODE node)
{ {
u32 kid[2]; u32 kid[2];
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
keyid_from_pk (node->pkt->pkt.public_key, kid); keyid_from_pk (node->pkt->pkt.public_key, kid);
else
keyid_from_sk (node->pkt->pkt.secret_key, kid);
for (; list; list = list->next) for (; list; list = list->next)
if (list->kid[0] == kid[0] && list->kid[1] == kid[1]) if (list->kid[0] == kid[0] && list->kid[1] == kid[1])
@ -208,10 +205,9 @@ new_subkey_list_item (KBNODE node)
{ {
subkey_list_t list = xcalloc (1, sizeof *list); subkey_list_t list = xcalloc (1, sizeof *list);
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY)
keyid_from_pk (node->pkt->pkt.public_key, list->kid); keyid_from_pk (node->pkt->pkt.public_key, list->kid);
else if (node->pkt->pkttype == PKT_SECRET_SUBKEY)
keyid_from_sk (node->pkt->pkt.secret_key, list->kid);
return list; return list;
} }
@ -235,19 +231,13 @@ exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
{ {
case KEYDB_SEARCH_MODE_SHORT_KID: case KEYDB_SEARCH_MODE_SHORT_KID:
case KEYDB_SEARCH_MODE_LONG_KID: case KEYDB_SEARCH_MODE_LONG_KID:
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
keyid_from_pk (node->pkt->pkt.public_key, kid); keyid_from_pk (node->pkt->pkt.public_key, kid);
else
keyid_from_sk (node->pkt->pkt.secret_key, kid);
break; break;
case KEYDB_SEARCH_MODE_FPR16: case KEYDB_SEARCH_MODE_FPR16:
case KEYDB_SEARCH_MODE_FPR20: case KEYDB_SEARCH_MODE_FPR20:
case KEYDB_SEARCH_MODE_FPR: case KEYDB_SEARCH_MODE_FPR:
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen); fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
else
fingerprint_from_sk (node->pkt->pkt.secret_key, fpr,&fprlen);
break; break;
default: default:
@ -289,36 +279,38 @@ exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
contains a pointer to the first keyblock found and exported. No contains a pointer to the first keyblock found and exported. No
other keyblocks are exported. The caller must free it. */ other keyblocks are exported. The caller must free it. */
static int static int
do_export_stream( IOBUF out, strlist_t users, int secret, do_export_stream (iobuf_t out, strlist_t users, int secret,
KBNODE *keyblock_out, unsigned int options, int *any ) kbnode_t *keyblock_out, unsigned int options, int *any)
{ {
int rc = 0; gpg_error_t err = 0;
gpg_error_t err;
PACKET pkt; PACKET pkt;
KBNODE keyblock = NULL; KBNODE keyblock = NULL;
KBNODE kbctx, node; KBNODE kbctx, node;
size_t ndesc, descindex; size_t ndesc, descindex;
KEYDB_SEARCH_DESC *desc = NULL; KEYDB_SEARCH_DESC *desc = NULL;
subkey_list_t subkey_list = NULL; /* Track alreay processed subkeys. */ subkey_list_t subkey_list = NULL; /* Track already processed subkeys. */
KEYDB_HANDLE kdbhd; KEYDB_HANDLE kdbhd;
strlist_t sl; strlist_t sl;
int indent = 0; int indent = 0;
*any = 0; *any = 0;
init_packet( &pkt ); init_packet (&pkt);
kdbhd = keydb_new (); kdbhd = keydb_new ();
if (!users) { if (!users)
{
ndesc = 1; ndesc = 1;
desc = xcalloc ( ndesc, sizeof *desc ); desc = xcalloc (ndesc, sizeof *desc);
desc[0].mode = KEYDB_SEARCH_MODE_FIRST; desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
} }
else { else
{
for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++) for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
; ;
desc = xmalloc ( ndesc * sizeof *desc); desc = xmalloc ( ndesc * sizeof *desc);
for (ndesc=0, sl=users; sl; sl = sl->next) { for (ndesc=0, sl=users; sl; sl = sl->next)
{
if (!(err=classify_user_id (sl->d, desc+ndesc))) if (!(err=classify_user_id (sl->d, desc+ndesc)))
ndesc++; ndesc++;
else else
@ -326,66 +318,72 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
sl->d, gpg_strerror (err)); sl->d, gpg_strerror (err));
} }
/* It would be nice to see which of the given users did /* It would be nice to see which of the given users did actually
actually match one in the keyring. To implement this we match one in the keyring. To implement this we need to have
need to have a found flag for each entry in desc and to set a found flag for each entry in desc. To set this flag we
this we must check all those entries after a match to mark must check all those entries after a match to mark all
all matched one - currently we stop at the first match. To matched one - currently we stop at the first match. To do
do this we need an extra flag to enable this feature so */ this we need an extra flag to enable this feature. */
} }
#ifdef ENABLE_SELINUX_HACKS #ifdef ENABLE_SELINUX_HACKS
if (secret) { if (secret)
{
log_error (_("exporting secret keys not allowed\n")); log_error (_("exporting secret keys not allowed\n"));
rc = G10ERR_GENERAL; err = G10ERR_GENERAL;
goto leave; goto leave;
} }
#endif #endif
while (!(rc = keydb_search2 (kdbhd, desc, ndesc, &descindex))) { while (!(err = keydb_search2 (kdbhd, desc, ndesc, &descindex)))
int sha1_warned=0,skip_until_subkey=0; {
u32 sk_keyid[2]; int sha1_warned = 0;
int skip_until_subkey = 0;
u32 keyid[2];
if (!users) if (!users)
desc[0].mode = KEYDB_SEARCH_MODE_NEXT; desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
/* Read the keyblock. */ /* Read the keyblock. */
rc = keydb_get_keyblock (kdbhd, &keyblock ); err = keydb_get_keyblock (kdbhd, &keyblock);
if( rc ) { if (err)
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); {
log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
goto leave; goto leave;
} }
if((node=find_kbnode(keyblock,PKT_SECRET_KEY))) if ((node=find_kbnode(keyblock, PKT_SECRET_KEY)))
{ {
PKT_secret_key *sk=node->pkt->pkt.secret_key; PKT_public_key *pk = node->pkt->pkt.public_key;
keyid_from_sk(sk,sk_keyid); keyid_from_pk (pk, keyid);
/* We can't apply GNU mode 1001 on an unprotected key. */ /* We can't apply GNU mode 1001 on an unprotected key. */
if( secret == 2 && !sk->is_protected ) if( secret == 2
&& pk->seckey_info && !pk->seckey_info->is_protected )
{ {
log_info(_("key %s: not protected - skipped\n"), log_info (_("key %s: not protected - skipped\n"),
keystr(sk_keyid)); keystr (keyid));
continue; continue;
} }
/* No v3 keys with GNU mode 1001. */ /* No v3 keys with GNU mode 1001. */
if( secret == 2 && sk->version == 3 ) if( secret == 2 && pk->version == 3 )
{ {
log_info(_("key %s: PGP 2.x style key - skipped\n"), log_info(_("key %s: PGP 2.x style key - skipped\n"),
keystr(sk_keyid)); keystr (keyid));
continue; continue;
} }
/* It does not make sense to export a key with a primary /* It does not make sense to export a key with a primary
key on card using a non-key stub. We simply skip those key on card using a non-key stub. We simply skip those
keys when used with --export-secret-subkeys. */ keys when used with --export-secret-subkeys. */
if (secret == 2 && sk->is_protected if (secret == 2
&& sk->protect.s2k.mode == 1002 ) && pk->seckey_info && pk->seckey_info->is_protected
&& pk->seckey_info->s2k.mode == 1002 )
{ {
log_info(_("key %s: key material on-card - skipped\n"), log_info(_("key %s: key material on-card - skipped\n"),
keystr(sk_keyid)); keystr (keyid));
continue; continue;
} }
} }
@ -393,21 +391,22 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
{ {
/* It's a public key export, so do the cleaning if /* It's a public key export, so do the cleaning if
requested. Note that both export-clean and requested. Note that both export-clean and
export-minimal only apply to UID sigs (0x10, 0x11, export-minimal only apply to UID sigs (0x10, 0x11, 0x12,
0x12, and 0x13). A designated revocation is never and 0x13). A designated revocation is never stripped,
stripped, even with export-minimal set. */ even with export-minimal set. */
if ( (options & EXPORT_CLEAN) )
if(options&EXPORT_CLEAN) clean_key (keyblock, opt.verbose, options&EXPORT_MINIMAL,
clean_key(keyblock,opt.verbose,options&EXPORT_MINIMAL,NULL,NULL); NULL, NULL);
} }
/* And write it. */ /* And write it. */
for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) { for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
if( skip_until_subkey )
{ {
if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY if (skip_until_subkey)
{
if (node->pkt->pkttype==PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype==PKT_SECRET_SUBKEY) || node->pkt->pkttype==PKT_SECRET_SUBKEY)
skip_until_subkey=0; skip_until_subkey = 0;
else else
continue; continue;
} }
@ -415,7 +414,7 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
/* We used to use comment packets, but not any longer. In /* We used to use comment packets, but not any longer. In
case we still have comments on a key, strip them here case we still have comments on a key, strip them here
before we call build_packet(). */ before we call build_packet(). */
if( node->pkt->pkttype == PKT_COMMENT ) if (node->pkt->pkttype == PKT_COMMENT)
continue; continue;
/* Make sure that ring_trust packets never get exported. */ /* Make sure that ring_trust packets never get exported. */
@ -425,9 +424,9 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
/* If exact is set, then we only export what was requested /* If exact is set, then we only export what was requested
(plus the primary key, if the user didn't specifically (plus the primary key, if the user didn't specifically
request it). */ request it). */
if(desc[descindex].exact if (desc[descindex].exact
&& (node->pkt->pkttype==PKT_PUBLIC_SUBKEY && (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype==PKT_SECRET_SUBKEY)) || node->pkt->pkttype == PKT_SECRET_SUBKEY))
{ {
if (!exact_subkey_match_p (desc+descindex, node)) if (!exact_subkey_match_p (desc+descindex, node))
{ {
@ -442,8 +441,8 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
We need this whole mess because the import We need this whole mess because the import
function is not able to merge secret keys and function is not able to merge secret keys and
thus it is useless to output them as two thus it is useless to output them as two separate
separate keys and have import merge them. */ keys and have import merge them. */
if (subkey_in_list_p (subkey_list, node)) if (subkey_in_list_p (subkey_list, node))
skip_until_subkey = 1; /* Already processed this one. */ skip_until_subkey = 1; /* Already processed this one. */
else else
@ -470,11 +469,11 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
} }
} }
if(node->pkt->pkttype==PKT_SIGNATURE) if (node->pkt->pkttype == PKT_SIGNATURE)
{ {
/* do not export packets which are marked as not /* Do not export packets which are marked as not
exportable */ exportable. */
if(!(options&EXPORT_LOCAL_SIGS) if (!(options&EXPORT_LOCAL_SIGS)
&& !node->pkt->pkt.signature->flags.exportable) && !node->pkt->pkt.signature->flags.exportable)
continue; /* not exportable */ continue; /* not exportable */
@ -482,121 +481,125 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
key unless the user wants us to. Note that we do key unless the user wants us to. Note that we do
export these when issuing the actual revocation export these when issuing the actual revocation
(see revoke.c). */ (see revoke.c). */
if(!(options&EXPORT_SENSITIVE_REVKEYS) if (!(options&EXPORT_SENSITIVE_REVKEYS)
&& node->pkt->pkt.signature->revkey) && node->pkt->pkt.signature->revkey)
{ {
int i; int i;
for(i=0;i<node->pkt->pkt.signature->numrevkeys;i++) for (i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
if(node->pkt->pkt.signature->revkey[i]->class & 0x40) if ( (node->pkt->pkt.signature->revkey[i]->class & 0x40))
break; break;
if(i<node->pkt->pkt.signature->numrevkeys) if (i < node->pkt->pkt.signature->numrevkeys)
continue; continue;
} }
} }
/* Don't export attribs? */ /* Don't export attribs? */
if( !(options&EXPORT_ATTRIBUTES) && if (!(options&EXPORT_ATTRIBUTES)
node->pkt->pkttype == PKT_USER_ID && && node->pkt->pkttype == PKT_USER_ID
node->pkt->pkt.user_id->attrib_data ) { && node->pkt->pkt.user_id->attrib_data )
{
/* Skip until we get to something that is not an attrib /* Skip until we get to something that is not an attrib
or a signature on an attrib */ or a signature on an attrib */
while(kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE) { while (kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE)
kbctx=kbctx->next; kbctx = kbctx->next;
}
continue; continue;
} }
if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) if (secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY)
{ {
/* We don't want to export the secret parts of the /* We don't want to export the secret parts of the
* primary key, this is done by using GNU protection mode 1001 * primary key, this is done by temporary switching to
*/ * GNU protection mode 1001. */
int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode; int save_mode = node->pkt->pkt.public_key->seckey_info->s2k.mode;
node->pkt->pkt.secret_key->protect.s2k.mode = 1001; node->pkt->pkt.public_key->seckey_info->s2k.mode = 1001;
if ((options&EXPORT_SEXP_FORMAT)) if ((options&EXPORT_SEXP_FORMAT))
rc = build_sexp (out, node->pkt, &indent); err = build_sexp (out, node->pkt, &indent);
else else
rc = build_packet (out, node->pkt); err = build_packet (out, node->pkt);
node->pkt->pkt.secret_key->protect.s2k.mode = save_mode; node->pkt->pkt.public_key->seckey_info->s2k.mode = save_mode;
} }
else if (secret == 2 && node->pkt->pkttype == PKT_SECRET_SUBKEY else if (secret == 2 && node->pkt->pkttype == PKT_SECRET_SUBKEY
&& (opt.export_options&EXPORT_RESET_SUBKEY_PASSWD)) && (opt.export_options&EXPORT_RESET_SUBKEY_PASSWD))
{ {
/* If the subkey is protected reset the passphrase to /* If the subkey is protected reset the passphrase to
export an unprotected subkey. This feature is export an unprotected subkey. This feature is useful
useful in cases of a subkey copied to an unattended in cases of a subkey copied to an unattended machine
machine where a passphrase is not required. */ where a passphrase is not required. */
PKT_secret_key *sk_save, *sk; err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
sk_save = node->pkt->pkt.secret_key;
sk = copy_secret_key (NULL, sk_save);
node->pkt->pkt.secret_key = sk;
log_info (_("about to export an unprotected subkey\n"));
switch (is_secret_key_protected (sk))
{
case -1:
rc = G10ERR_PUBKEY_ALGO;
break;
case 0:
break;
default:
if (sk->protect.s2k.mode == 1001)
; /* No secret parts. */
else if( sk->protect.s2k.mode == 1002 )
; /* Card key stub. */
else
{
/* rc = check_secret_key( sk, 0 ); */
}
break;
}
if (rc)
{
node->pkt->pkt.secret_key = sk_save;
free_secret_key (sk);
log_error (_("failed to unprotect the subkey: %s\n"),
g10_errstr (rc));
goto leave; goto leave;
} #warning We need to implement this
/* PKT_secret_key *sk_save, *sk; */
if ((options&EXPORT_SEXP_FORMAT)) /* sk_save = node->pkt->pkt.secret_key; */
rc = build_sexp (out, node->pkt, &indent); /* sk = copy_secret_key (NULL, sk_save); */
else /* node->pkt->pkt.secret_key = sk; */
rc = build_packet (out, node->pkt);
node->pkt->pkt.secret_key = sk_save; /* log_info (_("about to export an unprotected subkey\n")); */
free_secret_key (sk); /* switch (is_secret_key_protected (sk)) */
/* { */
/* case -1: */
/* err = gpg_error (GPG_ERR_PUBKEY_ALGO); */
/* break; */
/* case 0: */
/* break; */
/* default: */
/* if (sk->protect.s2k.mode == 1001) */
/* ; /\* No secret parts. *\/ */
/* else if( sk->protect.s2k.mode == 1002 ) */
/* ; /\* Card key stub. *\/ */
/* else */
/* { */
/* /\* err = check_secret_key( sk, 0 ); *\/ */
/* } */
/* break; */
/* } */
/* if (err) */
/* { */
/* node->pkt->pkt.secret_key = sk_save; */
/* free_secret_key (sk); */
/* log_error (_("failed to unprotect the subkey: %s\n"), */
/* g10_errstr (rc)); */
/* goto leave; */
/* } */
/* if ((options&EXPORT_SEXP_FORMAT)) */
/* err = build_sexp (out, node->pkt, &indent); */
/* else */
/* err = build_packet (out, node->pkt); */
/* node->pkt->pkt.secret_key = sk_save; */
/* free_secret_key (sk); */
} }
else else
{ {
/* Warn the user if the secret key or any of the secret /* Warn the user if the secret key or any of the secret
subkeys are protected with SHA1 and we have subkeys are protected with SHA1 and we have
simple_sk_checksum set. */ simple_sk_checksum set. */
if(!sha1_warned && opt.simple_sk_checksum && if (!sha1_warned && opt.simple_sk_checksum &&
(node->pkt->pkttype==PKT_SECRET_KEY || (node->pkt->pkttype == PKT_SECRET_KEY
node->pkt->pkttype==PKT_SECRET_SUBKEY) && || node->pkt->pkttype == PKT_SECRET_SUBKEY)
node->pkt->pkt.secret_key->protect.sha1chk) && node->pkt->pkt.public_key->seckey_info->sha1chk)
{ {
/* I hope this warning doesn't confuse people. */ /* I hope this warning doesn't confuse people. */
log_info(_("WARNING: secret key %s does not have a " log_info(_("WARNING: secret key %s does not have a "
"simple SK checksum\n"),keystr(sk_keyid)); "simple SK checksum\n"), keystr (keyid));
sha1_warned=1; sha1_warned = 1;
} }
if ((options&EXPORT_SEXP_FORMAT)) if ((options&EXPORT_SEXP_FORMAT))
rc = build_sexp (out, node->pkt, &indent); err = build_sexp (out, node->pkt, &indent);
else else
rc = build_packet (out, node->pkt); err = build_packet (out, node->pkt);
} }
if( rc ) { if (err)
log_error("build_packet(%d) failed: %s\n", {
node->pkt->pkttype, g10_errstr(rc) ); log_error ("build_packet(%d) failed: %s\n",
node->pkt->pkttype, gpg_strerror (err));
goto leave; goto leave;
} }
} }
@ -621,117 +624,119 @@ do_export_stream( IOBUF out, strlist_t users, int secret,
iobuf_put (out, ')'); iobuf_put (out, ')');
iobuf_put (out, '\n'); iobuf_put (out, '\n');
} }
if( rc == -1 ) if( err == -1 )
rc = 0; err = 0;
leave: leave:
release_subkey_list (subkey_list); release_subkey_list (subkey_list);
xfree(desc); xfree(desc);
keydb_release (kdbhd); keydb_release (kdbhd);
if(rc || keyblock_out==NULL) if (err || !keyblock_out)
release_kbnode( keyblock ); release_kbnode( keyblock );
if( !*any ) if( !*any )
log_info(_("WARNING: nothing exported\n")); log_info(_("WARNING: nothing exported\n"));
return rc; return err;
} }
static int /* static int */
write_sexp_line (iobuf_t out, int *indent, const char *text) /* write_sexp_line (iobuf_t out, int *indent, const char *text) */
{ /* { */
int i; /* int i; */
for (i=0; i < *indent; i++) /* for (i=0; i < *indent; i++) */
iobuf_put (out, ' '); /* iobuf_put (out, ' '); */
iobuf_writestr (out, text); /* iobuf_writestr (out, text); */
return 0; /* return 0; */
} /* } */
static int /* static int */
write_sexp_keyparm (iobuf_t out, int *indent, const char *name, gcry_mpi_t a) /* write_sexp_keyparm (iobuf_t out, int *indent, const char *name, gcry_mpi_t a) */
{ /* { */
int rc; /* int rc; */
unsigned char *buffer; /* unsigned char *buffer; */
write_sexp_line (out, indent, "("); /* write_sexp_line (out, indent, "("); */
iobuf_writestr (out, name); /* iobuf_writestr (out, name); */
iobuf_writestr (out, " #"); /* iobuf_writestr (out, " #"); */
rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a); /* rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a); */
assert (!rc); /* assert (!rc); */
iobuf_writestr (out, buffer); /* iobuf_writestr (out, buffer); */
iobuf_writestr (out, "#)"); /* iobuf_writestr (out, "#)"); */
gcry_free (buffer); /* gcry_free (buffer); */
return 0; /* return 0; */
} /* } */
static int static int
build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent) build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
{ {
PKT_secret_key *sk = pkt->pkt.secret_key; /* FIXME: Not yet implemented. */
char tmpbuf[100]; return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
/* PKT_secret_key *sk = pkt->pkt.secret_key; */
/* char tmpbuf[100]; */
if (pkt->pkttype == PKT_SECRET_KEY) /* if (pkt->pkttype == PKT_SECRET_KEY) */
{ /* { */
iobuf_writestr (out, "(openpgp-key\n"); /* iobuf_writestr (out, "(openpgp-key\n"); */
(*indent)++; /* (*indent)++; */
} /* } */
else /* else */
{ /* { */
iobuf_writestr (out, " (subkey\n"); /* iobuf_writestr (out, " (subkey\n"); */
(*indent)++; /* (*indent)++; */
} /* } */
(*indent)++; /* (*indent)++; */
write_sexp_line (out, indent, "(private-key\n"); /* write_sexp_line (out, indent, "(private-key\n"); */
(*indent)++; /* (*indent)++; */
if (is_RSA (sk->pubkey_algo) && !sk->is_protected) /* if (is_RSA (sk->pubkey_algo) && !sk->is_protected) */
{ /* { */
write_sexp_line (out, indent, "(rsa\n"); /* write_sexp_line (out, indent, "(rsa\n"); */
(*indent)++; /* (*indent)++; */
write_sexp_keyparm (out, indent, "n", sk->skey[0]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "n", sk->skey[0]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "e", sk->skey[1]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "e", sk->skey[1]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "d", sk->skey[2]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "d", sk->skey[2]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "p", sk->skey[3]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "p", sk->skey[3]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "q", sk->skey[4]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "q", sk->skey[4]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "u", sk->skey[5]); /* write_sexp_keyparm (out, indent, "u", sk->skey[5]); */
iobuf_put (out,')'); iobuf_put (out,'\n'); /* iobuf_put (out,')'); iobuf_put (out,'\n'); */
(*indent)--; /* (*indent)--; */
} /* } */
else if (sk->pubkey_algo == PUBKEY_ALGO_DSA && !sk->is_protected) /* else if (sk->pubkey_algo == PUBKEY_ALGO_DSA && !sk->is_protected) */
{ /* { */
write_sexp_line (out, indent, "(dsa\n"); /* write_sexp_line (out, indent, "(dsa\n"); */
(*indent)++; /* (*indent)++; */
write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "q", sk->skey[1]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "q", sk->skey[1]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "x", sk->skey[4]); /* write_sexp_keyparm (out, indent, "x", sk->skey[4]); */
iobuf_put (out,')'); iobuf_put (out,'\n'); /* iobuf_put (out,')'); iobuf_put (out,'\n'); */
(*indent)--; /* (*indent)--; */
} /* } */
else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected) /* else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected) */
{ /* { */
write_sexp_line (out, indent, "(elg\n"); /* write_sexp_line (out, indent, "(elg\n"); */
(*indent)++; /* (*indent)++; */
write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n'); /* write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n'); */
write_sexp_keyparm (out, indent, "x", sk->skey[4]); /* write_sexp_keyparm (out, indent, "x", sk->skey[4]); */
iobuf_put (out,')'); iobuf_put (out,'\n'); /* iobuf_put (out,')'); iobuf_put (out,'\n'); */
(*indent)--; /* (*indent)--; */
} /* } */
write_sexp_line (out, indent, "(attrib\n"); (*indent)++; /* write_sexp_line (out, indent, "(attrib\n"); (*indent)++; */
sprintf (tmpbuf, "(created \"%lu\"", (unsigned long)sk->timestamp); /* sprintf (tmpbuf, "(created \"%lu\"", (unsigned long)sk->timestamp); */
write_sexp_line (out, indent, tmpbuf); /* write_sexp_line (out, indent, tmpbuf); */
iobuf_put (out,')'); (*indent)--; /* close created */ /* iobuf_put (out,')'); (*indent)--; /\* close created *\/ */
iobuf_put (out,')'); (*indent)--; /* close attrib */ /* iobuf_put (out,')'); (*indent)--; /\* close attrib *\/ */
iobuf_put (out,')'); (*indent)--; /* close private-key */ /* iobuf_put (out,')'); (*indent)--; /\* close private-key *\/ */
if (pkt->pkttype != PKT_SECRET_KEY) /* if (pkt->pkttype != PKT_SECRET_KEY) */
iobuf_put (out,')'), (*indent)--; /* close subkey */ /* iobuf_put (out,')'), (*indent)--; /\* close subkey *\/ */
iobuf_put (out,'\n'); /* iobuf_put (out,'\n'); */
return 0; /* return 0; */
} }

View File

@ -1,6 +1,6 @@
/* free-packet.c - cleanup stuff for packets /* free-packet.c - cleanup stuff for packets
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
* 2005 Free Software Foundation, Inc. * 2005, 2010 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -76,36 +76,50 @@ free_seckey_enc( PKT_signature *sig )
void void
release_public_key_parts( PKT_public_key *pk ) release_public_key_parts (PKT_public_key *pk)
{ {
int n, i; int n, i;
n = pubkey_get_npkey( pk->pubkey_algo );
if( !n ) if (pk->seckey_info)
mpi_release(pk->pkey[0]); n = pubkey_get_nskey (pk->pubkey_algo);
for(i=0; i < n; i++ ) { else
mpi_release( pk->pkey[i] ); n = pubkey_get_npkey (pk->pubkey_algo);
if (!n)
mpi_release (pk->pkey[0]);
for (i=0; i < n; i++ )
{
mpi_release (pk->pkey[i]);
pk->pkey[i] = NULL; pk->pkey[i] = NULL;
} }
if (pk->prefs) { if (pk->seckey_info)
{
xfree (pk->seckey_info);
pk->seckey_info = NULL;
}
if (pk->prefs)
{
xfree (pk->prefs); xfree (pk->prefs);
pk->prefs = NULL; pk->prefs = NULL;
} }
if (pk->user_id) { if (pk->user_id)
{
free_user_id (pk->user_id); free_user_id (pk->user_id);
pk->user_id = NULL; pk->user_id = NULL;
} }
if (pk->revkey) { if (pk->revkey)
{
xfree(pk->revkey); xfree(pk->revkey);
pk->revkey=NULL; pk->revkey=NULL;
pk->numrevkeys=0; pk->numrevkeys=0;
} }
} }
void void
free_public_key( PKT_public_key *pk ) free_public_key (PKT_public_key *pk)
{ {
release_public_key_parts( pk ); release_public_key_parts (pk);
xfree(pk); xfree(pk);
} }
@ -150,26 +164,37 @@ copy_prefs (const prefitem_t *prefs)
} }
/* Copy the public key S to D. If D is NULL allocate a new public key
structure. If S has seckret key infos, only the public stuff is
copied. */
PKT_public_key * PKT_public_key *
copy_public_key ( PKT_public_key *d, PKT_public_key *s) copy_public_key (PKT_public_key *d, PKT_public_key *s)
{ {
int n, i; int n, i;
if( !d ) if (!d)
d = xmalloc(sizeof *d); d = xmalloc (sizeof *d);
memcpy( d, s, sizeof *d ); memcpy (d, s, sizeof *d);
d->seckey_info = NULL;
d->user_id = scopy_user_id (s->user_id); d->user_id = scopy_user_id (s->user_id);
d->prefs = copy_prefs (s->prefs); d->prefs = copy_prefs (s->prefs);
n = pubkey_get_npkey( s->pubkey_algo );
if( !n ) n = pubkey_get_npkey (s->pubkey_algo);
d->pkey[0] = mpi_copy(s->pkey[0]); i = 0;
else { if (!n)
for(i=0; i < n; i++ ) d->pkey[i++] = mpi_copy (s->pkey[0]);
else
{
for (; i < n; i++ )
d->pkey[i] = mpi_copy( s->pkey[i] ); d->pkey[i] = mpi_copy( s->pkey[i] );
} }
if( !s->revkey && s->numrevkeys ) for (; i < PUBKEY_MAX_NSKEY; i++)
d->pkey[i] = NULL;
if (!s->revkey && s->numrevkeys)
BUG(); BUG();
if( s->numrevkeys ) { if (s->numrevkeys)
{
d->revkey = xmalloc(sizeof(struct revocation_key)*s->numrevkeys); d->revkey = xmalloc(sizeof(struct revocation_key)*s->numrevkeys);
memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys); memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
} }
@ -178,27 +203,6 @@ copy_public_key ( PKT_public_key *d, PKT_public_key *s)
return d; return d;
} }
/****************
* Replace all common parts of a sk by the one from the public key.
* This is a hack and a better solution will be to just store the real secret
* parts somewhere and don't duplicate all the other stuff.
*/
void
copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
{
sk->expiredate = pk->expiredate;
sk->pubkey_algo = pk->pubkey_algo;
sk->pubkey_usage= pk->pubkey_usage;
sk->req_usage = pk->req_usage;
sk->req_algo = pk->req_algo;
sk->has_expired = pk->has_expired;
sk->is_revoked = pk->is_revoked;
sk->is_valid = pk->is_valid;
sk->main_keyid[0]= pk->main_keyid[0];
sk->main_keyid[1]= pk->main_keyid[1];
sk->keyid[0] = pk->keyid[0];
sk->keyid[1] = pk->keyid[1];
}
static pka_info_t * static pka_info_t *
@ -256,48 +260,6 @@ scopy_user_id (PKT_user_id *s)
void
release_secret_key_parts( PKT_secret_key *sk )
{
int n, i;
n = pubkey_get_nskey( sk->pubkey_algo );
if( !n )
mpi_release(sk->skey[0]);
for(i=0; i < n; i++ ) {
mpi_release( sk->skey[i] );
sk->skey[i] = NULL;
}
}
void
free_secret_key( PKT_secret_key *sk )
{
release_secret_key_parts( sk );
xfree(sk);
}
PKT_secret_key *
copy_secret_key( PKT_secret_key *d, PKT_secret_key *s )
{
int n, i;
if( !d )
d = xmalloc_secure(sizeof *d);
else
release_secret_key_parts (d);
memcpy( d, s, sizeof *d );
n = pubkey_get_nskey( s->pubkey_algo );
if( !n )
d->skey[0] = mpi_copy(s->skey[0]);
else {
for(i=0; i < n; i++ )
d->skey[i] = mpi_copy( s->skey[i] );
}
return d;
}
void void
free_comment( PKT_comment *rem ) free_comment( PKT_comment *rem )
{ {
@ -407,11 +369,9 @@ free_packet( PACKET *pkt )
break; break;
case PKT_PUBLIC_KEY: case PKT_PUBLIC_KEY:
case PKT_PUBLIC_SUBKEY: case PKT_PUBLIC_SUBKEY:
free_public_key( pkt->pkt.public_key );
break;
case PKT_SECRET_KEY: case PKT_SECRET_KEY:
case PKT_SECRET_SUBKEY: case PKT_SECRET_SUBKEY:
free_secret_key( pkt->pkt.secret_key ); free_public_key (pkt->pkt.public_key);
break; break;
case PKT_COMMENT: case PKT_COMMENT:
free_comment( pkt->pkt.comment ); free_comment( pkt->pkt.comment );
@ -462,59 +422,6 @@ cmp_public_keys( PKT_public_key *a, PKT_public_key *b )
return 0; return 0;
} }
/****************
* Returns 0 if they match.
* We only compare the public parts.
*/
int
cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b )
{
int n, i;
log_debug ("FIXME: %s Should not be used\n", __func__);
if( a->timestamp != b->timestamp )
return -1;
if( a->version < 4 && a->expiredate != b->expiredate )
return -1;
if( a->pubkey_algo != b->pubkey_algo )
return -1;
n = pubkey_get_npkey( b->pubkey_algo );
if( !n )
return -1; /* can't compare due to unknown algorithm */
for(i=0; i < n; i++ ) {
if( mpi_cmp( a->skey[i], b->skey[i] ) )
return -1;
}
return 0;
}
/****************
* Returns 0 if they match.
*/
int
cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
{
int n, i;
if( pk->timestamp != sk->timestamp )
return -1;
if( pk->version < 4 && pk->expiredate != sk->expiredate )
return -1;
if( pk->pubkey_algo != sk->pubkey_algo )
return -1;
n = pubkey_get_npkey( pk->pubkey_algo );
if( !n )
return -1; /* can't compare due to unknown algorithm */
for(i=0; i < n; i++ ) {
if( mpi_cmp( pk->pkey[i] , sk->skey[i] ) )
return -1;
}
return 0;
}
int int

View File

@ -2522,7 +2522,7 @@ found:
* so that can free it's context. * so that can free it's context.
*/ */
int int
enum_secret_keys (void **context, PKT_secret_key * sk, enum_secret_keys (void **context, PKT_public_key * sk,
int with_subkeys, int with_spm) int with_subkeys, int with_spm)
{ {
log_debug ("FIXME: Anonymous recipient does not yet work\n"); log_debug ("FIXME: Anonymous recipient does not yet work\n");

View File

@ -567,19 +567,16 @@ fix_bad_direct_key_sigs (kbnode_t keyblock, u32 *keyid)
static void static void
print_import_ok (PKT_public_key *pk, PKT_secret_key *sk, unsigned int reason) print_import_ok (PKT_public_key *pk, unsigned int reason)
{ {
byte array[MAX_FINGERPRINT_LEN], *s; byte array[MAX_FINGERPRINT_LEN], *s;
char buf[MAX_FINGERPRINT_LEN*2+30], *p; char buf[MAX_FINGERPRINT_LEN*2+30], *p;
size_t i, n; size_t i, n;
sprintf (buf, "%u ", reason); snprintf (buf, sizeof buf, "%u ", reason);
p = buf + strlen (buf); p = buf + strlen (buf);
if (pk)
fingerprint_from_pk (pk, array, &n); fingerprint_from_pk (pk, array, &n);
else
fingerprint_from_sk (sk, array, &n);
s = array; s = array;
for (i=0; i < n ; i++, s++, p += 2) for (i=0; i < n ; i++, s++, p += 2)
sprintf (p, "%02X", *s); sprintf (p, "%02X", *s);
@ -886,7 +883,7 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
char *us = get_long_user_id_string( keyid ); char *us = get_long_user_id_string( keyid );
write_status_text( STATUS_IMPORTED, us ); write_status_text( STATUS_IMPORTED, us );
xfree(us); xfree(us);
print_import_ok (pk,NULL, 1); print_import_ok (pk, 1);
} }
stats->imported++; stats->imported++;
if( is_RSA( pk->pubkey_algo ) ) if( is_RSA( pk->pubkey_algo ) )
@ -1007,14 +1004,13 @@ import_one( const char *fname, KBNODE keyblock, struct stats_s *stats,
stats->n_uids_cleaned +=n_uids_cleaned; stats->n_uids_cleaned +=n_uids_cleaned;
if (is_status_enabled ()) if (is_status_enabled ())
print_import_ok (pk, NULL, print_import_ok (pk, ((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0)));
((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0)));
} }
else else
{ {
same_key = 1; same_key = 1;
if (is_status_enabled ()) if (is_status_enabled ())
print_import_ok (pk, NULL, 0); print_import_ok (pk, 0);
if( !opt.quiet ) if( !opt.quiet )
{ {
@ -1092,7 +1088,8 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
size_t keklen; size_t keklen;
kbnode_t ctx = NULL; kbnode_t ctx = NULL;
kbnode_t node; kbnode_t node;
PKT_secret_key *main_sk, *sk; PKT_public_key *main_pk, *pk;
struct seckey_info *ski;
int nskey; int nskey;
membuf_t mbuf; membuf_t mbuf;
int i, j; int i, j;
@ -1126,21 +1123,25 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
xfree (kek); xfree (kek);
kek = NULL; kek = NULL;
main_sk = NULL; main_pk = NULL;
while ((node = walk_kbnode (sec_keyblock, &ctx, 0))) while ((node = walk_kbnode (sec_keyblock, &ctx, 0)))
{ {
if (node->pkt->pkttype != PKT_SECRET_KEY if (node->pkt->pkttype != PKT_SECRET_KEY
&& node->pkt->pkttype != PKT_SECRET_SUBKEY) && node->pkt->pkttype != PKT_SECRET_SUBKEY)
continue; continue;
sk = node->pkt->pkt.secret_key; pk = node->pkt->pkt.public_key;
if (!main_sk) if (!main_pk)
main_sk = sk; main_pk = pk;
ski = pk->seckey_info;
if (!ski)
BUG ();
stats->count++; stats->count++;
stats->secret_read++; stats->secret_read++;
/* Convert our internal secret key object into an S-expression. */ /* Convert our internal secret key object into an S-expression. */
nskey = pubkey_get_nskey (sk->pubkey_algo); nskey = pubkey_get_nskey (pk->pubkey_algo);
if (!nskey || nskey > PUBKEY_MAX_NSKEY) if (!nskey || nskey > PUBKEY_MAX_NSKEY)
{ {
err = gpg_error (GPG_ERR_BAD_SECKEY); err = gpg_error (GPG_ERR_BAD_SECKEY);
@ -1152,10 +1153,10 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
put_membuf_str (&mbuf, "(skey"); put_membuf_str (&mbuf, "(skey");
for (i=j=0; i < nskey; i++) for (i=j=0; i < nskey; i++)
{ {
if (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE)) if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE))
{ {
put_membuf_str (&mbuf, " e %b"); put_membuf_str (&mbuf, " e %b");
format_args_buf_ptr[i] = gcry_mpi_get_opaque (sk->skey[i], &n); format_args_buf_ptr[i] = gcry_mpi_get_opaque (pk->pkey[i], &n);
format_args_buf_int[i] = (n+7)/8; format_args_buf_int[i] = (n+7)/8;
format_args[j++] = format_args_buf_int + i; format_args[j++] = format_args_buf_int + i;
format_args[j++] = format_args_buf_ptr + i; format_args[j++] = format_args_buf_ptr + i;
@ -1163,7 +1164,7 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
else else
{ {
put_membuf_str (&mbuf, " _ %m"); put_membuf_str (&mbuf, " _ %m");
format_args[j++] = sk->skey + i; format_args[j++] = pk->pkey + i;
} }
} }
put_membuf_str (&mbuf, ")\n"); put_membuf_str (&mbuf, ")\n");
@ -1182,21 +1183,21 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
goto leave; goto leave;
} }
if (sk->is_protected) if (ski->is_protected)
{ {
char countbuf[35]; char countbuf[35];
snprintf (countbuf, sizeof countbuf, "%lu", snprintf (countbuf, sizeof countbuf, "%lu",
(unsigned long)sk->protect.s2k.count); (unsigned long)ski->s2k.count);
err = gcry_sexp_build err = gcry_sexp_build
(&prot, NULL, (&prot, NULL,
" (protection %s %s %b %d %s %b %s)\n", " (protection %s %s %b %d %s %b %s)\n",
sk->protect.sha1chk? "sha1":"sum", ski->sha1chk? "sha1":"sum",
openpgp_cipher_algo_name (sk->protect.algo), openpgp_cipher_algo_name (ski->algo),
(int)sk->protect.ivlen, sk->protect.iv, (int)ski->ivlen, ski->iv,
sk->protect.s2k.mode, ski->s2k.mode,
openpgp_md_algo_name (sk->protect.s2k.hash_algo), openpgp_md_algo_name (ski->s2k.hash_algo),
(int)sizeof (sk->protect.s2k.salt), sk->protect.s2k.salt, (int)sizeof (ski->s2k.salt), ski->s2k.salt,
countbuf); countbuf);
} }
else else
@ -1213,9 +1214,9 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
" %S\n" " %S\n"
" (csum %d)\n" " (csum %d)\n"
" %S)\n", " %S)\n",
sk->version, pk->version,
openpgp_pk_algo_name (sk->pubkey_algo), openpgp_pk_algo_name (pk->pubkey_algo),
skey, (int)(unsigned long)sk->csum, prot); skey, (int)(unsigned long)ski->csum, prot);
gcry_sexp_release (skey); gcry_sexp_release (skey);
gcry_sexp_release (prot); gcry_sexp_release (prot);
if (!err) if (!err)
@ -1243,37 +1244,7 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
/* Send the wrapped key to the agent. */ /* Send the wrapped key to the agent. */
{ {
char *uid, *desc; char *desc = gpg_format_keydesc (pk, 1, 1);
size_t uidlen;
u32 keyid[2];
char *orig_codeset;
/* FIXME: We should use gpg_format_keydesc, however that
requires a public key structure. It might be useful to
merge the secret and public key structures. */
keyid_from_sk (sk, keyid);
uid = get_user_id (keyid, &uidlen);
orig_codeset = i18n_switchto_utf8 ();
desc = xtryasprintf (_("Please enter the passphrase to import the"
" secret key for the OpenPGP certificate:\n"
"\"%.*s\"\n" \
"%u-bit %s key, ID %s,\n"
"created %s.\n"),
(int)uidlen, uid,
nbits_from_sk (sk),
openpgp_pk_algo_name (sk->pubkey_algo),
(main_sk == sk
? keystr_from_sk (sk)
: keystr_from_sk_with_sub (main_sk, sk)),
strtimestamp (sk->timestamp));
i18n_switchback (orig_codeset);
xfree (uid);
if (desc)
{
uid = percent_plus_escape (desc);
xfree (desc);
desc = uid;
}
err = agent_import_key (ctrl, desc, &cache_nonce, err = agent_import_key (ctrl, desc, &cache_nonce,
wrappedkey, wrappedkeylen); wrappedkey, wrappedkeylen);
xfree (desc); xfree (desc);
@ -1282,23 +1253,23 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
{ {
if (opt.verbose) if (opt.verbose)
log_info (_("key %s: secret key imported\n"), log_info (_("key %s: secret key imported\n"),
keystr_from_sk_with_sub (main_sk, sk)); keystr_from_pk_with_sub (main_pk, pk));
stats->secret_imported++; stats->secret_imported++;
} }
else if ( gpg_err_code (err) == GPG_ERR_EEXIST ) else if ( gpg_err_code (err) == GPG_ERR_EEXIST )
{ {
if (opt.verbose) if (opt.verbose)
log_info (_("key %s: secret key already exists\n"), log_info (_("key %s: secret key already exists\n"),
keystr_from_sk_with_sub (main_sk, sk)); keystr_from_pk_with_sub (main_pk, pk));
err = 0; err = 0;
stats->secret_dups++; stats->secret_dups++;
} }
else else
{ {
log_error (_("key %s: error sending to agent: %s\n"), log_error (_("key %s: error sending to agent: %s\n"),
keystr_from_sk_with_sub (main_sk, sk), keystr_from_pk_with_sub (main_pk, pk),
gpg_strerror (err)); gpg_strerror (err));
if (sk->protect.algo == GCRY_CIPHER_IDEA if (ski->algo == GCRY_CIPHER_IDEA
&& gpg_err_code (err) == GPG_ERR_CIPHER_ALGO) && gpg_err_code (err) == GPG_ERR_CIPHER_ALGO)
{ {
write_status (STATUS_RSA_OR_IDEA); write_status (STATUS_RSA_OR_IDEA);
@ -1333,40 +1304,24 @@ sec_to_pub_keyblock (kbnode_t sec_keyblock)
if (secnode->pkt->pkttype == PKT_SECRET_KEY if (secnode->pkt->pkttype == PKT_SECRET_KEY
|| secnode->pkt->pkttype == PKT_SECRET_SUBKEY) || secnode->pkt->pkttype == PKT_SECRET_SUBKEY)
{ {
/* Make a public key. We only need to convert enough to /* Make a public key. */
write the keyblock out. */
PACKET *pkt; PACKET *pkt;
PKT_secret_key *sk;
PKT_public_key *pk; PKT_public_key *pk;
int n, i;
pkt = xcalloc (1, sizeof *pkt);
sk = secnode->pkt->pkt.secret_key;
pk = xcalloc (1, sizeof *pk);
pkt = xtrycalloc (1, sizeof *pkt);
pk = pkt? copy_public_key (NULL, secnode->pkt->pkt.public_key): NULL;
if (!pk)
{
xfree (pkt);
release_kbnode (pub_keyblock);
return NULL;
}
if (secnode->pkt->pkttype == PKT_SECRET_KEY) if (secnode->pkt->pkttype == PKT_SECRET_KEY)
pkt->pkttype = PKT_PUBLIC_KEY; pkt->pkttype = PKT_PUBLIC_KEY;
else else
pkt->pkttype = PKT_PUBLIC_SUBKEY; pkt->pkttype = PKT_PUBLIC_SUBKEY;
pkt->pkt.public_key = pk; pkt->pkt.public_key = pk;
pk->version = sk->version;
pk->timestamp = sk->timestamp;
pk->expiredate = sk->expiredate;
pk->pubkey_algo = sk->pubkey_algo;
n = pubkey_get_npkey (pk->pubkey_algo);
if (!n)
{
/* We can't properly extract the pubkey without knowing
the number of MPIs */
release_kbnode (pub_keyblock);
return NULL;
}
for (i=0; i < n; i++)
pk->pkey[i] = mpi_copy (sk->skey[i]);
pubnode = new_kbnode (pkt); pubnode = new_kbnode (pkt);
} }
else else
@ -1393,10 +1348,10 @@ static int
import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock, import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
struct stats_s *stats, unsigned int options) struct stats_s *stats, unsigned int options)
{ {
PKT_secret_key *sk; PKT_public_key *pk;
struct seckey_info *ski;
KBNODE node, uidnode; KBNODE node, uidnode;
u32 keyid[2]; u32 keyid[2];
int have_seckey;
int rc = 0; int rc = 0;
/* Get the key and print some info about it */ /* Get the key and print some info about it */
@ -1404,16 +1359,17 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
if (!node) if (!node)
BUG (); BUG ();
sk = node->pkt->pkt.secret_key; pk = node->pkt->pkt.public_key;
keyid_from_sk (sk, keyid);
keyid_from_pk (pk, keyid);
uidnode = find_next_kbnode (keyblock, PKT_USER_ID); uidnode = find_next_kbnode (keyblock, PKT_USER_ID);
if (opt.verbose) if (opt.verbose)
{ {
log_info ("sec %4u%c/%s %s ", log_info ("sec %4u%c/%s %s ",
nbits_from_sk (sk), nbits_from_pk (pk),
pubkey_letter (sk->pubkey_algo), pubkey_letter (pk->pubkey_algo),
keystr_from_sk (sk), datestr_from_sk (sk)); keystr_from_pk (pk), datestr_from_pk (pk));
if (uidnode) if (uidnode)
print_utf8_buffer (log_get_stream (), uidnode->pkt->pkt.user_id->name, print_utf8_buffer (log_get_stream (), uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len); uidnode->pkt->pkt.user_id->len);
@ -1423,16 +1379,24 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
if (!uidnode) if (!uidnode)
{ {
log_error( _("key %s: no user ID\n"), keystr_from_sk(sk)); log_error( _("key %s: no user ID\n"), keystr_from_pk (pk));
return 0;
}
ski = pk->seckey_info;
if (!ski)
{
/* Actually an internal error. */
log_error ("key %s: secret key info missing\n", keystr_from_pk (pk));
return 0; return 0;
} }
/* A quick check to not import keys with an invalid protection /* A quick check to not import keys with an invalid protection
cipher algorithm (only checks the primary key, though). */ cipher algorithm (only checks the primary key, though). */
if (sk->protect.algo > 110) if (ski->algo > 110)
{ {
log_error (_("key %s: secret key with invalid cipher %d" log_error (_("key %s: secret key with invalid cipher %d"
" - skipped\n"),keystr_from_sk(sk),sk->protect.algo); " - skipped\n"), keystr_from_pk (pk), ski->algo);
return 0; return 0;
} }
@ -1447,9 +1411,9 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
} }
#endif #endif
clear_kbnode_flags( keyblock ); clear_kbnode_flags (keyblock);
if ( !(opt.import_options&IMPORT_MERGE_ONLY) ) if (!(options&IMPORT_MERGE_ONLY) || !have_secret_key_with_kid (keyid) )
{ {
/* We don't have this key, insert as a new key. */ /* We don't have this key, insert as a new key. */
kbnode_t pub_keyblock; kbnode_t pub_keyblock;
@ -1458,7 +1422,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
pub_keyblock = sec_to_pub_keyblock (keyblock); pub_keyblock = sec_to_pub_keyblock (keyblock);
if (!pub_keyblock) if (!pub_keyblock)
log_error ("key %s: failed to create public key from secret key\n", log_error ("key %s: failed to create public key from secret key\n",
keystr_from_sk (sk)); keystr_from_pk (pk));
else else
{ {
import_one (fname, pub_keyblock, stats, import_one (fname, pub_keyblock, stats,
@ -1474,29 +1438,29 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
node = get_pubkeyblock (keyid); node = get_pubkeyblock (keyid);
if (!node) if (!node)
log_error ("key %s: failed to re-lookup public key\n", log_error ("key %s: failed to re-lookup public key\n",
keystr_from_sk (sk)); keystr_from_pk (pk));
else else
{ {
if (!transfer_secret_keys (ctrl, stats, keyblock)) if (!transfer_secret_keys (ctrl, stats, keyblock))
{ {
if (!opt.quiet) if (!opt.quiet)
log_info (_("key %s: secret key imported\n"), log_info (_("key %s: secret key imported\n"),
keystr_from_sk (sk)); keystr_from_pk (pk));
if (is_status_enabled ()) if (is_status_enabled ())
print_import_ok (NULL, sk, 1|16); print_import_ok (pk, 1|16);
check_prefs (node); check_prefs (node);
} }
release_kbnode (node); release_kbnode (node);
} }
} }
} }
else if (have_secret_key_with_kid (keyid)) else
{ {
/* We don't want to merge the secret keys. */ /* We don't want to merge the secret keys. */
log_error( _("key %s: secret key part already available\n"), log_error (_("key %s: secret key part already available\n"),
keystr_from_sk(sk)); keystr_from_pk (pk));
if (is_status_enabled ()) if (is_status_enabled ())
print_import_ok (NULL, sk, 16); print_import_ok (pk, 16);
} }
return rc; return rc;
@ -2072,12 +2036,12 @@ collapse_uids( KBNODE *keyblock )
{ {
const char *key="???"; const char *key="???";
if( (uid1=find_kbnode( *keyblock, PKT_PUBLIC_KEY )) ) if ((uid1 = find_kbnode (*keyblock, PKT_PUBLIC_KEY)) )
key=keystr_from_pk(uid1->pkt->pkt.public_key); key = keystr_from_pk (uid1->pkt->pkt.public_key);
else if( (uid1 = find_kbnode( *keyblock, PKT_SECRET_KEY )) ) else if ((uid1 = find_kbnode( *keyblock, PKT_SECRET_KEY)) )
key=keystr_from_sk(uid1->pkt->pkt.secret_key); key = keystr_from_pk (uid1->pkt->pkt.public_key);
log_info(_("key %s: duplicated user ID detected - merged\n"),key); log_info (_("key %s: duplicated user ID detected - merged\n"), key);
} }
return any; return any;
@ -2308,8 +2272,8 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
/* do we have this in the original keyblock? */ /* do we have this in the original keyblock? */
for(onode=keyblock_orig->next; onode; onode=onode->next ) for(onode=keyblock_orig->next; onode; onode=onode->next )
if( onode->pkt->pkttype == PKT_SECRET_SUBKEY if( onode->pkt->pkttype == PKT_SECRET_SUBKEY
&& !cmp_secret_keys( onode->pkt->pkt.secret_key, && !cmp_public_keys (onode->pkt->pkt.public_key,
node->pkt->pkt.secret_key ) ) node->pkt->pkt.public_key) )
break; break;
if( !onode ) { /* this is a new subkey: append */ if( !onode ) { /* this is a new subkey: append */
rc = append_key( keyblock_orig, node, n_sigs, fname, keyid); rc = append_key( keyblock_orig, node, n_sigs, fname, keyid);
@ -2327,14 +2291,11 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
|| onode->pkt->pkttype == PKT_SECRET_SUBKEY) ) { || onode->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
/* find the subkey in the imported keyblock */ /* find the subkey in the imported keyblock */
for(node=keyblock->next; node; node=node->next ) { for(node=keyblock->next; node; node=node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY if ((node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY)
&& !cmp_public_keys( onode->pkt->pkt.public_key, && !cmp_public_keys( onode->pkt->pkt.public_key,
node->pkt->pkt.public_key ) ) node->pkt->pkt.public_key ) )
break; break;
else if( node->pkt->pkttype == PKT_SECRET_SUBKEY
&& !cmp_secret_keys( onode->pkt->pkt.secret_key,
node->pkt->pkt.secret_key ) )
break;
} }
if( node ) { /* found: merge */ if( node ) { /* found: merge */
rc = merge_keysigs( onode, node, n_sigs, fname, keyid ); rc = merge_keysigs( onode, node, n_sigs, fname, keyid );
@ -2497,8 +2458,9 @@ merge_keysigs (KBNODE dst, KBNODE src, int *n_sigs,
return 0; return 0;
} }
/****************
* append the subkey starting with NODE and all signatures to KEYBLOCK. /*
* Append the subkey starting with NODE and all signatures to KEYBLOCK.
* Mark all new and copied packets by setting flag bit 0. * Mark all new and copied packets by setting flag bit 0.
*/ */
static int static int
@ -2530,233 +2492,3 @@ append_key (KBNODE keyblock, KBNODE node, int *n_sigs,
return 0; return 0;
} }
/* Walk a public keyblock and produce a secret keyblock out of it.
Instead of inserting the secret key parameters (which we don't
have), we insert a stub. */
static KBNODE
pub_to_sec_keyblock (KBNODE pub_keyblock)
{
KBNODE pubnode, secnode;
KBNODE sec_keyblock = NULL;
KBNODE walkctx = NULL;
while((pubnode = walk_kbnode (pub_keyblock,&walkctx,0)))
{
if (pubnode->pkt->pkttype == PKT_PUBLIC_KEY
|| pubnode->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
/* Make a secret key. We only need to convert enough to
write the keyblock out. */
PKT_public_key *pk = pubnode->pkt->pkt.public_key;
PACKET *pkt = xmalloc_clear (sizeof *pkt);
PKT_secret_key *sk = xmalloc_clear (sizeof *sk);
int i, n;
if (pubnode->pkt->pkttype == PKT_PUBLIC_KEY)
pkt->pkttype = PKT_SECRET_KEY;
else
pkt->pkttype = PKT_SECRET_SUBKEY;
pkt->pkt.secret_key = sk;
copy_public_parts_to_secret_key ( pk, sk );
sk->version = pk->version;
sk->timestamp = pk->timestamp;
n = pubkey_get_npkey (pk->pubkey_algo);
if (!n)
n = 1; /* Unknown number of parameters, however the data
is stored in the first mpi. */
for (i=0; i < n; i++ )
sk->skey[i] = mpi_copy (pk->pkey[i]);
sk->is_protected = 1;
sk->protect.s2k.mode = 1001;
secnode = new_kbnode (pkt);
}
else
{
secnode = clone_kbnode (pubnode);
}
if(!sec_keyblock)
sec_keyblock = secnode;
else
add_kbnode (sec_keyblock, secnode);
}
return sec_keyblock;
}
/* Walk over the secret keyring SEC_KEYBLOCK and update any simple
stub keys with the serial number SNNUM of the card if one of the
fingerprints FPR1, FPR2 or FPR3 match. Print a note if the key is
a duplicate (may happen in case of backed uped keys).
Returns: True if anything changed.
*/
static int
update_sec_keyblock_with_cardinfo (KBNODE sec_keyblock,
const unsigned char *fpr1,
const unsigned char *fpr2,
const unsigned char *fpr3,
const char *serialnostr)
{
KBNODE node;
KBNODE walkctx = NULL;
PKT_secret_key *sk;
byte array[MAX_FINGERPRINT_LEN];
size_t n;
int result = 0;
const char *s;
while((node = walk_kbnode (sec_keyblock, &walkctx, 0)))
{
if (node->pkt->pkttype != PKT_SECRET_KEY
&& node->pkt->pkttype != PKT_SECRET_SUBKEY)
continue;
sk = node->pkt->pkt.secret_key;
fingerprint_from_sk (sk, array, &n);
if (n != 20)
continue; /* Can't be a card key. */
if ( !((fpr1 && !memcmp (array, fpr1, 20))
|| (fpr2 && !memcmp (array, fpr2, 20))
|| (fpr3 && !memcmp (array, fpr3, 20))) )
continue; /* No match. */
if (sk->is_protected == 1 && sk->protect.s2k.mode == 1001)
{
/* Standard case: migrate that stub to a key stub. */
sk->protect.s2k.mode = 1002;
s = serialnostr;
for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1];
sk->protect.ivlen++, s += 2)
sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s);
result = 1;
}
else if (sk->is_protected == 1 && sk->protect.s2k.mode == 1002)
{
s = serialnostr;
for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1];
sk->protect.ivlen++, s += 2)
if (sk->protect.iv[sk->protect.ivlen] != xtoi_2 (s))
{
log_info (_("NOTE: a key's S/N does not "
"match the card's one\n"));
break;
}
}
else
{
if (node->pkt->pkttype != PKT_SECRET_KEY)
log_info (_("NOTE: primary key is online and stored on card\n"));
else
log_info (_("NOTE: secondary key is online and stored on card\n"));
}
}
return result;
}
/* Check whether a secret key stub exists for the public key PK. If
not create such a stub key and store it into the secring. If it
exists, add appropriate subkey stubs and update the secring.
Return 0 if the key could be created. */
int
auto_create_card_key_stub ( const char *serialnostr,
const unsigned char *fpr1,
const unsigned char *fpr2,
const unsigned char *fpr3)
{
KBNODE pub_keyblock;
KBNODE sec_keyblock;
KEYDB_HANDLE hd;
int rc;
/* We only want to do this for an OpenPGP card. */
if (!serialnostr || strncmp (serialnostr, "D27600012401", 12)
|| strlen (serialnostr) != 32 )
return G10ERR_GENERAL;
/* First get the public keyring from any of the provided fingerprints. */
if ( (fpr1 && !get_keyblock_byfprint (&pub_keyblock, fpr1, 20))
|| (fpr2 && !get_keyblock_byfprint (&pub_keyblock, fpr2, 20))
|| (fpr3 && !get_keyblock_byfprint (&pub_keyblock, fpr3, 20)))
;
else
return G10ERR_GENERAL;
log_debug ("FIXME: Do we need the stub at all?\n");
hd = keydb_new (); /* FIXME. */
/* Now check whether there is a secret keyring. */
{
PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
byte afp[MAX_FINGERPRINT_LEN];
size_t an;
fingerprint_from_pk (pk, afp, &an);
if (an < MAX_FINGERPRINT_LEN)
memset (afp+an, 0, MAX_FINGERPRINT_LEN-an);
rc = keydb_search_fpr (hd, afp);
}
if (!rc)
{
rc = keydb_get_keyblock (hd, &sec_keyblock);
if (rc)
{
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
rc = G10ERR_GENERAL;
}
else
{
merge_keys_and_selfsig (sec_keyblock);
/* FIXME: We need to add new subkeys first. */
if (update_sec_keyblock_with_cardinfo (sec_keyblock,
fpr1, fpr2, fpr3,
serialnostr))
{
rc = keydb_update_keyblock (hd, sec_keyblock );
if (rc)
log_error (_("error writing keyring `%s': %s\n"),
keydb_get_resource_name (hd), g10_errstr(rc) );
}
}
}
else /* A secret key does not exists - create it. */
{
sec_keyblock = pub_to_sec_keyblock (pub_keyblock);
update_sec_keyblock_with_cardinfo (sec_keyblock,
fpr1, fpr2, fpr3,
serialnostr);
rc = keydb_locate_writable (hd, NULL);
if (rc)
{
log_error (_("no default secret keyring: %s\n"), g10_errstr (rc));
rc = G10ERR_GENERAL;
}
else
{
rc = keydb_insert_keyblock (hd, sec_keyblock );
if (rc)
log_error (_("error writing keyring `%s': %s\n"),
keydb_get_resource_name (hd), g10_errstr(rc) );
}
}
release_kbnode (sec_keyblock);
release_kbnode (pub_keyblock);
keydb_release (hd);
return rc;
}

View File

@ -195,7 +195,7 @@ void set_next_passphrase( const char *s );
char *get_last_passphrase(void); char *get_last_passphrase(void);
void next_to_last_passphrase(void); void next_to_last_passphrase(void);
char *gpg_format_keydesc (PKT_public_key *pk, int escaped); char *gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped);
/*-- getkey.c --*/ /*-- getkey.c --*/
@ -241,8 +241,8 @@ void getkey_end (getkey_ctx_t ctx);
int have_any_secret_key (ctrl_t ctrl, kbnode_t keyblock); int have_any_secret_key (ctrl_t ctrl, kbnode_t keyblock);
int enum_secret_keys( void **context, PKT_secret_key *sk, //int enum_secret_keys( void **context, PKT_secret_key *sk,
int with_subkeys, int with_spm ); // int with_subkeys, int with_spm );
void merge_keys_and_selfsig( KBNODE keyblock ); void merge_keys_and_selfsig( KBNODE keyblock );
char*get_user_id_string( u32 *keyid ); char*get_user_id_string( u32 *keyid );
char*get_user_id_string_native( u32 *keyid ); char*get_user_id_string_native( u32 *keyid );
@ -263,34 +263,23 @@ const char *keystr_with_sub (u32 *main_kid, u32 *sub_kid);
const char *keystr_from_pk(PKT_public_key *pk); const char *keystr_from_pk(PKT_public_key *pk);
const char *keystr_from_pk_with_sub (PKT_public_key *main_pk, const char *keystr_from_pk_with_sub (PKT_public_key *main_pk,
PKT_public_key *sub_pk); PKT_public_key *sub_pk);
const char *keystr_from_sk(PKT_secret_key *sk);
const char *keystr_from_sk_with_sub (PKT_secret_key *main_sk,
PKT_secret_key *sub_sk);
const char *keystr_from_desc(KEYDB_SEARCH_DESC *desc); const char *keystr_from_desc(KEYDB_SEARCH_DESC *desc);
u32 keyid_from_sk( PKT_secret_key *sk, u32 *keyid );
u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid ); u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid );
u32 keyid_from_sig( PKT_signature *sig, u32 *keyid ); u32 keyid_from_sig( PKT_signature *sig, u32 *keyid );
u32 keyid_from_fingerprint(const byte *fprint, size_t fprint_len, u32 *keyid); u32 keyid_from_fingerprint(const byte *fprint, size_t fprint_len, u32 *keyid);
byte *namehash_from_uid(PKT_user_id *uid); byte *namehash_from_uid(PKT_user_id *uid);
unsigned nbits_from_pk( PKT_public_key *pk ); unsigned nbits_from_pk( PKT_public_key *pk );
unsigned nbits_from_sk( PKT_secret_key *sk );
const char *datestr_from_pk( PKT_public_key *pk ); const char *datestr_from_pk( PKT_public_key *pk );
const char *datestr_from_sk( PKT_secret_key *sk );
const char *datestr_from_sig( PKT_signature *sig ); const char *datestr_from_sig( PKT_signature *sig );
const char *expirestr_from_pk( PKT_public_key *pk ); const char *expirestr_from_pk( PKT_public_key *pk );
const char *expirestr_from_sk( PKT_secret_key *sk );
const char *expirestr_from_sig( PKT_signature *sig ); const char *expirestr_from_sig( PKT_signature *sig );
const char *revokestr_from_pk( PKT_public_key *pk ); const char *revokestr_from_pk( PKT_public_key *pk );
const char *usagestr_from_pk( PKT_public_key *pk ); const char *usagestr_from_pk( PKT_public_key *pk );
const char *colon_strtime (u32 t); const char *colon_strtime (u32 t);
const char *colon_datestr_from_pk (PKT_public_key *pk); const char *colon_datestr_from_pk (PKT_public_key *pk);
const char *colon_datestr_from_sk (PKT_secret_key *sk);
const char *colon_datestr_from_sig (PKT_signature *sig); const char *colon_datestr_from_sig (PKT_signature *sig);
const char *colon_expirestr_from_sig (PKT_signature *sig); const char *colon_expirestr_from_sig (PKT_signature *sig);
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,
PKT_secret_key *sk);
gpg_error_t keygrip_from_pk (PKT_public_key *pk, unsigned char *array); 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); gpg_error_t hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip);

View File

@ -2924,7 +2924,9 @@ show_key_with_all_names (KBNODE keyblock, int only_marked, int with_revoker,
keyid_from_pk (pk, NULL); keyid_from_pk (pk, NULL);
tty_printf ("%s%c %4u%c/%s ", tty_printf ("%s%c %4u%c/%s ",
node->pkt->pkttype == PKT_PUBLIC_KEY ? "pub" : "sub", node->pkt->pkttype == PKT_PUBLIC_KEY ? "pub" :
node->pkt->pkttype == PKT_PUBLIC_SUBKEY ? "sub" :
node->pkt->pkttype == PKT_SECRET_KEY ? "sec" : "ssb",
(node->flag & NODFLG_SELKEY) ? '*' : ' ', (node->flag & NODFLG_SELKEY) ? '*' : ' ',
nbits_from_pk (pk), nbits_from_pk (pk),
pubkey_letter (pk->pubkey_algo), keystr (pk->keyid)); pubkey_letter (pk->pubkey_algo), keystr (pk->keyid));
@ -2941,7 +2943,35 @@ show_key_with_all_names (KBNODE keyblock, int only_marked, int with_revoker,
tty_printf (_("usage: %s"), usagestr_from_pk (pk)); tty_printf (_("usage: %s"), usagestr_from_pk (pk));
tty_printf ("\n"); tty_printf ("\n");
if (node->pkt->pkttype == PKT_PUBLIC_KEY) if (pk->seckey_info
&& pk->seckey_info->is_protected
&& pk->seckey_info->s2k.mode == 1002)
{
tty_printf (" ");
tty_printf (_("card-no: "));
if (pk->seckey_info->ivlen == 16
&& !memcmp (pk->seckey_info->iv,
"\xD2\x76\x00\x01\x24\x01", 6))
{
/* This is an OpenPGP card. */
for (i = 8; i < 14; i++)
{
if (i == 10)
tty_printf (" ");
tty_printf ("%02X", pk->seckey_info->iv[i]);
}
}
else
{
/* Unknown card: Print all. */
for (i = 0; i < pk->seckey_info->ivlen; i++)
tty_printf ("%02X", pk->seckey_info->iv[i]);
}
tty_printf ("\n");
}
if (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_SECRET_KEY)
{ {
if (opt.trust_model != TM_ALWAYS) if (opt.trust_model != TM_ALWAYS)
{ {
@ -2970,47 +3000,13 @@ show_key_with_all_names (KBNODE keyblock, int only_marked, int with_revoker,
} }
} }
if (node->pkt->pkttype == PKT_PUBLIC_KEY && with_fpr) if ((node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_SECRET_KEY) && with_fpr)
{ {
print_fingerprint (pk, 2); print_fingerprint (pk, 2);
tty_printf ("\n"); tty_printf ("\n");
} }
} }
else if (node->pkt->pkttype == PKT_SECRET_KEY
|| (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY))
{
PKT_secret_key *sk = node->pkt->pkt.secret_key;
tty_printf ("%s%c %4u%c/%s ",
node->pkt->pkttype == PKT_SECRET_KEY ? "sec" : "ssb",
(node->flag & NODFLG_SELKEY) ? '*' : ' ',
nbits_from_sk (sk),
pubkey_letter (sk->pubkey_algo), keystr_from_sk (sk));
tty_printf (_("created: %s"), datestr_from_sk (sk));
tty_printf (" ");
tty_printf (_("expires: %s"), expirestr_from_sk (sk));
tty_printf ("\n");
if (sk->is_protected && sk->protect.s2k.mode == 1002)
{
tty_printf (" ");
tty_printf (_("card-no: "));
if (sk->protect.ivlen == 16
&& !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6))
{ /* This is an OpenPGP card. */
for (i = 8; i < 14; i++)
{
if (i == 10)
tty_printf (" ");
tty_printf ("%02X", sk->protect.iv[i]);
}
}
else
{ /* Something is wrong: Print all. */
for (i = 0; i < sk->protect.ivlen; i++)
tty_printf ("%02X", sk->protect.iv[i]);
}
tty_printf ("\n");
}
}
} }
show_names (keyblock, primary, only_marked ? NODFLG_MARK_A : 0, with_prefs); show_names (keyblock, primary, only_marked ? NODFLG_MARK_A : 0, with_prefs);
@ -3035,14 +3031,17 @@ show_basic_key_info (KBNODE keyblock)
/* The primary key */ /* The primary key */
for (node = keyblock; node; node = node->next) for (node = keyblock; node; node = node->next)
{ {
if (node->pkt->pkttype == PKT_PUBLIC_KEY) if (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_SECRET_KEY)
{ {
PKT_public_key *pk = node->pkt->pkt.public_key; PKT_public_key *pk = node->pkt->pkt.public_key;
/* Note, we use the same format string as in other show /* Note, we use the same format string as in other show
functions to make the translation job easier. */ functions to make the translation job easier. */
tty_printf ("%s %4u%c/%s ", tty_printf ("%s %4u%c/%s ",
node->pkt->pkttype == PKT_PUBLIC_KEY ? "pub" : "sub", node->pkt->pkttype == PKT_PUBLIC_KEY ? "pub" :
node->pkt->pkttype == PKT_PUBLIC_SUBKEY ? "sub" :
node->pkt->pkttype == PKT_SECRET_KEY ? "sec" :"ssb",
nbits_from_pk (pk), nbits_from_pk (pk),
pubkey_letter (pk->pubkey_algo), keystr_from_pk (pk)); pubkey_letter (pk->pubkey_algo), keystr_from_pk (pk));
tty_printf (_("created: %s"), datestr_from_pk (pk)); tty_printf (_("created: %s"), datestr_from_pk (pk));
@ -3052,21 +3051,6 @@ show_basic_key_info (KBNODE keyblock)
print_fingerprint (pk, 3); print_fingerprint (pk, 3);
tty_printf ("\n"); tty_printf ("\n");
} }
else if (node->pkt->pkttype == PKT_SECRET_KEY)
{
PKT_secret_key *sk = node->pkt->pkt.secret_key;
tty_printf ("%s %4u%c/%s",
node->pkt->pkttype == PKT_SECRET_KEY ? "sec" : "ssb",
nbits_from_sk (sk),
pubkey_letter (sk->pubkey_algo), keystr_from_sk (sk));
tty_printf (_("created: %s"), datestr_from_sk (sk));
tty_printf (" ");
tty_printf (_("expires: %s"), expirestr_from_sk (sk));
tty_printf ("\n");
log_debug ("FIXME\n");
/* print_fingerprint (NULL, sk, 3); */
tty_printf ("\n");
}
} }
/* The user IDs. */ /* The user IDs. */

View File

@ -38,10 +38,12 @@
#define KEYID_STR_SIZE 19 #define KEYID_STR_SIZE 19
/* Return a letter describing the public key algorithms. */
int int
pubkey_letter( int algo ) pubkey_letter( int algo )
{ {
switch( algo ) { switch (algo)
{
case PUBKEY_ALGO_RSA: return 'R' ; case PUBKEY_ALGO_RSA: return 'R' ;
case PUBKEY_ALGO_RSA_E: return 'r' ; case PUBKEY_ALGO_RSA_E: return 'r' ;
case PUBKEY_ALGO_RSA_S: return 's' ; case PUBKEY_ALGO_RSA_S: return 's' ;
@ -52,10 +54,11 @@ pubkey_letter( int algo )
} }
} }
/* This function is useful for v4 fingerprints and v3 or v4 key
signing. */ /* Hash a public key. This function is useful for v4 fingerprints and
for v3 or v4 key signing. */
void void
hash_public_key( gcry_md_hd_t md, PKT_public_key *pk ) hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
{ {
unsigned int n = 6; unsigned int n = 6;
unsigned int nn[PUBKEY_MAX_NPKEY]; unsigned int nn[PUBKEY_MAX_NPKEY];
@ -77,6 +80,7 @@ hash_public_key( gcry_md_hd_t md, PKT_public_key *pk )
n+=nn[0]; n+=nn[0];
} }
else else
{
for(i=0; i < npkey; i++ ) for(i=0; i < npkey; i++ )
{ {
if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i])) if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i]))
@ -88,6 +92,7 @@ hash_public_key( gcry_md_hd_t md, PKT_public_key *pk )
nn[i] = nbytes; nn[i] = nbytes;
n += nn[i]; n += nn[i];
} }
}
gcry_md_putc ( md, 0x99 ); /* ctb */ gcry_md_putc ( md, 0x99 ); /* ctb */
/* What does it mean if n is greater than than 0xFFFF ? */ /* What does it mean if n is greater than than 0xFFFF ? */
@ -125,6 +130,7 @@ hash_public_key( gcry_md_hd_t md, PKT_public_key *pk )
} }
} }
static gcry_md_hd_t static gcry_md_hd_t
do_fingerprint_md( PKT_public_key *pk ) do_fingerprint_md( PKT_public_key *pk )
{ {
@ -138,27 +144,9 @@ do_fingerprint_md( PKT_public_key *pk )
return md; return md;
} }
static gcry_md_hd_t
do_fingerprint_md_sk( PKT_secret_key *sk )
{
PKT_public_key pk;
int npkey = pubkey_get_npkey( sk->pubkey_algo ); /* npkey is correct! */
int i;
if(npkey==0)
return NULL;
pk.pubkey_algo = sk->pubkey_algo;
pk.version = sk->version;
pk.timestamp = sk->timestamp;
pk.expiredate = sk->expiredate;
pk.pubkey_algo = sk->pubkey_algo;
for( i=0; i < npkey; i++ )
pk.pkey[i] = sk->skey[i];
return do_fingerprint_md( &pk );
}
/* fixme: Check whether we can replace this function or if not
describe why we need it. */
u32 u32
v3_keyid (gcry_mpi_t a, u32 *ki) v3_keyid (gcry_mpi_t a, u32 *ki)
{ {
@ -280,24 +268,6 @@ keystr_from_pk_with_sub (PKT_public_key *main_pk, PKT_public_key *sub_pk)
} }
const char *
keystr_from_sk(PKT_secret_key *sk)
{
keyid_from_sk (sk,NULL);
return keystr(sk->keyid);
}
const char *
keystr_from_sk_with_sub (PKT_secret_key *main_sk, PKT_secret_key *sub_sk)
{
keyid_from_sk (main_sk, NULL);
keyid_from_sk (sub_sk, NULL);
return keystr_with_sub (main_sk->keyid, sub_sk->keyid);
}
const char * const char *
keystr_from_desc(KEYDB_SEARCH_DESC *desc) keystr_from_desc(KEYDB_SEARCH_DESC *desc)
@ -332,72 +302,18 @@ keystr_from_desc(KEYDB_SEARCH_DESC *desc)
} }
} }
/****************
* Get the keyid from the secret key and put it into keyid
* if this is not NULL. Return the 32 low bits of the keyid.
*/
u32
keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
{
u32 lowbits;
u32 dummy_keyid[2];
if( !keyid ) /*
keyid = dummy_keyid;
if( sk->keyid[0] || sk->keyid[1] )
{
keyid[0] = sk->keyid[0];
keyid[1] = sk->keyid[1];
lowbits = keyid[1];
}
else if( sk->version < 4 )
{
if( is_RSA(sk->pubkey_algo) )
{
lowbits = (pubkey_get_npkey (sk->pubkey_algo) ?
v3_keyid( sk->skey[0], keyid ) : 0); /* Take n. */
sk->keyid[0]=keyid[0];
sk->keyid[1]=keyid[1];
}
else
sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF;
}
else
{
const byte *dp;
gcry_md_hd_t md;
md = do_fingerprint_md_sk(sk);
if(md)
{
dp = gcry_md_read (md, 0);
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
lowbits = keyid[1];
gcry_md_close (md);
sk->keyid[0] = keyid[0];
sk->keyid[1] = keyid[1];
}
else
sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF;
}
return lowbits;
}
/****************
* Get the keyid from the public key and put it into keyid * Get the keyid from the public key and put it into keyid
* if this is not NULL. Return the 32 low bits of the keyid. * if this is not NULL. Return the 32 low bits of the keyid.
*/ */
u32 u32
keyid_from_pk( PKT_public_key *pk, u32 *keyid ) keyid_from_pk (PKT_public_key *pk, u32 *keyid)
{ {
u32 lowbits; u32 lowbits;
u32 dummy_keyid[2]; u32 dummy_keyid[2];
if( !keyid ) if (!keyid)
keyid = dummy_keyid; keyid = dummy_keyid;
if( pk->keyid[0] || pk->keyid[1] ) if( pk->keyid[0] || pk->keyid[1] )
@ -442,7 +358,7 @@ keyid_from_pk( PKT_public_key *pk, u32 *keyid )
} }
/**************** /*
* Get the keyid from the fingerprint. This function is simple for most * Get the keyid from the fingerprint. This function is simple for most
* keys, but has to do a keylookup for old stayle keys. * keys, but has to do a keylookup for old stayle keys.
*/ */
@ -454,22 +370,25 @@ keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
if( !keyid ) if( !keyid )
keyid = dummy_keyid; keyid = dummy_keyid;
if( fprint_len != 20 ) { if (fprint_len != 20)
/* This is special as we have to lookup the key first */ {
/* This is special as we have to lookup the key first. */
PKT_public_key pk; PKT_public_key pk;
int rc; int rc;
memset( &pk, 0, sizeof pk ); memset (&pk, 0, sizeof pk);
rc = get_pubkey_byfprint( &pk, fprint, fprint_len ); rc = get_pubkey_byfprint (&pk, fprint, fprint_len);
if( rc ) { if( rc )
{
log_error("Oops: keyid_from_fingerprint: no pubkey\n"); log_error("Oops: keyid_from_fingerprint: no pubkey\n");
keyid[0] = 0; keyid[0] = 0;
keyid[1] = 0; keyid[1] = 0;
} }
else else
keyid_from_pk( &pk, keyid ); keyid_from_pk (&pk, keyid);
} }
else { else
{
const byte *dp = fprint; const byte *dp = fprint;
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ; keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ; keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
@ -480,23 +399,25 @@ keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
u32 u32
keyid_from_sig( PKT_signature *sig, u32 *keyid ) keyid_from_sig (PKT_signature *sig, u32 *keyid)
{ {
if( keyid ) { if( keyid )
{
keyid[0] = sig->keyid[0]; keyid[0] = sig->keyid[0];
keyid[1] = sig->keyid[1]; keyid[1] = sig->keyid[1];
} }
return sig->keyid[1]; return sig->keyid[1];
} }
byte * byte *
namehash_from_uid(PKT_user_id *uid) namehash_from_uid (PKT_user_id *uid)
{ {
if (!uid->namehash) if (!uid->namehash)
{ {
uid->namehash = xmalloc (20); uid->namehash = xmalloc (20);
if(uid->attrib_data) if (uid->attrib_data)
rmd160_hash_buffer (uid->namehash, uid->attrib_data, uid->attrib_len); rmd160_hash_buffer (uid->namehash, uid->attrib_data, uid->attrib_len);
else else
rmd160_hash_buffer (uid->namehash, uid->name, uid->len); rmd160_hash_buffer (uid->namehash, uid->name, uid->len);
@ -505,23 +426,16 @@ namehash_from_uid(PKT_user_id *uid)
return uid->namehash; return uid->namehash;
} }
/****************
* return the number of bits used in the pk /*
* Return the number of bits used in PK.
*/ */
unsigned unsigned int
nbits_from_pk( PKT_public_key *pk ) nbits_from_pk (PKT_public_key *pk)
{ {
return pubkey_nbits( pk->pubkey_algo, pk->pkey ); return pubkey_nbits (pk->pubkey_algo, pk->pkey);
} }
/****************
* return the number of bits used in the sk
*/
unsigned
nbits_from_sk( PKT_secret_key *sk )
{
return pubkey_nbits( sk->pubkey_algo, sk->skey );
}
static const char * static const char *
mk_datestr (char *buffer, time_t atime) mk_datestr (char *buffer, time_t atime)
@ -530,7 +444,8 @@ mk_datestr (char *buffer, time_t atime)
if ( atime < 0 ) /* 32 bit time_t and after 2038-01-19 */ if ( atime < 0 ) /* 32 bit time_t and after 2038-01-19 */
strcpy (buffer, "????" "-??" "-??"); /* mark this as invalid */ strcpy (buffer, "????" "-??" "-??"); /* mark this as invalid */
else { else
{
tp = gmtime (&atime); tp = gmtime (&atime);
sprintf (buffer,"%04d-%02d-%02d", sprintf (buffer,"%04d-%02d-%02d",
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday ); 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
@ -538,13 +453,14 @@ mk_datestr (char *buffer, time_t atime)
return buffer; return buffer;
} }
/****************
/*
* return a string with the creation date of the pk * return a string with the creation date of the pk
* Note: this is alloced in a static buffer. * Note: this is alloced in a static buffer.
* Format is: yyyy-mm-dd * Format is: yyyy-mm-dd
*/ */
const char * const char *
datestr_from_pk( PKT_public_key *pk ) datestr_from_pk (PKT_public_key *pk)
{ {
static char buffer[11+5]; static char buffer[11+5];
time_t atime = pk->timestamp; time_t atime = pk->timestamp;
@ -552,17 +468,9 @@ datestr_from_pk( PKT_public_key *pk )
return mk_datestr (buffer, atime); return mk_datestr (buffer, atime);
} }
const char *
datestr_from_sk( PKT_secret_key *sk )
{
static char buffer[11+5];
time_t atime = sk->timestamp;
return mk_datestr (buffer, atime);
}
const char * const char *
datestr_from_sig( PKT_signature *sig ) datestr_from_sig (PKT_signature *sig )
{ {
static char buffer[11+5]; static char buffer[11+5];
time_t atime = sig->timestamp; time_t atime = sig->timestamp;
@ -570,42 +478,33 @@ datestr_from_sig( PKT_signature *sig )
return mk_datestr (buffer, atime); return mk_datestr (buffer, atime);
} }
const char * const char *
expirestr_from_pk( PKT_public_key *pk ) expirestr_from_pk (PKT_public_key *pk)
{ {
static char buffer[11+5]; static char buffer[11+5];
time_t atime; time_t atime;
if( !pk->expiredate ) if (!pk->expiredate)
return _("never "); return _("never ");
atime = pk->expiredate; atime = pk->expiredate;
return mk_datestr (buffer, atime); return mk_datestr (buffer, atime);
} }
const char * const char *
expirestr_from_sk( PKT_secret_key *sk ) expirestr_from_sig (PKT_signature *sig)
{ {
static char buffer[11+5]; static char buffer[11+5];
time_t atime; time_t atime;
if( !sk->expiredate ) if (!sig->expiredate)
return _("never ");
atime = sk->expiredate;
return mk_datestr (buffer, atime);
}
const char *
expirestr_from_sig( PKT_signature *sig )
{
static char buffer[11+5];
time_t atime;
if(!sig->expiredate)
return _("never "); return _("never ");
atime=sig->expiredate; atime=sig->expiredate;
return mk_datestr (buffer, atime); return mk_datestr (buffer, atime);
} }
const char * const char *
revokestr_from_pk( PKT_public_key *pk ) revokestr_from_pk( PKT_public_key *pk )
{ {
@ -666,14 +565,6 @@ colon_datestr_from_pk (PKT_public_key *pk)
return buf; return buf;
} }
const char *
colon_datestr_from_sk (PKT_secret_key *sk)
{
static char buf[20];
snprintf (buf, sizeof buf, "%lu", (ulong)sk->timestamp);
return buf;
}
const char * const char *
colon_datestr_from_sig (PKT_signature *sig) colon_datestr_from_sig (PKT_signature *sig)
@ -697,14 +588,13 @@ colon_expirestr_from_sig (PKT_signature *sig)
} }
/**************** . /*
* Return a byte array with the fingerprint for the given PK/SK * Return a byte array with the fingerprint for the given PK/SK
* The length of the array is returned in ret_len. Caller must free * The length of the array is returned in ret_len. Caller must free
* the array or provide an array of length MAX_FINGERPRINT_LEN. * the array or provide an array of length MAX_FINGERPRINT_LEN.
*/ */
byte * byte *
fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len ) fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
{ {
byte *buf; byte *buf;
const byte *dp; const byte *dp;
@ -771,105 +661,7 @@ fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
return array; return array;
} }
byte *
fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len )
{
byte *buf;
const char *dp;
size_t len, nbytes;
int i;
if (sk->version < 4)
{
if ( is_RSA(sk->pubkey_algo) )
{
/* RSA in version 3 packets is special. */
gcry_md_hd_t md;
if (gcry_md_open (&md, DIGEST_ALGO_MD5, 0))
BUG ();
if (pubkey_get_npkey( sk->pubkey_algo ) > 1)
{
for (i=0; i < 2; i++)
{
if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0,
&nbytes, sk->skey[i]))
BUG ();
/* fixme: Better allocate BUF on the stack */
buf = xmalloc (nbytes);
if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes,
NULL, sk->skey[i]))
BUG ();
gcry_md_write (md, buf, nbytes);
xfree (buf);
}
}
gcry_md_final(md);
if (!array)
array = xmalloc (16);
len = 16;
memcpy (array, gcry_md_read (md, DIGEST_ALGO_MD5), 16);
gcry_md_close (md);
}
else
{
if (!array)
array = xmalloc (16);
len=16;
memset (array,0,16);
}
}
else
{
gcry_md_hd_t md;
md = do_fingerprint_md_sk(sk);
if (md)
{
dp = gcry_md_read ( md, 0 );
len = gcry_md_get_algo_dlen ( gcry_md_get_algo (md) );
assert ( len <= MAX_FINGERPRINT_LEN );
if (!array)
array = xmalloc( len );
memcpy (array, dp, len);
gcry_md_close (md);
}
else
{
len = MAX_FINGERPRINT_LEN;
if (!array)
array = xmalloc (len);
memset (array, 0, len);
}
}
*ret_len = len;
return array;
}
/* Create a serialno/fpr string from the serial number and the secret
key. Caller must free the returned string. There is no error
return. */
char *
serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
PKT_secret_key *sk)
{
unsigned char fpr[MAX_FINGERPRINT_LEN];
size_t fprlen;
char *buffer, *p;
int i;
fingerprint_from_sk (sk, fpr, &fprlen);
buffer = p = xmalloc (snlen*2 + 1 + fprlen*2 + 1);
for (i=0; i < snlen; i++, p+=2)
sprintf (p, "%02X", sn[i]);
*p++ = '/';
for (i=0; i < fprlen; i++, p+=2)
sprintf (p, "%02X", fpr[i]);
*p = 0;
return buffer;
}

View File

@ -44,7 +44,7 @@
static void list_all (int); static void list_all (int);
static void list_one (strlist_t names, int secret); static void list_one (strlist_t names, int secret);
static void locate_one (strlist_t names); static void locate_one (strlist_t names);
static void print_card_serialno (PKT_secret_key * sk); static void print_card_serialno (PKT_public_key *sk);
struct sig_stats struct sig_stats
{ {
@ -174,52 +174,53 @@ print_pubkey_info (estream_t fp, PKT_public_key * pk)
/* Print basic information of a secret key including the card serial /* Print basic information of a secret key including the card serial
number information. */ number information. */
void void
print_card_key_info (estream_t fp, KBNODE keyblock) print_card_key_info (estream_t fp, kbnode_t keyblock)
{ {
KBNODE node; /* KBNODE node; */
int i; /* int i; */
for (node = keyblock; node; node = node->next) log_debug ("Fixme: Needs to be adjusted to gpg-agent\n");
{ /* for (node = keyblock; node; node = node->next) */
if (node->pkt->pkttype == PKT_SECRET_KEY /* { */
|| (node->pkt->pkttype == PKT_SECRET_SUBKEY)) /* if (node->pkt->pkttype == PKT_SECRET_KEY */
{ /* || (node->pkt->pkttype == PKT_SECRET_SUBKEY)) */
PKT_secret_key *sk = node->pkt->pkt.secret_key; /* { */
/* PKT_public_key *pk = node->pkt->pkt.public_key; */
tty_fprintf (fp, "%s%c %4u%c/%s ", /* tty_fprintf (fp, "%s%c %4u%c/%s ", */
node->pkt->pkttype == PKT_SECRET_KEY ? "sec" : "ssb", /* node->pkt->pkttype == PKT_SECRET_KEY ? "sec" : "ssb", */
(sk->protect.s2k.mode == 1001) ? '#' : /* (sk->protect.s2k.mode == 1001) ? '#' : */
(sk->protect.s2k.mode == 1002) ? '>' : ' ', /* (sk->protect.s2k.mode == 1002) ? '>' : ' ', */
nbits_from_sk (sk), /* nbits_from_sk (sk), */
pubkey_letter (sk->pubkey_algo), keystr_from_sk (sk)); /* pubkey_letter (sk->pubkey_algo), keystr_from_sk (sk)); */
tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk)); /* tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk)); */
tty_fprintf (fp, " "); /* tty_fprintf (fp, " "); */
tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk)); /* tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk)); */
if (sk->is_protected && sk->protect.s2k.mode == 1002) /* if (sk->is_protected && sk->protect.s2k.mode == 1002) */
{ /* { */
tty_fprintf (fp, "\n "); /* tty_fprintf (fp, "\n "); */
tty_fprintf (fp, _("card-no: ")); /* tty_fprintf (fp, _("card-no: ")); */
if (sk->protect.ivlen == 16 /* if (sk->protect.ivlen == 16 */
&& !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) /* && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) */
{ /* { */
/* This is an OpenPGP card. */ /* /\* This is an OpenPGP card. *\/ */
for (i = 8; i < 14; i++) /* for (i = 8; i < 14; i++) */
{ /* { */
if (i == 10) /* if (i == 10) */
tty_fprintf (fp, " "); /* tty_fprintf (fp, " "); */
tty_fprintf (fp, "%02X", sk->protect.iv[i]); /* tty_fprintf (fp, "%02X", sk->protect.iv[i]); */
} /* } */
} /* } */
else /* else */
{ /* { */
/* Something is wrong: Print all. */ /* /\* Something is wrong: Print all. *\/ */
for (i = 0; i < sk->protect.ivlen; i++) /* for (i = 0; i < sk->protect.ivlen; i++) */
tty_fprintf (fp, "%02X", sk->protect.iv[i]); /* tty_fprintf (fp, "%02X", sk->protect.iv[i]); */
} /* } */
} /* } */
tty_fprintf (fp, "\n"); /* tty_fprintf (fp, "\n"); */
} /* } */
} /* } */
} }
@ -1524,37 +1525,38 @@ print_fingerprint (PKT_public_key *pk, int mode)
/* Print the serial number of an OpenPGP card if available. */ /* Print the serial number of an OpenPGP card if available. */
static void static void
print_card_serialno (PKT_secret_key * sk) print_card_serialno (PKT_public_key *pk)
{ {
int i; log_debug ("Fixme: Needs to be adjusted to gpg-agent\n");
/* int i; */
if (!sk) /* if (!sk) */
return; /* return; */
if (!sk->is_protected || sk->protect.s2k.mode != 1002) /* if (!sk->is_protected || sk->protect.s2k.mode != 1002) */
return; /* Not a card. */ /* return; /\* Not a card. *\/ */
if (opt.with_colons) /* if (opt.with_colons) */
return; /* Handled elsewhere. */ /* return; /\* Handled elsewhere. *\/ */
es_fputs (_(" Card serial no. ="), es_stdout); /* es_fputs (_(" Card serial no. ="), es_stdout); */
es_putc (' ', es_stdout); /* es_putc (' ', es_stdout); */
if (sk->protect.ivlen == 16 /* if (sk->protect.ivlen == 16 */
&& !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) /* && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) */
{ /* { */
/* This is an OpenPGP card. Just print the relevant part. */ /* /\* This is an OpenPGP card. Just print the relevant part. *\/ */
for (i = 8; i < 14; i++) /* for (i = 8; i < 14; i++) */
{ /* { */
if (i == 10) /* if (i == 10) */
es_putc (' ', es_stdout); /* es_putc (' ', es_stdout); */
es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); /* es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
} /* } */
} /* } */
else /* else */
{ /* { */
/* Something is wrong: Print all. */ /* /\* Something is wrong: Print all. *\/ */
for (i = 0; i < sk->protect.ivlen; i++) /* for (i = 0; i < sk->protect.ivlen; i++) */
es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); /* es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
} /* } */
es_putc ('\n', es_stdout); /* es_putc ('\n', es_stdout); */
} }

View File

@ -899,7 +899,6 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
int use_offtbl; int use_offtbl;
PKT_user_id *uid = NULL; PKT_user_id *uid = NULL;
PKT_public_key *pk = NULL; PKT_public_key *pk = NULL;
PKT_secret_key *sk = NULL;
u32 aki[2]; u32 aki[2];
/* figure out what information we need */ /* figure out what information we need */
@ -1017,10 +1016,11 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
} }
pk = NULL; pk = NULL;
sk = NULL;
uid = NULL; uid = NULL;
if ( pkt.pkttype == PKT_PUBLIC_KEY if ( pkt.pkttype == PKT_PUBLIC_KEY
|| pkt.pkttype == PKT_PUBLIC_SUBKEY) || pkt.pkttype == PKT_PUBLIC_SUBKEY
|| pkt.pkttype == PKT_SECRET_KEY
|| pkt.pkttype == PKT_SECRET_SUBKEY)
{ {
pk = pkt.pkt.public_key; pk = pkt.pkt.public_key;
++pk_no; ++pk_no;
@ -1041,21 +1041,6 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
uid = pkt.pkt.user_id; uid = pkt.pkt.user_id;
++uid_no; ++uid_no;
} }
else if ( pkt.pkttype == PKT_SECRET_KEY
|| pkt.pkttype == PKT_SECRET_SUBKEY)
{
sk = pkt.pkt.secret_key;
++pk_no;
if (need_fpr) {
fingerprint_from_sk (sk, afp, &an);
while (an < 20) /* fill up to 20 bytes */
afp[an++] = 0;
}
if (need_keyid)
keyid_from_sk (sk, aki);
}
for (n=0; n < ndesc; n++) for (n=0; n < ndesc; n++)
{ {
@ -1076,29 +1061,29 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
break; break;
case KEYDB_SEARCH_MODE_SHORT_KID: case KEYDB_SEARCH_MODE_SHORT_KID:
if ((pk||sk) && desc[n].u.kid[1] == aki[1]) if (pk && desc[n].u.kid[1] == aki[1])
goto found; goto found;
break; break;
case KEYDB_SEARCH_MODE_LONG_KID: case KEYDB_SEARCH_MODE_LONG_KID:
if ((pk||sk) && desc[n].u.kid[0] == aki[0] if (pk && desc[n].u.kid[0] == aki[0]
&& desc[n].u.kid[1] == aki[1]) && desc[n].u.kid[1] == aki[1])
goto found; goto found;
break; break;
case KEYDB_SEARCH_MODE_FPR16: case KEYDB_SEARCH_MODE_FPR16:
if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 16)) if (pk && !memcmp (desc[n].u.fpr, afp, 16))
goto found; goto found;
break; break;
case KEYDB_SEARCH_MODE_FPR20: case KEYDB_SEARCH_MODE_FPR20:
case KEYDB_SEARCH_MODE_FPR: case KEYDB_SEARCH_MODE_FPR:
if ((pk||sk) && !memcmp (desc[n].u.fpr, afp, 20)) if (pk && !memcmp (desc[n].u.fpr, afp, 20))
goto found; goto found;
break; break;
case KEYDB_SEARCH_MODE_FIRST: case KEYDB_SEARCH_MODE_FIRST:
if (pk||sk) if (pk)
goto found; goto found;
break; break;
case KEYDB_SEARCH_MODE_NEXT: case KEYDB_SEARCH_MODE_NEXT:
if (pk||sk) if (pk)
goto found; goto found;
break; break;
default: default:
@ -1128,7 +1113,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
{ {
hd->found.offset = main_offset; hd->found.offset = main_offset;
hd->found.kr = hd->current.kr; hd->found.kr = hd->current.kr;
hd->found.pk_no = (pk||sk)? pk_no : 0; hd->found.pk_no = pk? pk_no : 0;
hd->found.uid_no = uid? uid_no : 0; hd->found.uid_no = uid? uid_no : 0;
} }
else if (rc == -1) else if (rc == -1)

View File

@ -277,10 +277,6 @@ void import_print_stats (void *hd);
int collapse_uids( KBNODE *keyblock ); int collapse_uids( KBNODE *keyblock );
int auto_create_card_key_stub ( const char *serialnostr,
const unsigned char *fpr1,
const unsigned char *fpr2,
const unsigned char *fpr3);
/*-- export.c --*/ /*-- export.c --*/
int parse_export_options(char *str,unsigned int *options,int noisy); int parse_export_options(char *str,unsigned int *options,int noisy);

View File

@ -58,7 +58,6 @@ struct mainproc_context
{ {
struct mainproc_context *anchor; /* May be useful in the future. */ struct mainproc_context *anchor; /* May be useful in the future. */
PKT_public_key *last_pubkey; PKT_public_key *last_pubkey;
PKT_secret_key *last_seckey;
PKT_user_id *last_user_id; PKT_user_id *last_user_id;
md_filter_context_t mfx; md_filter_context_t mfx;
int sigs_only; /* Process only signatures and reject all other stuff. */ int sigs_only; /* Process only signatures and reject all other stuff. */
@ -1118,11 +1117,9 @@ list_node( CTX c, KBNODE node )
u32 keyid[2]; u32 keyid[2];
if( c->list->pkt->pkttype == PKT_PUBLIC_KEY if( c->list->pkt->pkttype == PKT_PUBLIC_KEY
|| c->list->pkt->pkttype == PKT_SECRET_KEY ) { || c->list->pkt->pkttype == PKT_SECRET_KEY )
if( c->list->pkt->pkttype == PKT_PUBLIC_KEY ) {
keyid_from_pk( c->list->pkt->pkt.public_key, keyid ); keyid_from_pk (c->list->pkt->pkt.public_key, keyid);
else
keyid_from_sk( c->list->pkt->pkt.secret_key, keyid );
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
is_selfsig = 1; is_selfsig = 1;

View File

@ -53,8 +53,9 @@ typedef struct {
byte value; byte value;
} prefitem_t; } prefitem_t;
typedef struct { typedef struct
int mode; {
int mode; /* Must be an integer due to the GNU modes 1001 et al. */
byte hash_algo; byte hash_algo;
byte salt[8]; byte salt[8];
u32 count; u32 count;
@ -204,11 +205,35 @@ struct revoke_info
byte algo; byte algo;
}; };
/* Information pertaining to secret keys. */
struct seckey_info
{
int is_protected:1; /* The secret info is protected and must */
/* be decrypted before use, the protected */
/* MPIs are simply (void*) pointers to memory */
/* and should never be passed to a mpi_xxx() */
int sha1chk:1; /* SHA1 is used instead of a 16 bit checksum */
u16 csum; /* Checksum for old protection modes. */
byte algo; /* Cipher used to protect the secret information. */
STRING2KEY s2k; /* S2K parameter. */
byte ivlen; /* Used length of the IV. */
byte iv[16]; /* Initialization vector for CFB mode. */
};
/**************** /****************
* Note about the pkey/skey elements: We assume that the secret keys * We assume that secret keys have the same number of parameters as
* has the same elements as the public key at the begin of the array, so * the public key and that the public parameters are the first items
* that npkey < nskey and it is possible to compare the secret and * in the PKEY array. Thus NPKEY is always less than NSKEY and it is
* public keys by comparing the first npkey elements of pkey againts skey. * possible to compare the secret and public keys by comparing the
* first NPKEY elements of the PKEY array. Note that since GnuPG 2.1
* we don't use secret keys anymore directly because they are managed
* by gpg-agent. However for parsing OpenPGP key files we need a way
* to temporary store those secret keys. We do this by putting them
* into the public key structure and extending the PKEY field to NSKEY
* elements; the extra secret key information are stored in the
* SECKEY_INFO field.
*/ */
typedef struct { typedef struct {
u32 timestamp; /* key made */ u32 timestamp; /* key made */
@ -243,44 +268,16 @@ typedef struct {
byte trust_depth; byte trust_depth;
byte trust_value; byte trust_value;
const byte *trust_regexp; const byte *trust_regexp;
gcry_mpi_t pkey[PUBKEY_MAX_NPKEY]; struct seckey_info *seckey_info; /* If not NULL this malloced
structure describes a secret
key. */
gcry_mpi_t pkey[PUBKEY_MAX_NSKEY]; /* Right, NSKEY elements. */
} PKT_public_key; } PKT_public_key;
/* Evaluates as true if the pk is disabled, and false if it isn't. If /* Evaluates as true if the pk is disabled, and false if it isn't. If
there is no disable value cached, fill one in. */ there is no disable value cached, fill one in. */
#define pk_is_disabled(a) (((a)->is_disabled)?((a)->is_disabled==2):(cache_disabled_value((a)))) #define pk_is_disabled(a) (((a)->is_disabled)?((a)->is_disabled==2):(cache_disabled_value((a))))
typedef struct {
u32 timestamp; /* key made */
u32 expiredate; /* expires at this date or 0 if not at all */
u32 max_expiredate; /* must not expire past this date */
byte hdrbytes; /* number of header bytes */
byte version;
byte pubkey_algo; /* algorithm used for public key scheme */
byte pubkey_usage;
byte req_usage;
byte req_algo;
u32 has_expired; /* set to the expiration date if expired */
int is_revoked; /* key has been revoked */
int is_valid; /* key (especially subkey) is valid */
u32 main_keyid[2]; /* keyid of the primary key */
u32 keyid[2];
byte is_primary;
byte is_protected; /* The secret info is protected and must */
/* be decrypted before use, the protected */
/* MPIs are simply (void*) pointers to memory */
/* and should never be passed to a mpi_xxx() */
struct {
byte algo; /* cipher used to protect the secret information*/
byte sha1chk; /* SHA1 is used instead of a 16 bit checksum */
STRING2KEY s2k;
byte ivlen; /* used length of the iv */
byte iv[16]; /* initialization vector for CFB mode */
} protect;
gcry_mpi_t skey[PUBKEY_MAX_NSKEY];
u16 csum; /* checksum */
} PKT_secret_key;
typedef struct { typedef struct {
int len; /* length of data */ int len; /* length of data */
@ -339,7 +336,7 @@ struct packet_struct {
PKT_onepass_sig *onepass_sig; /* PKT_ONEPASS_SIG */ PKT_onepass_sig *onepass_sig; /* PKT_ONEPASS_SIG */
PKT_signature *signature; /* PKT_SIGNATURE */ PKT_signature *signature; /* PKT_SIGNATURE */
PKT_public_key *public_key; /* PKT_PUBLIC_[SUB)KEY */ PKT_public_key *public_key; /* PKT_PUBLIC_[SUB)KEY */
PKT_secret_key *secret_key; /* PKT_SECRET_[SUB]KEY */ PKT_public_key *secret_key; /* PKT_SECRET_[SUB]KEY */
PKT_comment *comment; /* PKT_COMMENT */ PKT_comment *comment; /* PKT_COMMENT */
PKT_user_id *user_id; /* PKT_USER_ID */ PKT_user_id *user_id; /* PKT_USER_ID */
PKT_compressed *compressed; /* PKT_COMPRESSED */ PKT_compressed *compressed; /* PKT_COMPRESSED */
@ -452,22 +449,16 @@ void free_seckey_enc( PKT_signature *enc );
int digest_algo_from_sig( PKT_signature *sig ); int digest_algo_from_sig( PKT_signature *sig );
void release_public_key_parts( PKT_public_key *pk ); void release_public_key_parts( PKT_public_key *pk );
void free_public_key( PKT_public_key *key ); void free_public_key( PKT_public_key *key );
void release_secret_key_parts( PKT_secret_key *sk );
void free_secret_key( PKT_secret_key *sk );
void free_attributes(PKT_user_id *uid); void free_attributes(PKT_user_id *uid);
void free_user_id( PKT_user_id *uid ); void free_user_id( PKT_user_id *uid );
void free_comment( PKT_comment *rem ); void free_comment( PKT_comment *rem );
void free_packet( PACKET *pkt ); void free_packet( PACKET *pkt );
prefitem_t *copy_prefs (const prefitem_t *prefs); prefitem_t *copy_prefs (const prefitem_t *prefs);
PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s ); PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s );
void copy_public_parts_to_secret_key( PKT_public_key *pk, PKT_secret_key *sk );
PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s );
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s ); PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
PKT_user_id *scopy_user_id (PKT_user_id *sd ); PKT_user_id *scopy_user_id (PKT_user_id *sd );
int cmp_public_keys( PKT_public_key *a, PKT_public_key *b ); int cmp_public_keys( PKT_public_key *a, PKT_public_key *b );
int cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b );
int cmp_signatures( PKT_signature *a, PKT_signature *b ); int cmp_signatures( PKT_signature *a, PKT_signature *b );
int cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk );
int cmp_user_ids( PKT_user_id *a, PKT_user_id *b ); int cmp_user_ids( PKT_user_id *a, PKT_user_id *b );

View File

@ -565,12 +565,9 @@ parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
{ {
case PKT_PUBLIC_KEY: case PKT_PUBLIC_KEY:
case PKT_PUBLIC_SUBKEY: case PKT_PUBLIC_SUBKEY:
pkt->pkt.public_key = xmalloc_clear (sizeof *pkt->pkt.public_key);
rc = parse_key (inp, pkttype, pktlen, hdr, hdrlen, pkt);
break;
case PKT_SECRET_KEY: case PKT_SECRET_KEY:
case PKT_SECRET_SUBKEY: case PKT_SECRET_SUBKEY:
pkt->pkt.secret_key = xmalloc_clear (sizeof *pkt->pkt.secret_key); pkt->pkt.public_key = xmalloc_clear (sizeof *pkt->pkt.public_key);
rc = parse_key (inp, pkttype, pktlen, hdr, hdrlen, pkt); rc = parse_key (inp, pkttype, pktlen, hdr, hdrlen, pkt);
break; break;
case PKT_SYMKEY_ENC: case PKT_SYMKEY_ENC:
@ -627,6 +624,7 @@ parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
} }
leave: leave:
/* FIXME: Do we leak in case of an error? */
if (!rc && iobuf_error (inp)) if (!rc && iobuf_error (inp))
rc = G10ERR_INV_KEYRING; rc = G10ERR_INV_KEYRING;
return rc; return rc;
@ -1815,6 +1813,7 @@ static int
parse_key (IOBUF inp, int pkttype, unsigned long pktlen, parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
byte * hdr, int hdrlen, PACKET * pkt) byte * hdr, int hdrlen, PACKET * pkt)
{ {
gpg_error_t err = 0;
int i, version, algorithm; int i, version, algorithm;
unsigned n; unsigned n;
unsigned long timestamp, expiredate, max_expiredate; unsigned long timestamp, expiredate, max_expiredate;
@ -1822,9 +1821,12 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
int is_v4 = 0; int is_v4 = 0;
int rc = 0; int rc = 0;
u32 keyid[2]; u32 keyid[2];
PKT_public_key *pk;
(void) hdr; (void) hdr;
pk = pkt->pkt.public_key; /* PK has been cleared. */
version = iobuf_get_noeof (inp); version = iobuf_get_noeof (inp);
pktlen--; pktlen--;
if (pkttype == PKT_PUBLIC_SUBKEY && version == '#') if (pkttype == PKT_PUBLIC_SUBKEY && version == '#')
@ -1853,14 +1855,14 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
else if (version != 2 && version != 3) else if (version != 2 && version != 3)
{ {
log_error ("packet(%d) with unknown version %d\n", pkttype, version); log_error ("packet(%d) with unknown version %d\n", pkttype, version);
rc = gpg_error (GPG_ERR_INV_PACKET); err = gpg_error (GPG_ERR_INV_PACKET);
goto leave; goto leave;
} }
if (pktlen < 11) if (pktlen < 11)
{ {
log_error ("packet(%d) too short\n", pkttype); log_error ("packet(%d) too short\n", pkttype);
rc = gpg_error (GPG_ERR_INV_PACKET); err = gpg_error (GPG_ERR_INV_PACKET);
goto leave; goto leave;
} }
@ -1894,38 +1896,14 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
pkttype == PKT_SECRET_SUBKEY ? "secret sub" : "??", pkttype == PKT_SECRET_SUBKEY ? "secret sub" : "??",
version, algorithm, timestamp, expiredate); version, algorithm, timestamp, expiredate);
if (pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY)
{
PKT_secret_key *sk = pkt->pkt.secret_key;
sk->timestamp = timestamp;
sk->expiredate = expiredate;
sk->max_expiredate = max_expiredate;
sk->hdrbytes = hdrlen;
sk->version = version;
sk->is_primary = pkttype == PKT_SECRET_KEY;
sk->pubkey_algo = algorithm;
sk->req_usage = 0;
sk->pubkey_usage = 0; /* not yet used */
}
else
{
PKT_public_key *pk = pkt->pkt.public_key;
pk->timestamp = timestamp; pk->timestamp = timestamp;
pk->expiredate = expiredate; pk->expiredate = expiredate;
pk->max_expiredate = max_expiredate; pk->max_expiredate = max_expiredate;
pk->hdrbytes = hdrlen; pk->hdrbytes = hdrlen;
pk->version = version; pk->version = version;
pk->is_primary = pkttype == PKT_PUBLIC_KEY; pk->is_primary = (pkttype == PKT_PUBLIC_KEY || pkttype == PKT_SECRET_KEY);
pk->pubkey_algo = algorithm; pk->pubkey_algo = algorithm;
pk->req_usage = 0;
pk->pubkey_usage = 0; /* not yet used */
pk->is_revoked = 0;
pk->is_disabled = 0;
pk->keyid[0] = 0;
pk->keyid[1] = 0;
}
nskey = pubkey_get_nskey (algorithm); nskey = pubkey_get_nskey (algorithm);
npkey = pubkey_get_npkey (algorithm); npkey = pubkey_get_npkey (algorithm);
if (!npkey) if (!npkey)
@ -1936,62 +1914,77 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
} }
if (pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY)
{
PKT_secret_key *sk = pkt->pkt.secret_key;
byte temp[16];
size_t snlen = 0;
if (!npkey) if (!npkey)
{ {
sk->skey[0] = gcry_mpi_set_opaque (NULL, read_rest (inp, pktlen, 0), /* Unknown algorithm - put data into an opaque MPI. */
pk->pkey[0] = gcry_mpi_set_opaque (NULL,
read_rest (inp, pktlen, 0),
pktlen * 8); pktlen * 8);
pktlen = 0; pktlen = 0;
goto leave; goto leave;
} }
else
{
/* Fill in public key parameters. */
for (i = 0; i < npkey; i++) for (i = 0; i < npkey; i++)
{ {
n = pktlen; n = pktlen;
sk->skey[i] = mpi_read (inp, &n, 0); pk->pkey[i] = mpi_read (inp, &n, 0);
pktlen -= n; pktlen -= n;
if (list_mode) if (list_mode)
{ {
es_fprintf (listfp, "\tskey[%d]: ", i); es_fprintf (listfp, "\tpkey[%d]: ", i);
mpi_print (listfp, sk->skey[i], mpi_print_mode); mpi_print (listfp, pk->pkey[i], mpi_print_mode);
es_putc ('\n', listfp); es_putc ('\n', listfp);
} }
if (!sk->skey[i]) if (!pk->pkey[i])
rc = G10ERR_INVALID_PACKET; err = gpg_error (GPG_ERR_INV_PACKET);
} }
if (rc) /* One of the MPIs were bad. */ if (err)
goto leave; goto leave;
sk->protect.algo = iobuf_get_noeof (inp); }
pktlen--;
sk->protect.sha1chk = 0; if (list_mode)
if (sk->protect.algo) keyid_from_pk (pk, keyid);
if (pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY)
{ {
sk->is_protected = 1; struct seckey_info *ski;
sk->protect.s2k.count = 0; byte temp[16];
if (sk->protect.algo == 254 || sk->protect.algo == 255) size_t snlen = 0;
pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
if (!pk->seckey_info)
{
err = gpg_error_from_syserror ();
goto leave;
}
ski->algo = iobuf_get_noeof (inp);
pktlen--;
if (ski->algo)
{
ski->is_protected = 1;
ski->s2k.count = 0;
if (ski->algo == 254 || ski->algo == 255)
{ {
if (pktlen < 3) if (pktlen < 3)
{ {
rc = G10ERR_INVALID_PACKET; err = gpg_error (GPG_ERR_INV_PACKET);
goto leave; goto leave;
} }
sk->protect.sha1chk = (sk->protect.algo == 254); ski->sha1chk = (ski->algo == 254);
sk->protect.algo = iobuf_get_noeof (inp); ski->algo = iobuf_get_noeof (inp);
pktlen--; pktlen--;
/* Note that a sk->protect.algo > 110 is illegal, but /* Note that a ski->algo > 110 is illegal, but I'm not
I'm not erroring on it here as otherwise there would erroring on it here as otherwise there would be no
be no way to delete such a key. */ way to delete such a key. */
sk->protect.s2k.mode = iobuf_get_noeof (inp); ski->s2k.mode = iobuf_get_noeof (inp);
pktlen--; pktlen--;
sk->protect.s2k.hash_algo = iobuf_get_noeof (inp); ski->s2k.hash_algo = iobuf_get_noeof (inp);
pktlen--; pktlen--;
/* check for the special GNU extension */ /* Check for the special GNU extension. */
if (is_v4 && sk->protect.s2k.mode == 101) if (is_v4 && ski->s2k.mode == 101)
{ {
for (i = 0; i < 4 && pktlen; i++, pktlen--) for (i = 0; i < 4 && pktlen; i++, pktlen--)
temp[i] = iobuf_get_noeof (inp); temp[i] = iobuf_get_noeof (inp);
@ -1999,26 +1992,30 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
{ {
if (list_mode) if (list_mode)
es_fprintf (listfp, "\tunknown S2K %d\n", es_fprintf (listfp, "\tunknown S2K %d\n",
sk->protect.s2k.mode); ski->s2k.mode);
rc = G10ERR_INVALID_PACKET; err = gpg_error (GPG_ERR_INV_PACKET);
goto leave; goto leave;
} }
/* Here we know that it is a GNU extension. What /* Here we know that it is a GNU extension. What
* follows is the GNU protection mode: All values * follows is the GNU protection mode: All values
* have special meanings and they are mapped to MODE * have special meanings and they are mapped to MODE
* with a base of 1000. */ * with a base of 1000. */
sk->protect.s2k.mode = 1000 + temp[3]; ski->s2k.mode = 1000 + temp[3];
} }
switch (sk->protect.s2k.mode)
/* Read the salt. */
switch (ski->s2k.mode)
{ {
case 1: case 1:
case 3: case 3:
for (i = 0; i < 8 && pktlen; i++, pktlen--) for (i = 0; i < 8 && pktlen; i++, pktlen--)
temp[i] = iobuf_get_noeof (inp); temp[i] = iobuf_get_noeof (inp);
memcpy (sk->protect.s2k.salt, temp, 8); memcpy (ski->s2k.salt, temp, 8);
break; break;
} }
switch (sk->protect.s2k.mode)
/* Check the mode. */
switch (ski->s2k.mode)
{ {
case 0: case 0:
if (list_mode) if (list_mode)
@ -2043,202 +2040,163 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
default: default:
if (list_mode) if (list_mode)
es_fprintf (listfp, "\tunknown %sS2K %d\n", es_fprintf (listfp, "\tunknown %sS2K %d\n",
sk->protect.s2k.mode < 1000 ? "" : "GNU ", ski->s2k.mode < 1000 ? "" : "GNU ",
sk->protect.s2k.mode); ski->s2k.mode);
rc = G10ERR_INVALID_PACKET; err = gpg_error (GPG_ERR_INV_PACKET);
goto leave; goto leave;
} }
/* Print some info. */
if (list_mode) if (list_mode)
{ {
es_fprintf (listfp, ", algo: %d,%s hash: %d", es_fprintf (listfp, ", algo: %d,%s hash: %d",
sk->protect.algo, ski->algo,
sk->protect.sha1chk ? " SHA1 protection," ski->sha1chk ? " SHA1 protection,"
: " simple checksum,", sk->protect.s2k.hash_algo); : " simple checksum,", ski->s2k.hash_algo);
if (sk->protect.s2k.mode == 1 || sk->protect.s2k.mode == 3) if (ski->s2k.mode == 1 || ski->s2k.mode == 3)
{ {
es_fprintf (listfp, ", salt: "); es_fprintf (listfp, ", salt: ");
es_write_hexstring (listfp, sk->protect.s2k.salt, 8, es_write_hexstring (listfp, ski->s2k.salt, 8, 0, NULL);
0, NULL);
} }
es_putc ('\n', listfp); es_putc ('\n', listfp);
} }
if (sk->protect.s2k.mode == 3) /* Read remaining protection parameters. */
if (ski->s2k.mode == 3)
{ {
if (pktlen < 1) if (pktlen < 1)
{ {
rc = G10ERR_INVALID_PACKET; err = gpg_error (GPG_ERR_INV_PACKET);
goto leave; goto leave;
} }
sk->protect.s2k.count = iobuf_get (inp); ski->s2k.count = iobuf_get (inp);
pktlen--; pktlen--;
if (list_mode) if (list_mode)
es_fprintf (listfp, "\tprotect count: %lu\n", es_fprintf (listfp, "\tprotect count: %lu\n",
(ulong) sk->protect.s2k.count); (ulong) ski->s2k.count);
} }
else if (sk->protect.s2k.mode == 1002) else if (ski->s2k.mode == 1002)
{ {
/* Read the serial number. */ /* Read the serial number. */
if (pktlen < 1) if (pktlen < 1)
{ {
rc = G10ERR_INVALID_PACKET; err = gpg_error (GPG_ERR_INV_PACKET);
goto leave; goto leave;
} }
snlen = iobuf_get (inp); snlen = iobuf_get (inp);
pktlen--; pktlen--;
if (pktlen < snlen || snlen == -1) if (pktlen < snlen || snlen == -1)
{ {
rc = G10ERR_INVALID_PACKET; err = gpg_error (GPG_ERR_INV_PACKET);
goto leave; goto leave;
} }
} }
} }
else /* Old version; no S2K, so we set mode to 0, hash MD5. */ else /* Old version; no S2K, so we set mode to 0, hash MD5. */
{ {
/* Note that a sk->protect.algo > 110 is illegal, but /* Note that a ski->algo > 110 is illegal, but I'm not
I'm not erroring on it here as otherwise there would erroring on it here as otherwise there would be no
be no way to delete such a key. */ way to delete such a key. */
sk->protect.s2k.mode = 0; ski->s2k.mode = 0;
sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5; ski->s2k.hash_algo = DIGEST_ALGO_MD5;
if (list_mode) if (list_mode)
es_fprintf (listfp, "\tprotect algo: %d (hash algo: %d)\n", es_fprintf (listfp, "\tprotect algo: %d (hash algo: %d)\n",
sk->protect.algo, sk->protect.s2k.hash_algo); ski->algo, ski->s2k.hash_algo);
} }
/* It is really ugly that we don't know the size /* It is really ugly that we don't know the size
* of the IV here in cases we are not aware of the algorithm. * of the IV here in cases we are not aware of the algorithm.
* so a * so a
* sk->protect.ivlen = cipher_get_blocksize(sk->protect.algo); * ski->ivlen = cipher_get_blocksize (ski->algo);
* won't work. The only solution I see is to hardwire it. * won't work. The only solution I see is to hardwire it.
* NOTE: if you change the ivlen above 16, don't forget to * NOTE: if you change the ivlen above 16, don't forget to
* enlarge temp. */ * enlarge temp. */
sk->protect.ivlen = openpgp_cipher_blocklen (sk->protect.algo); ski->ivlen = openpgp_cipher_blocklen (ski->algo);
assert (sk->protect.ivlen <= sizeof (temp)); assert (ski->ivlen <= sizeof (temp));
if (sk->protect.s2k.mode == 1001) if (ski->s2k.mode == 1001)
sk->protect.ivlen = 0; ski->ivlen = 0;
else if (sk->protect.s2k.mode == 1002) else if (ski->s2k.mode == 1002)
sk->protect.ivlen = snlen < 16 ? snlen : 16; ski->ivlen = snlen < 16 ? snlen : 16;
if (pktlen < sk->protect.ivlen) if (pktlen < ski->ivlen)
{ {
rc = G10ERR_INVALID_PACKET; err = gpg_error (GPG_ERR_INV_PACKET);
goto leave; goto leave;
} }
for (i = 0; i < sk->protect.ivlen && pktlen; i++, pktlen--) for (i = 0; i < ski->ivlen && pktlen; i++, pktlen--)
temp[i] = iobuf_get_noeof (inp); temp[i] = iobuf_get_noeof (inp);
if (list_mode) if (list_mode)
{ {
es_fprintf (listfp, es_fprintf (listfp,
sk->protect.s2k.mode == 1002 ? "\tserial-number: " ski->s2k.mode == 1002 ? "\tserial-number: "
: "\tprotect IV: "); : "\tprotect IV: ");
for (i = 0; i < sk->protect.ivlen; i++) for (i = 0; i < ski->ivlen; i++)
es_fprintf (listfp, " %02x", temp[i]); es_fprintf (listfp, " %02x", temp[i]);
es_putc ('\n', listfp); es_putc ('\n', listfp);
} }
memcpy (sk->protect.iv, temp, sk->protect.ivlen); memcpy (ski->iv, temp, ski->ivlen);
} }
else
sk->is_protected = 0;
/* It does not make sense to read it into secure memory. /* It does not make sense to read it into secure memory.
* If the user is so careless, not to protect his secret key, * If the user is so careless, not to protect his secret key,
* we can assume, that he operates an open system :=(. * we can assume, that he operates an open system :=(.
* So we put the key into secure memory when we unprotect it. */ * So we put the key into secure memory when we unprotect it. */
if (sk->protect.s2k.mode == 1001 || sk->protect.s2k.mode == 1002) if (ski->s2k.mode == 1001 || ski->s2k.mode == 1002)
{ {
/* Better set some dummy stuff here. */ /* Better set some dummy stuff here. */
sk->skey[npkey] = gcry_mpi_set_opaque (NULL, pk->pkey[npkey] = gcry_mpi_set_opaque (NULL,
xstrdup ("dummydata"), xstrdup ("dummydata"),
10 * 8); 10 * 8);
pktlen = 0; pktlen = 0;
} }
else if (is_v4 && sk->is_protected) else if (is_v4 && ski->is_protected)
{ {
/* Ugly: The length is encrypted too, so we read all stuff /* Ugly: The length is encrypted too, so we read all stuff
* up to the end of the packet into the first SKEY * up to the end of the packet into the first SKEY
* element. */ * element. */
sk->skey[npkey] = gcry_mpi_set_opaque (NULL, pk->pkey[npkey] = gcry_mpi_set_opaque (NULL,
read_rest (inp, pktlen, 0), read_rest (inp, pktlen, 0),
pktlen * 8); pktlen * 8);
pktlen = 0; pktlen = 0;
if (list_mode) if (list_mode)
{ es_fprintf (listfp, "\tskey[%d]: [v4 protected]\n", npkey);
es_fprintf (listfp, "\tencrypted stuff follows\n");
} }
} else
else /* The v3 method: The mpi length is not encrypted. */
{ {
/* The v3 method: The mpi length is not encrypted. */
for (i = npkey; i < nskey; i++) for (i = npkey; i < nskey; i++)
{ {
if (sk->is_protected) if (ski->is_protected)
{ {
sk->skey[i] = read_protected_v3_mpi (inp, &pktlen); pk->pkey[i] = read_protected_v3_mpi (inp, &pktlen);
if (list_mode) if (list_mode)
es_fprintf (listfp, "\tskey[%d]: [encrypted]\n", i); es_fprintf (listfp, "\tskey[%d]: [v3 protected]\n", i);
} }
else else
{
n = pktlen;
sk->skey[i] = mpi_read (inp, &n, 0);
pktlen -= n;
if (list_mode)
{
es_fprintf (listfp, "\tskey[%d]: ", i);
mpi_print (listfp, sk->skey[i], mpi_print_mode);
es_putc ('\n', listfp);
}
}
if (!sk->skey[i])
rc = G10ERR_INVALID_PACKET;
}
if (rc)
goto leave;
sk->csum = read_16 (inp);
pktlen -= 2;
if (list_mode)
{
es_fprintf (listfp, "\tchecksum: %04hx\n", sk->csum);
}
}
if (list_mode)
keyid_from_sk (sk, keyid);
}
else
{
PKT_public_key *pk = pkt->pkt.public_key;
if (!npkey)
{
pk->pkey[0] = gcry_mpi_set_opaque (NULL,
read_rest (inp, pktlen, 0),
pktlen * 8);
pktlen = 0;
goto leave;
}
for (i = 0; i < npkey; i++)
{ {
n = pktlen; n = pktlen;
pk->pkey[i] = mpi_read (inp, &n, 0); pk->pkey[i] = mpi_read (inp, &n, 0);
pktlen -= n; pktlen -= n;
if (list_mode) if (list_mode)
{ {
es_fprintf (listfp, "\tpkey[%d]: ", i); es_fprintf (listfp, "\tskey[%d]: ", i);
mpi_print (listfp, pk->pkey[i], mpi_print_mode); mpi_print (listfp, pk->pkey[i], mpi_print_mode);
es_putc ('\n', listfp); es_putc ('\n', listfp);
} }
if (!pk->pkey[i])
rc = G10ERR_INVALID_PACKET;
} }
if (rc)
if (!pk->pkey[i])
err = gpg_error (GPG_ERR_INV_PACKET);
}
if (err)
goto leave; goto leave;
ski->csum = read_16 (inp);
pktlen -= 2;
if (list_mode) if (list_mode)
keyid_from_pk (pk, keyid); es_fprintf (listfp, "\tchecksum: %04hx\n", ski->csum);
}
} }
if (list_mode) if (list_mode)

View File

@ -686,10 +686,10 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
/* Return an allocated utf-8 string describing the key PK. IF ESCAPED /* Return an allocated utf-8 string describing the key PK. IF ESCAPED
is true spaces and control characters are percent or plus is true spaces and control characters are percent or plus escaped.
escaped. */ MODE 0 is for the common prompt, MODE 1 for the import prompt. */
char * char *
gpg_format_keydesc (PKT_public_key *pk, int escaped) gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped)
{ {
char *uid; char *uid;
size_t uidlen; size_t uidlen;
@ -698,6 +698,7 @@ gpg_format_keydesc (PKT_public_key *pk, int escaped)
char *orig_codeset; char *orig_codeset;
char *maink; char *maink;
char *desc; char *desc;
const char *prompt;
algo_name = gcry_pk_algo_name (pk->pubkey_algo); algo_name = gcry_pk_algo_name (pk->pubkey_algo);
timestr = strtimestamp (pk->timestamp); timestr = strtimestamp (pk->timestamp);
@ -712,11 +713,26 @@ gpg_format_keydesc (PKT_public_key *pk, int escaped)
else else
maink = NULL; maink = NULL;
desc = xtryasprintf (_("Please enter the passphrase to unlock the" switch (mode)
" secret key for the OpenPGP certificate:\n" {
case 0:
prompt = _("Please enter the passphrase to unlock the"
" secret key for the OpenPGP certificate:");
break;
case 1:
prompt = _("Please enter the passphrase to import the"
" secret key for the OpenPGP certificate:");
break;
default:
prompt = "?";
break;
}
desc = xtryasprintf (_("%s\n"
"\"%.*s\"\n" "\"%.*s\"\n"
"%u-bit %s key, ID %s,\n" "%u-bit %s key, ID %s,\n"
"created %s%s.\n"), "created %s%s.\n"),
prompt,
(int)uidlen, uid, (int)uidlen, uid,
nbits_from_pk (pk), algo_name, nbits_from_pk (pk), algo_name,
keystr (pk->keyid), timestr, keystr (pk->keyid), timestr,

View File

@ -196,7 +196,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
goto leave; goto leave;
/* Decrypt. */ /* Decrypt. */
desc = gpg_format_keydesc (sk, 1); desc = gpg_format_keydesc (sk, 0, 1);
err = agent_pkdecrypt (NULL, keygrip, desc, s_data, &frame, &nframe); err = agent_pkdecrypt (NULL, keygrip, desc, s_data, &frame, &nframe);
xfree (desc); xfree (desc);
gcry_sexp_release (s_data); gcry_sexp_release (s_data);

View File

@ -314,7 +314,7 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
char *desc; char *desc;
gcry_sexp_t s_sigval; gcry_sexp_t s_sigval;
desc = gpg_format_keydesc (pksk, 1); desc = gpg_format_keydesc (pksk, 0, 1);
err = agent_pksign (NULL/*ctrl*/, cache_nonce, hexgrip, desc, err = agent_pksign (NULL/*ctrl*/, cache_nonce, hexgrip, desc,
dp, gcry_md_get_algo_dlen (mdalgo), mdalgo, dp, gcry_md_get_algo_dlen (mdalgo), mdalgo,
&s_sigval); &s_sigval);