mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01: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:
parent
daab9aff3a
commit
299ed4c9e2
@ -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>
|
||||
|
||||
* import.c (transfer_secret_keys, import_secret_one): Enable stats.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* build-packet.c - assemble packets and write them
|
||||
* 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.
|
||||
*
|
||||
@ -35,8 +35,7 @@
|
||||
#include "options.h"
|
||||
|
||||
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_secret_key( IOBUF out, int ctb, PKT_secret_key *pk );
|
||||
static int do_key (iobuf_t out, int ctb, PKT_public_key *pk);
|
||||
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 u32 calc_plaintext( PKT_plaintext *pt );
|
||||
@ -107,11 +106,9 @@ build_packet( IOBUF out, PACKET *pkt )
|
||||
break;
|
||||
case PKT_PUBLIC_SUBKEY:
|
||||
case PKT_PUBLIC_KEY:
|
||||
rc = do_public_key( out, ctb, pkt->pkt.public_key );
|
||||
break;
|
||||
case PKT_SECRET_SUBKEY:
|
||||
case PKT_SECRET_KEY:
|
||||
rc = do_secret_key( out, ctb, pkt->pkt.secret_key );
|
||||
rc = do_key (out, ctb, pkt->pkt.public_key);
|
||||
break;
|
||||
case 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;
|
||||
}
|
||||
|
||||
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 )
|
||||
iobuf_put( a, 3 );
|
||||
iobuf_put ( a, 3 );
|
||||
else
|
||||
iobuf_put( a, pk->version );
|
||||
write_32(a, pk->timestamp );
|
||||
iobuf_put ( a, pk->version );
|
||||
write_32 (a, pk->timestamp );
|
||||
|
||||
/* v3 needs the expiration time. */
|
||||
if ( pk->version < 4 )
|
||||
{
|
||||
u16 ndays;
|
||||
@ -261,179 +262,139 @@ do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
|
||||
ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L);
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
iobuf_put (a, sk->pubkey_algo );
|
||||
iobuf_put (a, pk->pubkey_algo );
|
||||
|
||||
/* Get number of secret and public parameters. They are held in one
|
||||
array first the public ones, then the secret ones. */
|
||||
nskey = pubkey_get_nskey ( sk->pubkey_algo );
|
||||
npkey = pubkey_get_npkey ( sk->pubkey_algo );
|
||||
nskey = pubkey_get_nskey (pk->pubkey_algo);
|
||||
npkey = pubkey_get_npkey (pk->pubkey_algo);
|
||||
|
||||
/* 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
|
||||
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;
|
||||
}
|
||||
assert ( npkey < nskey );
|
||||
assert (npkey < nskey);
|
||||
|
||||
/* Writing the public parameters is easy. */
|
||||
for (i=0; i < npkey; i++ )
|
||||
if ((rc = mpi_write (a, sk->skey[i])))
|
||||
if ((err = mpi_write (a, pk->pkey[i])))
|
||||
goto leave;
|
||||
|
||||
/* Build the header for protected (encrypted) secret parameters. */
|
||||
if ( sk->is_protected )
|
||||
if (pk->seckey_info)
|
||||
{
|
||||
if ( is_RSA(sk->pubkey_algo)
|
||||
&& sk->version < 4
|
||||
&& !sk->protect.s2k.mode )
|
||||
/* This is a secret key packet. */
|
||||
struct seckey_info *ski = pk->seckey_info;
|
||||
|
||||
/* Build the header for protected (encrypted) secret parameters. */
|
||||
if (ski->is_protected)
|
||||
{
|
||||
/* The simple rfc1991 (v3) way. */
|
||||
iobuf_put (a, sk->protect.algo );
|
||||
iobuf_write (a, sk->protect.iv, sk->protect.ivlen );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* OpenPGP protection according to rfc2440. */
|
||||
iobuf_put(a, sk->protect.sha1chk? 0xfe : 0xff );
|
||||
iobuf_put(a, sk->protect.algo );
|
||||
if ( sk->protect.s2k.mode >= 1000 )
|
||||
if ( is_RSA (pk->pubkey_algo) && pk->version < 4 && !ski->s2k.mode )
|
||||
{
|
||||
/* These modes are not possible in OpenPGP, we use them
|
||||
to implement our extensions, 101 can be seen as a
|
||||
private/experimental extension (this is not specified
|
||||
in rfc2440 but the same scheme is used for all other
|
||||
algorithm identifiers) */
|
||||
iobuf_put(a, 101 );
|
||||
iobuf_put(a, sk->protect.s2k.hash_algo );
|
||||
iobuf_write(a, "GNU", 3 );
|
||||
iobuf_put(a, sk->protect.s2k.mode - 1000 );
|
||||
}
|
||||
/* The simple rfc1991 (v3) way. */
|
||||
iobuf_put (a, ski->algo );
|
||||
iobuf_write (a, ski->iv, ski->ivlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
iobuf_put(a, sk->protect.s2k.mode );
|
||||
iobuf_put(a, sk->protect.s2k.hash_algo );
|
||||
}
|
||||
if ( sk->protect.s2k.mode == 1
|
||||
|| sk->protect.s2k.mode == 3 )
|
||||
iobuf_write (a, sk->protect.s2k.salt, 8 );
|
||||
/* OpenPGP protection according to rfc2440. */
|
||||
iobuf_put (a, ski->sha1chk? 0xfe : 0xff);
|
||||
iobuf_put (a, ski->algo);
|
||||
if (ski->s2k.mode >= 1000)
|
||||
{
|
||||
/* These modes are not possible in OpenPGP, we use
|
||||
them to implement our extensions, 101 can be
|
||||
viewed as a private/experimental extension (this
|
||||
is not specified in rfc2440 but the same scheme
|
||||
is used for all other algorithm identifiers). */
|
||||
iobuf_put (a, 101);
|
||||
iobuf_put (a, ski->s2k.hash_algo);
|
||||
iobuf_write (a, "GNU", 3 );
|
||||
iobuf_put (a, ski->s2k.mode - 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
iobuf_put (a, ski->s2k.mode);
|
||||
iobuf_put (a, ski->s2k.hash_algo);
|
||||
}
|
||||
|
||||
if ( sk->protect.s2k.mode == 3 )
|
||||
iobuf_put (a, sk->protect.s2k.count );
|
||||
if (ski->s2k.mode == 1 || ski->s2k.mode == 3)
|
||||
iobuf_write (a, ski->s2k.salt, 8);
|
||||
|
||||
/* For our special modes 1001, 1002 we do not need an IV. */
|
||||
if ( sk->protect.s2k.mode != 1001
|
||||
&& sk->protect.s2k.mode != 1002 )
|
||||
iobuf_write (a, sk->protect.iv, sk->protect.ivlen );
|
||||
}
|
||||
}
|
||||
else
|
||||
iobuf_put (a, 0 );
|
||||
if (ski->s2k.mode == 3)
|
||||
iobuf_put (a, ski->s2k.count);
|
||||
|
||||
if ( sk->protect.s2k.mode == 1001 )
|
||||
; /* GnuPG extension - don't write a secret key at all. */
|
||||
else if ( sk->protect.s2k.mode == 1002 )
|
||||
{
|
||||
/* GnuPG extension - divert to OpenPGP smartcard. */
|
||||
iobuf_put(a, sk->protect.ivlen ); /* Length of the serial number
|
||||
or 0 for no serial
|
||||
number. */
|
||||
/* The serial number gets stored in the IV field. */
|
||||
iobuf_write(a, sk->protect.iv, sk->protect.ivlen);
|
||||
}
|
||||
else if ( sk->is_protected && sk->version >= 4 )
|
||||
{
|
||||
/* The secret key is protected - write it out as it is. */
|
||||
byte *p;
|
||||
unsigned int ndatabits;
|
||||
/* For our special modes 1001, 1002 we do not need an IV. */
|
||||
if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002)
|
||||
iobuf_write (a, ski->iv, ski->ivlen);
|
||||
}
|
||||
}
|
||||
else /* Not protected. */
|
||||
iobuf_put (a, 0 );
|
||||
|
||||
assert (gcry_mpi_get_flag (sk->skey[npkey], GCRYMPI_FLAG_OPAQUE));
|
||||
p = gcry_mpi_get_opaque (sk->skey[npkey], &ndatabits );
|
||||
iobuf_write (a, p, (ndatabits+7)/8 );
|
||||
}
|
||||
else if ( sk->is_protected )
|
||||
{
|
||||
/* The secret key is protected the old v4 way. */
|
||||
for ( ; i < nskey; i++ )
|
||||
if (ski->s2k.mode == 1001)
|
||||
; /* GnuPG extension - don't write a secret key at all. */
|
||||
else if (ski->s2k.mode == 1002)
|
||||
{
|
||||
/* GnuPG extension - divert to OpenPGP smartcard. */
|
||||
/* Length of the serial number or 0 for no serial number. */
|
||||
iobuf_put (a, ski->ivlen );
|
||||
/* The serial number gets stored in the IV field. */
|
||||
iobuf_write (a, ski->iv, ski->ivlen);
|
||||
}
|
||||
else if (ski->is_protected && pk->version >= 4)
|
||||
{
|
||||
/* The secret key is protected - write it out as it is. */
|
||||
byte *p;
|
||||
unsigned int ndatabits;
|
||||
|
||||
assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE));
|
||||
p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits);
|
||||
iobuf_write (a, p, (ndatabits+7)/8);
|
||||
assert (gcry_mpi_get_flag (pk->pkey[npkey], GCRYMPI_FLAG_OPAQUE));
|
||||
p = gcry_mpi_get_opaque (pk->pkey[npkey], &ndatabits);
|
||||
iobuf_write (a, p, (ndatabits+7)/8 );
|
||||
}
|
||||
else if (ski->is_protected)
|
||||
{
|
||||
/* The secret key is protected the old v4 way. */
|
||||
for ( ; i < nskey; i++ )
|
||||
{
|
||||
byte *p;
|
||||
unsigned int ndatabits;
|
||||
|
||||
assert (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE));
|
||||
p = gcry_mpi_get_opaque (pk->pkey[i], &ndatabits);
|
||||
iobuf_write (a, p, (ndatabits+7)/8);
|
||||
}
|
||||
write_16 (a, ski->csum );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non-protected key. */
|
||||
for ( ; i < nskey; i++ )
|
||||
if ( (err = mpi_write (a, pk->pkey[i])))
|
||||
goto leave;
|
||||
write_16 (a, ski->csum );
|
||||
}
|
||||
write_16(a, sk->csum );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non-protected key. */
|
||||
for ( ; i < nskey; i++ )
|
||||
if ( (rc = mpi_write (a, sk->skey[i])))
|
||||
goto leave;
|
||||
write_16 (a, sk->csum );
|
||||
}
|
||||
|
||||
leave:
|
||||
if (!rc)
|
||||
if (!err)
|
||||
{
|
||||
/* Build the header of the packet - which we must do after
|
||||
writing all the other stuff, so that we know the length of
|
||||
the packet */
|
||||
write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes);
|
||||
/* And finally write it out the real stream */
|
||||
rc = iobuf_write_temp( out, a );
|
||||
write_header2 (out, ctb, iobuf_get_temp_length(a), pk->hdrbytes);
|
||||
/* And finally write it out to the real stream. */
|
||||
err = iobuf_write_temp (out, a);
|
||||
}
|
||||
|
||||
iobuf_close(a); /* Close the remporary buffer */
|
||||
return rc;
|
||||
iobuf_close (a); /* Close the temporary buffer */
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
|
258
g10/card-util.c
258
g10/card-util.c
@ -207,6 +207,9 @@ get_manufacturer (unsigned int no)
|
||||
case 0x0005: return "ZeitControl";
|
||||
|
||||
case 0x002A: return "Magrathea";
|
||||
|
||||
case 0xF517: return "FSIJ";
|
||||
|
||||
/* 0x00000 and 0xFFFF are defined as test cards per spec,
|
||||
0xFFF00 to 0xFFFE are assigned for use with randomly created
|
||||
serial numbers. */
|
||||
@ -581,6 +584,7 @@ card_status (estream_t fp, char *serialno, size_t serialnobuflen)
|
||||
|
||||
print_pubkey_info (fp, pk);
|
||||
|
||||
#if GNUPG_MAJOR_VERSION == 1
|
||||
if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) )
|
||||
print_card_key_info (fp, keyblock);
|
||||
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);
|
||||
#endif /* GNUPG_MAJOR_VERSION == 1 */
|
||||
}
|
||||
else
|
||||
tty_fprintf (fp, "[none]\n");
|
||||
@ -1514,150 +1519,151 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
|
||||
int
|
||||
card_store_subkey (KBNODE node, int use)
|
||||
{
|
||||
struct agent_card_info_s info;
|
||||
int okay = 0;
|
||||
int rc;
|
||||
int keyno, i;
|
||||
PKT_secret_key *copied_sk = NULL;
|
||||
PKT_secret_key *sk;
|
||||
size_t n;
|
||||
const char *s;
|
||||
int allow_keyno[3];
|
||||
unsigned int nbits;
|
||||
/* struct agent_card_info_s info; */
|
||||
/* int okay = 0; */
|
||||
/* int rc; */
|
||||
/* int keyno, i; */
|
||||
/* PKT_secret_key *copied_sk = NULL; */
|
||||
/* PKT_secret_key *sk; */
|
||||
/* size_t n; */
|
||||
/* const char *s; */
|
||||
/* int allow_keyno[3]; */
|
||||
/* unsigned int nbits; */
|
||||
|
||||
|
||||
assert (node->pkt->pkttype == PKT_SECRET_KEY
|
||||
|| node->pkt->pkttype == PKT_SECRET_SUBKEY);
|
||||
sk = node->pkt->pkt.secret_key;
|
||||
/* assert (node->pkt->pkttype == PKT_SECRET_KEY */
|
||||
/* || node->pkt->pkttype == PKT_SECRET_SUBKEY); */
|
||||
/* sk = node->pkt->pkt.secret_key; */
|
||||
|
||||
if (get_info_for_key_operation (&info))
|
||||
return 0;
|
||||
/* if (get_info_for_key_operation (&info)) */
|
||||
/* return 0; */
|
||||
|
||||
if (!info.extcap.ki)
|
||||
{
|
||||
tty_printf ("The card does not support the import of keys\n");
|
||||
tty_printf ("\n");
|
||||
goto leave;
|
||||
}
|
||||
/* if (!info.extcap.ki) */
|
||||
/* { */
|
||||
/* tty_printf ("The card does not support the import of keys\n"); */
|
||||
/* tty_printf ("\n"); */
|
||||
/* 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) )
|
||||
{
|
||||
tty_printf ("You may only store a 1024 bit RSA key on the card\n");
|
||||
tty_printf ("\n");
|
||||
goto leave;
|
||||
}
|
||||
/* 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 ("\n"); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
|
||||
allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG)));
|
||||
allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC)));
|
||||
allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH)));
|
||||
/* allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG))); */
|
||||
/* allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC))); */
|
||||
/* 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])
|
||||
tty_printf (_(" (1) Signature key\n"));
|
||||
if (allow_keyno[1])
|
||||
tty_printf (_(" (2) Encryption key\n"));
|
||||
if (allow_keyno[2])
|
||||
tty_printf (_(" (3) Authentication key\n"));
|
||||
/* if (allow_keyno[0]) */
|
||||
/* tty_printf (_(" (1) Signature key\n")); */
|
||||
/* if (allow_keyno[1]) */
|
||||
/* tty_printf (_(" (2) Encryption key\n")); */
|
||||
/* if (allow_keyno[2]) */
|
||||
/* tty_printf (_(" (3) Authentication key\n")); */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char *answer = cpr_get ("cardedit.genkeys.storekeytype",
|
||||
_("Your selection? "));
|
||||
cpr_kill_prompt();
|
||||
if (*answer == CONTROL_D || !*answer)
|
||||
{
|
||||
xfree (answer);
|
||||
goto leave;
|
||||
}
|
||||
keyno = *answer? atoi(answer): 0;
|
||||
xfree(answer);
|
||||
if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1])
|
||||
{
|
||||
if (info.is_v2 && !info.extcap.aac
|
||||
&& info.key_attr[keyno-1].nbits != nbits)
|
||||
{
|
||||
tty_printf ("Key does not match the card's capability.\n");
|
||||
}
|
||||
else
|
||||
break; /* Okay. */
|
||||
}
|
||||
else
|
||||
tty_printf(_("Invalid selection.\n"));
|
||||
}
|
||||
/* for (;;) */
|
||||
/* { */
|
||||
/* char *answer = cpr_get ("cardedit.genkeys.storekeytype", */
|
||||
/* _("Your selection? ")); */
|
||||
/* cpr_kill_prompt(); */
|
||||
/* if (*answer == CONTROL_D || !*answer) */
|
||||
/* { */
|
||||
/* xfree (answer); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
/* keyno = *answer? atoi(answer): 0; */
|
||||
/* xfree(answer); */
|
||||
/* if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1]) */
|
||||
/* { */
|
||||
/* if (info.is_v2 && !info.extcap.aac */
|
||||
/* && info.key_attr[keyno-1].nbits != nbits) */
|
||||
/* { */
|
||||
/* tty_printf ("Key does not match the card's capability.\n"); */
|
||||
/* } */
|
||||
/* else */
|
||||
/* break; /\* Okay. *\/ */
|
||||
/* } */
|
||||
/* else */
|
||||
/* tty_printf(_("Invalid selection.\n")); */
|
||||
/* } */
|
||||
|
||||
if (replace_existing_key_p (&info, keyno))
|
||||
goto leave;
|
||||
/* if (replace_existing_key_p (&info, keyno)) */
|
||||
/* goto leave; */
|
||||
|
||||
/* Unprotect key. */
|
||||
switch (is_secret_key_protected (sk) )
|
||||
{
|
||||
case 0: /* Not protected. */
|
||||
break;
|
||||
case -1:
|
||||
log_error (_("unknown key protection algorithm\n"));
|
||||
goto leave;
|
||||
default:
|
||||
if (sk->protect.s2k.mode == 1001)
|
||||
{
|
||||
log_error (_("secret parts of key are not available\n"));
|
||||
goto leave;
|
||||
}
|
||||
if (sk->protect.s2k.mode == 1002)
|
||||
{
|
||||
log_error (_("secret key already stored on a card\n"));
|
||||
goto leave;
|
||||
}
|
||||
/* We better copy the key before we unprotect it. */
|
||||
copied_sk = sk = copy_secret_key (NULL, sk);
|
||||
rc = 0/*check_secret_key (sk, 0)*/;
|
||||
if (rc)
|
||||
goto leave;
|
||||
}
|
||||
/* /\* Unprotect key. *\/ */
|
||||
/* switch (is_secret_key_protected (sk) ) */
|
||||
/* { */
|
||||
/* case 0: /\* Not protected. *\/ */
|
||||
/* break; */
|
||||
/* case -1: */
|
||||
/* log_error (_("unknown key protection algorithm\n")); */
|
||||
/* goto leave; */
|
||||
/* default: */
|
||||
/* if (sk->protect.s2k.mode == 1001) */
|
||||
/* { */
|
||||
/* log_error (_("secret parts of key are not available\n")); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
/* if (sk->protect.s2k.mode == 1002) */
|
||||
/* { */
|
||||
/* log_error (_("secret key already stored on a card\n")); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
/* /\* We better copy the key before we unprotect it. *\/ */
|
||||
/* copied_sk = sk = copy_secret_key (NULL, sk); */
|
||||
/* rc = 0/\*check_secret_key (sk, 0)*\/; */
|
||||
/* if (rc) */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
|
||||
#warning code save_unprotected_key_to_card
|
||||
/* rc = save_unprotected_key_to_card (sk, keyno); */
|
||||
/* if (rc) */
|
||||
/* { */
|
||||
/* log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
/* #warning code save_unprotected_key_to_card */
|
||||
/* /\* rc = save_unprotected_key_to_card (sk, keyno); *\/ */
|
||||
/* /\* if (rc) *\/ */
|
||||
/* /\* { *\/ */
|
||||
/* /\* log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); *\/ */
|
||||
/* /\* goto leave; *\/ */
|
||||
/* /\* } *\/ */
|
||||
|
||||
/* Get back to the maybe protected original secret key. */
|
||||
if (copied_sk)
|
||||
{
|
||||
free_secret_key (copied_sk);
|
||||
copied_sk = NULL;
|
||||
}
|
||||
sk = node->pkt->pkt.secret_key;
|
||||
/* /\* Get back to the maybe protected original secret key. *\/ */
|
||||
/* if (copied_sk) */
|
||||
/* { */
|
||||
/* free_secret_key (copied_sk); */
|
||||
/* copied_sk = NULL; */
|
||||
/* } */
|
||||
/* sk = node->pkt->pkt.secret_key; */
|
||||
|
||||
/* Get rid of the secret key parameters and store the serial numer. */
|
||||
n = pubkey_get_nskey (sk->pubkey_algo);
|
||||
for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++)
|
||||
{
|
||||
gcry_mpi_release (sk->skey[i]);
|
||||
sk->skey[i] = NULL;
|
||||
}
|
||||
i = pubkey_get_npkey (sk->pubkey_algo);
|
||||
sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8);
|
||||
sk->is_protected = 1;
|
||||
sk->protect.s2k.mode = 1002;
|
||||
s = info.serialno;
|
||||
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);
|
||||
/* /\* Get rid of the secret key parameters and store the serial numer. *\/ */
|
||||
/* n = pubkey_get_nskey (sk->pubkey_algo); */
|
||||
/* for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++) */
|
||||
/* { */
|
||||
/* gcry_mpi_release (sk->skey[i]); */
|
||||
/* sk->skey[i] = NULL; */
|
||||
/* } */
|
||||
/* i = pubkey_get_npkey (sk->pubkey_algo); */
|
||||
/* sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); */
|
||||
/* sk->is_protected = 1; */
|
||||
/* sk->protect.s2k.mode = 1002; */
|
||||
/* s = info.serialno; */
|
||||
/* 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); */
|
||||
|
||||
okay = 1;
|
||||
/* okay = 1; */
|
||||
|
||||
leave:
|
||||
if (copied_sk)
|
||||
free_secret_key (copied_sk);
|
||||
agent_release_card_info (&info);
|
||||
return okay;
|
||||
/* leave: */
|
||||
/* if (copied_sk) */
|
||||
/* free_secret_key (copied_sk); */
|
||||
/* agent_release_card_info (&info); */
|
||||
/* return okay; */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
38
g10/delkey.c
38
g10/delkey.c
@ -54,7 +54,6 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
|
||||
KBNODE node;
|
||||
KEYDB_HANDLE hd = keydb_new ();
|
||||
PKT_public_key *pk = NULL;
|
||||
PKT_secret_key *sk = NULL;
|
||||
u32 keyid[2];
|
||||
int okay=0;
|
||||
int yes;
|
||||
@ -91,28 +90,19 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if( secret )
|
||||
{
|
||||
sk = node->pkt->pkt.secret_key;
|
||||
keyid_from_sk( sk, keyid );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* public */
|
||||
pk = node->pkt->pkt.public_key;
|
||||
keyid_from_pk( pk, keyid );
|
||||
pk = node->pkt->pkt.public_key;
|
||||
keyid_from_pk( pk, keyid );
|
||||
|
||||
if(!force)
|
||||
{
|
||||
if (have_secret_key_with_kid (keyid))
|
||||
{
|
||||
*r_sec_avail = 1;
|
||||
rc = -1;
|
||||
goto leave;
|
||||
}
|
||||
else
|
||||
rc = 0;
|
||||
}
|
||||
if (!force)
|
||||
{
|
||||
if (have_secret_key_with_kid (keyid))
|
||||
{
|
||||
*r_sec_avail = 1;
|
||||
rc = -1;
|
||||
goto leave;
|
||||
}
|
||||
else
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
if( rc )
|
||||
@ -133,9 +123,9 @@ do_delete_key( const char *username, int secret, int force, int *r_sec_avail )
|
||||
}
|
||||
else {
|
||||
if( secret )
|
||||
print_seckey_info( sk );
|
||||
print_seckey_info (pk);
|
||||
else
|
||||
print_pubkey_info(NULL, pk );
|
||||
print_pubkey_info (NULL, pk );
|
||||
tty_printf( "\n" );
|
||||
|
||||
yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay"
|
||||
|
791
g10/export.c
791
g10/export.c
@ -190,10 +190,7 @@ subkey_in_list_p (subkey_list_t list, KBNODE node)
|
||||
{
|
||||
u32 kid[2];
|
||||
|
||||
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
||||
keyid_from_pk (node->pkt->pkt.public_key, kid);
|
||||
else
|
||||
keyid_from_sk (node->pkt->pkt.secret_key, kid);
|
||||
keyid_from_pk (node->pkt->pkt.public_key, kid);
|
||||
|
||||
for (; list; list = list->next)
|
||||
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);
|
||||
|
||||
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);
|
||||
else if (node->pkt->pkttype == PKT_SECRET_SUBKEY)
|
||||
keyid_from_sk (node->pkt->pkt.secret_key, list->kid);
|
||||
|
||||
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_LONG_KID:
|
||||
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
||||
keyid_from_pk (node->pkt->pkt.public_key, kid);
|
||||
else
|
||||
keyid_from_sk (node->pkt->pkt.secret_key, kid);
|
||||
keyid_from_pk (node->pkt->pkt.public_key, kid);
|
||||
break;
|
||||
|
||||
case KEYDB_SEARCH_MODE_FPR16:
|
||||
case KEYDB_SEARCH_MODE_FPR20:
|
||||
case KEYDB_SEARCH_MODE_FPR:
|
||||
if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
|
||||
fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
|
||||
else
|
||||
fingerprint_from_sk (node->pkt->pkt.secret_key, fpr,&fprlen);
|
||||
fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -287,451 +277,466 @@ exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
|
||||
|
||||
/* If keyblock_out is non-NULL, AND the exit code is zero, then it
|
||||
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
|
||||
do_export_stream( IOBUF out, strlist_t users, int secret,
|
||||
KBNODE *keyblock_out, unsigned int options, int *any )
|
||||
do_export_stream (iobuf_t out, strlist_t users, int secret,
|
||||
kbnode_t *keyblock_out, unsigned int options, int *any)
|
||||
{
|
||||
int rc = 0;
|
||||
gpg_error_t err;
|
||||
PACKET pkt;
|
||||
KBNODE keyblock = NULL;
|
||||
KBNODE kbctx, node;
|
||||
size_t ndesc, descindex;
|
||||
KEYDB_SEARCH_DESC *desc = NULL;
|
||||
subkey_list_t subkey_list = NULL; /* Track alreay processed subkeys. */
|
||||
KEYDB_HANDLE kdbhd;
|
||||
strlist_t sl;
|
||||
int indent = 0;
|
||||
gpg_error_t err = 0;
|
||||
PACKET pkt;
|
||||
KBNODE keyblock = NULL;
|
||||
KBNODE kbctx, node;
|
||||
size_t ndesc, descindex;
|
||||
KEYDB_SEARCH_DESC *desc = NULL;
|
||||
subkey_list_t subkey_list = NULL; /* Track already processed subkeys. */
|
||||
KEYDB_HANDLE kdbhd;
|
||||
strlist_t sl;
|
||||
int indent = 0;
|
||||
|
||||
*any = 0;
|
||||
init_packet( &pkt );
|
||||
kdbhd = keydb_new ();
|
||||
*any = 0;
|
||||
init_packet (&pkt);
|
||||
kdbhd = keydb_new ();
|
||||
|
||||
if (!users) {
|
||||
ndesc = 1;
|
||||
desc = xcalloc ( ndesc, sizeof *desc );
|
||||
desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
|
||||
if (!users)
|
||||
{
|
||||
ndesc = 1;
|
||||
desc = xcalloc (ndesc, sizeof *desc);
|
||||
desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
|
||||
}
|
||||
else {
|
||||
for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
|
||||
;
|
||||
desc = xmalloc ( ndesc * sizeof *desc);
|
||||
else
|
||||
{
|
||||
for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
|
||||
;
|
||||
desc = xmalloc ( ndesc * sizeof *desc);
|
||||
|
||||
for (ndesc=0, sl=users; sl; sl = sl->next) {
|
||||
if (!(err=classify_user_id (sl->d, desc+ndesc)))
|
||||
ndesc++;
|
||||
else
|
||||
log_error (_("key \"%s\" not found: %s\n"),
|
||||
sl->d, gpg_strerror (err));
|
||||
for (ndesc=0, sl=users; sl; sl = sl->next)
|
||||
{
|
||||
if (!(err=classify_user_id (sl->d, desc+ndesc)))
|
||||
ndesc++;
|
||||
else
|
||||
log_error (_("key \"%s\" not found: %s\n"),
|
||||
sl->d, gpg_strerror (err));
|
||||
}
|
||||
|
||||
/* It would be nice to see which of the given users did
|
||||
actually match one in the keyring. To implement this we
|
||||
need to have a found flag for each entry in desc and to set
|
||||
this we must check all those entries after a match to mark
|
||||
all matched one - currently we stop at the first match. To
|
||||
do this we need an extra flag to enable this feature so */
|
||||
/* It would be nice to see which of the given users did actually
|
||||
match one in the keyring. To implement this we need to have
|
||||
a found flag for each entry in desc. To set this flag we
|
||||
must check all those entries after a match to mark all
|
||||
matched one - currently we stop at the first match. To do
|
||||
this we need an extra flag to enable this feature. */
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SELINUX_HACKS
|
||||
if (secret) {
|
||||
log_error (_("exporting secret keys not allowed\n"));
|
||||
rc = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
if (secret)
|
||||
{
|
||||
log_error (_("exporting secret keys not allowed\n"));
|
||||
err = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (!(rc = keydb_search2 (kdbhd, desc, ndesc, &descindex))) {
|
||||
int sha1_warned=0,skip_until_subkey=0;
|
||||
u32 sk_keyid[2];
|
||||
while (!(err = keydb_search2 (kdbhd, desc, ndesc, &descindex)))
|
||||
{
|
||||
int sha1_warned = 0;
|
||||
int skip_until_subkey = 0;
|
||||
u32 keyid[2];
|
||||
|
||||
if (!users)
|
||||
desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
|
||||
if (!users)
|
||||
desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
|
||||
|
||||
/* Read the keyblock. */
|
||||
rc = keydb_get_keyblock (kdbhd, &keyblock );
|
||||
if( rc ) {
|
||||
log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
|
||||
goto leave;
|
||||
/* Read the keyblock. */
|
||||
err = keydb_get_keyblock (kdbhd, &keyblock);
|
||||
if (err)
|
||||
{
|
||||
log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if((node=find_kbnode(keyblock,PKT_SECRET_KEY)))
|
||||
{
|
||||
PKT_secret_key *sk=node->pkt->pkt.secret_key;
|
||||
if ((node=find_kbnode(keyblock, 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. */
|
||||
if( secret == 2 && !sk->is_protected )
|
||||
{
|
||||
log_info(_("key %s: not protected - skipped\n"),
|
||||
keystr(sk_keyid));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No v3 keys with GNU mode 1001. */
|
||||
if( secret == 2 && sk->version == 3 )
|
||||
{
|
||||
log_info(_("key %s: PGP 2.x style key - skipped\n"),
|
||||
keystr(sk_keyid));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* It does not make sense to export a key with a primary
|
||||
key on card using a non-key stub. We simply skip those
|
||||
keys when used with --export-secret-subkeys. */
|
||||
if (secret == 2 && sk->is_protected
|
||||
&& sk->protect.s2k.mode == 1002 )
|
||||
{
|
||||
log_info(_("key %s: key material on-card - skipped\n"),
|
||||
keystr(sk_keyid));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's a public key export, so do the cleaning if
|
||||
requested. Note that both export-clean and
|
||||
export-minimal only apply to UID sigs (0x10, 0x11,
|
||||
0x12, and 0x13). A designated revocation is never
|
||||
stripped, even with export-minimal set. */
|
||||
|
||||
if(options&EXPORT_CLEAN)
|
||||
clean_key(keyblock,opt.verbose,options&EXPORT_MINIMAL,NULL,NULL);
|
||||
}
|
||||
|
||||
/* And write it. */
|
||||
for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
|
||||
if( skip_until_subkey )
|
||||
{
|
||||
if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY
|
||||
|| node->pkt->pkttype==PKT_SECRET_SUBKEY)
|
||||
skip_until_subkey=0;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We used to use comment packets, but not any longer. In
|
||||
case we still have comments on a key, strip them here
|
||||
before we call build_packet(). */
|
||||
if( node->pkt->pkttype == PKT_COMMENT )
|
||||
continue;
|
||||
|
||||
/* Make sure that ring_trust packets never get exported. */
|
||||
if (node->pkt->pkttype == PKT_RING_TRUST)
|
||||
/* We can't apply GNU mode 1001 on an unprotected key. */
|
||||
if( secret == 2
|
||||
&& pk->seckey_info && !pk->seckey_info->is_protected )
|
||||
{
|
||||
log_info (_("key %s: not protected - skipped\n"),
|
||||
keystr (keyid));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If exact is set, then we only export what was requested
|
||||
(plus the primary key, if the user didn't specifically
|
||||
request it). */
|
||||
if(desc[descindex].exact
|
||||
&& (node->pkt->pkttype==PKT_PUBLIC_SUBKEY
|
||||
|| node->pkt->pkttype==PKT_SECRET_SUBKEY))
|
||||
{
|
||||
if (!exact_subkey_match_p (desc+descindex, node))
|
||||
{
|
||||
/* Before skipping this subkey, check whether any
|
||||
other description wants an exact match on a
|
||||
subkey and include that subkey into the output
|
||||
too. Need to add this subkey to a list so that
|
||||
it won't get processed a second time.
|
||||
/* No v3 keys with GNU mode 1001. */
|
||||
if( secret == 2 && pk->version == 3 )
|
||||
{
|
||||
log_info(_("key %s: PGP 2.x style key - skipped\n"),
|
||||
keystr (keyid));
|
||||
continue;
|
||||
}
|
||||
|
||||
So the first step here is to check that list and
|
||||
skip in any case if the key is in that list.
|
||||
/* It does not make sense to export a key with a primary
|
||||
key on card using a non-key stub. We simply skip those
|
||||
keys when used with --export-secret-subkeys. */
|
||||
if (secret == 2
|
||||
&& pk->seckey_info && pk->seckey_info->is_protected
|
||||
&& pk->seckey_info->s2k.mode == 1002 )
|
||||
{
|
||||
log_info(_("key %s: key material on-card - skipped\n"),
|
||||
keystr (keyid));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's a public key export, so do the cleaning if
|
||||
requested. Note that both export-clean and
|
||||
export-minimal only apply to UID sigs (0x10, 0x11, 0x12,
|
||||
and 0x13). A designated revocation is never stripped,
|
||||
even with export-minimal set. */
|
||||
if ( (options & EXPORT_CLEAN) )
|
||||
clean_key (keyblock, opt.verbose, options&EXPORT_MINIMAL,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
We need this whole mess because the import
|
||||
function is not able to merge secret keys and
|
||||
thus it is useless to output them as two
|
||||
separate keys and have import merge them. */
|
||||
if (subkey_in_list_p (subkey_list, node))
|
||||
skip_until_subkey = 1; /* Already processed this one. */
|
||||
else
|
||||
{
|
||||
size_t j;
|
||||
/* And write it. */
|
||||
for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
|
||||
{
|
||||
if (skip_until_subkey)
|
||||
{
|
||||
if (node->pkt->pkttype==PKT_PUBLIC_SUBKEY
|
||||
|| node->pkt->pkttype==PKT_SECRET_SUBKEY)
|
||||
skip_until_subkey = 0;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j=0; j < ndesc; j++)
|
||||
if (j != descindex && desc[j].exact
|
||||
&& exact_subkey_match_p (desc+j, node))
|
||||
break;
|
||||
if (!(j < ndesc))
|
||||
skip_until_subkey = 1; /* No other one matching. */
|
||||
}
|
||||
}
|
||||
/* We used to use comment packets, but not any longer. In
|
||||
case we still have comments on a key, strip them here
|
||||
before we call build_packet(). */
|
||||
if (node->pkt->pkttype == PKT_COMMENT)
|
||||
continue;
|
||||
|
||||
if(skip_until_subkey)
|
||||
continue;
|
||||
/* Make sure that ring_trust packets never get exported. */
|
||||
if (node->pkt->pkttype == PKT_RING_TRUST)
|
||||
continue;
|
||||
|
||||
/* Mark this one as processed. */
|
||||
/* If exact is set, then we only export what was requested
|
||||
(plus the primary key, if the user didn't specifically
|
||||
request it). */
|
||||
if (desc[descindex].exact
|
||||
&& (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|
||||
|| node->pkt->pkttype == PKT_SECRET_SUBKEY))
|
||||
{
|
||||
if (!exact_subkey_match_p (desc+descindex, node))
|
||||
{
|
||||
subkey_list_t tmp = new_subkey_list_item (node);
|
||||
tmp->next = subkey_list;
|
||||
subkey_list = tmp;
|
||||
/* Before skipping this subkey, check whether any
|
||||
other description wants an exact match on a
|
||||
subkey and include that subkey into the output
|
||||
too. Need to add this subkey to a list so that
|
||||
it won't get processed a second time.
|
||||
|
||||
So the first step here is to check that list and
|
||||
skip in any case if the key is in that list.
|
||||
|
||||
We need this whole mess because the import
|
||||
function is not able to merge secret keys and
|
||||
thus it is useless to output them as two separate
|
||||
keys and have import merge them. */
|
||||
if (subkey_in_list_p (subkey_list, node))
|
||||
skip_until_subkey = 1; /* Already processed this one. */
|
||||
else
|
||||
{
|
||||
size_t j;
|
||||
|
||||
for (j=0; j < ndesc; j++)
|
||||
if (j != descindex && desc[j].exact
|
||||
&& exact_subkey_match_p (desc+j, node))
|
||||
break;
|
||||
if (!(j < ndesc))
|
||||
skip_until_subkey = 1; /* No other one matching. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(node->pkt->pkttype==PKT_SIGNATURE)
|
||||
{
|
||||
/* do not export packets which are marked as not
|
||||
exportable */
|
||||
if(!(options&EXPORT_LOCAL_SIGS)
|
||||
&& !node->pkt->pkt.signature->flags.exportable)
|
||||
continue; /* not exportable */
|
||||
if(skip_until_subkey)
|
||||
continue;
|
||||
|
||||
/* Do not export packets with a "sensitive" revocation
|
||||
key unless the user wants us to. Note that we do
|
||||
export these when issuing the actual revocation
|
||||
(see revoke.c). */
|
||||
if(!(options&EXPORT_SENSITIVE_REVKEYS)
|
||||
&& node->pkt->pkt.signature->revkey)
|
||||
{
|
||||
int i;
|
||||
/* Mark this one as processed. */
|
||||
{
|
||||
subkey_list_t tmp = new_subkey_list_item (node);
|
||||
tmp->next = subkey_list;
|
||||
subkey_list = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
|
||||
if(node->pkt->pkt.signature->revkey[i]->class & 0x40)
|
||||
break;
|
||||
if (node->pkt->pkttype == PKT_SIGNATURE)
|
||||
{
|
||||
/* Do not export packets which are marked as not
|
||||
exportable. */
|
||||
if (!(options&EXPORT_LOCAL_SIGS)
|
||||
&& !node->pkt->pkt.signature->flags.exportable)
|
||||
continue; /* not exportable */
|
||||
|
||||
if(i<node->pkt->pkt.signature->numrevkeys)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Do not export packets with a "sensitive" revocation
|
||||
key unless the user wants us to. Note that we do
|
||||
export these when issuing the actual revocation
|
||||
(see revoke.c). */
|
||||
if (!(options&EXPORT_SENSITIVE_REVKEYS)
|
||||
&& node->pkt->pkt.signature->revkey)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Don't export attribs? */
|
||||
if( !(options&EXPORT_ATTRIBUTES) &&
|
||||
node->pkt->pkttype == PKT_USER_ID &&
|
||||
node->pkt->pkt.user_id->attrib_data ) {
|
||||
for (i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
|
||||
if ( (node->pkt->pkt.signature->revkey[i]->class & 0x40))
|
||||
break;
|
||||
|
||||
if (i < node->pkt->pkt.signature->numrevkeys)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't export attribs? */
|
||||
if (!(options&EXPORT_ATTRIBUTES)
|
||||
&& node->pkt->pkttype == PKT_USER_ID
|
||||
&& node->pkt->pkt.user_id->attrib_data )
|
||||
{
|
||||
/* Skip until we get to something that is not an attrib
|
||||
or a signature on an attrib */
|
||||
while(kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE) {
|
||||
kbctx=kbctx->next;
|
||||
}
|
||||
while (kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE)
|
||||
kbctx = kbctx->next;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY )
|
||||
{
|
||||
/* We don't want to export the secret parts of the
|
||||
* primary key, this is done by using GNU protection mode 1001
|
||||
*/
|
||||
int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode;
|
||||
node->pkt->pkt.secret_key->protect.s2k.mode = 1001;
|
||||
if ((options&EXPORT_SEXP_FORMAT))
|
||||
rc = build_sexp (out, node->pkt, &indent);
|
||||
else
|
||||
rc = build_packet (out, node->pkt);
|
||||
node->pkt->pkt.secret_key->protect.s2k.mode = save_mode;
|
||||
}
|
||||
else if (secret == 2 && node->pkt->pkttype == PKT_SECRET_SUBKEY
|
||||
&& (opt.export_options&EXPORT_RESET_SUBKEY_PASSWD))
|
||||
{
|
||||
/* If the subkey is protected reset the passphrase to
|
||||
export an unprotected subkey. This feature is
|
||||
useful in cases of a subkey copied to an unattended
|
||||
machine where a passphrase is not required. */
|
||||
PKT_secret_key *sk_save, *sk;
|
||||
if (secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY)
|
||||
{
|
||||
/* We don't want to export the secret parts of the
|
||||
* primary key, this is done by temporary switching to
|
||||
* GNU protection mode 1001. */
|
||||
int save_mode = node->pkt->pkt.public_key->seckey_info->s2k.mode;
|
||||
node->pkt->pkt.public_key->seckey_info->s2k.mode = 1001;
|
||||
if ((options&EXPORT_SEXP_FORMAT))
|
||||
err = build_sexp (out, node->pkt, &indent);
|
||||
else
|
||||
err = build_packet (out, node->pkt);
|
||||
node->pkt->pkt.public_key->seckey_info->s2k.mode = save_mode;
|
||||
}
|
||||
else if (secret == 2 && node->pkt->pkttype == PKT_SECRET_SUBKEY
|
||||
&& (opt.export_options&EXPORT_RESET_SUBKEY_PASSWD))
|
||||
{
|
||||
/* If the subkey is protected reset the passphrase to
|
||||
export an unprotected subkey. This feature is useful
|
||||
in cases of a subkey copied to an unattended machine
|
||||
where a passphrase is not required. */
|
||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
goto leave;
|
||||
#warning We need to implement this
|
||||
/* PKT_secret_key *sk_save, *sk; */
|
||||
|
||||
sk_save = node->pkt->pkt.secret_key;
|
||||
sk = copy_secret_key (NULL, sk_save);
|
||||
node->pkt->pkt.secret_key = sk;
|
||||
/* 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;
|
||||
}
|
||||
/* log_info (_("about to export an unprotected subkey\n")); */
|
||||
/* 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))
|
||||
rc = build_sexp (out, node->pkt, &indent);
|
||||
else
|
||||
rc = build_packet (out, node->pkt);
|
||||
/* 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
|
||||
{
|
||||
/* Warn the user if the secret key or any of the secret
|
||||
subkeys are protected with SHA1 and we have
|
||||
simple_sk_checksum set. */
|
||||
if(!sha1_warned && opt.simple_sk_checksum &&
|
||||
(node->pkt->pkttype==PKT_SECRET_KEY ||
|
||||
node->pkt->pkttype==PKT_SECRET_SUBKEY) &&
|
||||
node->pkt->pkt.secret_key->protect.sha1chk)
|
||||
{
|
||||
/* I hope this warning doesn't confuse people. */
|
||||
log_info(_("WARNING: secret key %s does not have a "
|
||||
"simple SK checksum\n"),keystr(sk_keyid));
|
||||
/* node->pkt->pkt.secret_key = sk_save; */
|
||||
/* free_secret_key (sk); */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Warn the user if the secret key or any of the secret
|
||||
subkeys are protected with SHA1 and we have
|
||||
simple_sk_checksum set. */
|
||||
if (!sha1_warned && opt.simple_sk_checksum &&
|
||||
(node->pkt->pkttype == PKT_SECRET_KEY
|
||||
|| node->pkt->pkttype == PKT_SECRET_SUBKEY)
|
||||
&& node->pkt->pkt.public_key->seckey_info->sha1chk)
|
||||
{
|
||||
/* I hope this warning doesn't confuse people. */
|
||||
log_info(_("WARNING: secret key %s does not have a "
|
||||
"simple SK checksum\n"), keystr (keyid));
|
||||
|
||||
sha1_warned=1;
|
||||
}
|
||||
sha1_warned = 1;
|
||||
}
|
||||
|
||||
if ((options&EXPORT_SEXP_FORMAT))
|
||||
rc = build_sexp (out, node->pkt, &indent);
|
||||
else
|
||||
rc = build_packet (out, node->pkt);
|
||||
}
|
||||
if ((options&EXPORT_SEXP_FORMAT))
|
||||
err = build_sexp (out, node->pkt, &indent);
|
||||
else
|
||||
err = build_packet (out, node->pkt);
|
||||
}
|
||||
|
||||
if( rc ) {
|
||||
log_error("build_packet(%d) failed: %s\n",
|
||||
node->pkt->pkttype, g10_errstr(rc) );
|
||||
goto leave;
|
||||
if (err)
|
||||
{
|
||||
log_error ("build_packet(%d) failed: %s\n",
|
||||
node->pkt->pkttype, gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
if ((options&EXPORT_SEXP_FORMAT) && indent)
|
||||
{
|
||||
for (; indent; indent--)
|
||||
iobuf_put (out, ')');
|
||||
iobuf_put (out, '\n');
|
||||
}
|
||||
if ((options&EXPORT_SEXP_FORMAT) && indent)
|
||||
{
|
||||
for (; indent; indent--)
|
||||
iobuf_put (out, ')');
|
||||
iobuf_put (out, '\n');
|
||||
}
|
||||
|
||||
++*any;
|
||||
if(keyblock_out)
|
||||
{
|
||||
*keyblock_out=keyblock;
|
||||
break;
|
||||
}
|
||||
++*any;
|
||||
if(keyblock_out)
|
||||
{
|
||||
*keyblock_out=keyblock;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((options&EXPORT_SEXP_FORMAT) && indent)
|
||||
{
|
||||
for (; indent; indent--)
|
||||
iobuf_put (out, ')');
|
||||
iobuf_put (out, '\n');
|
||||
}
|
||||
if( rc == -1 )
|
||||
rc = 0;
|
||||
if ((options&EXPORT_SEXP_FORMAT) && indent)
|
||||
{
|
||||
for (; indent; indent--)
|
||||
iobuf_put (out, ')');
|
||||
iobuf_put (out, '\n');
|
||||
}
|
||||
if( err == -1 )
|
||||
err = 0;
|
||||
|
||||
leave:
|
||||
release_subkey_list (subkey_list);
|
||||
xfree(desc);
|
||||
keydb_release (kdbhd);
|
||||
if(rc || keyblock_out==NULL)
|
||||
release_kbnode( keyblock );
|
||||
if( !*any )
|
||||
log_info(_("WARNING: nothing exported\n"));
|
||||
return rc;
|
||||
leave:
|
||||
release_subkey_list (subkey_list);
|
||||
xfree(desc);
|
||||
keydb_release (kdbhd);
|
||||
if (err || !keyblock_out)
|
||||
release_kbnode( keyblock );
|
||||
if( !*any )
|
||||
log_info(_("WARNING: nothing exported\n"));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
write_sexp_line (iobuf_t out, int *indent, const char *text)
|
||||
{
|
||||
int i;
|
||||
/* static int */
|
||||
/* write_sexp_line (iobuf_t out, int *indent, const char *text) */
|
||||
/* { */
|
||||
/* int i; */
|
||||
|
||||
for (i=0; i < *indent; i++)
|
||||
iobuf_put (out, ' ');
|
||||
iobuf_writestr (out, text);
|
||||
return 0;
|
||||
}
|
||||
/* for (i=0; i < *indent; i++) */
|
||||
/* iobuf_put (out, ' '); */
|
||||
/* iobuf_writestr (out, text); */
|
||||
/* return 0; */
|
||||
/* } */
|
||||
|
||||
static int
|
||||
write_sexp_keyparm (iobuf_t out, int *indent, const char *name, gcry_mpi_t a)
|
||||
{
|
||||
int rc;
|
||||
unsigned char *buffer;
|
||||
/* static int */
|
||||
/* write_sexp_keyparm (iobuf_t out, int *indent, const char *name, gcry_mpi_t a) */
|
||||
/* { */
|
||||
/* int rc; */
|
||||
/* unsigned char *buffer; */
|
||||
|
||||
write_sexp_line (out, indent, "(");
|
||||
iobuf_writestr (out, name);
|
||||
iobuf_writestr (out, " #");
|
||||
/* write_sexp_line (out, indent, "("); */
|
||||
/* iobuf_writestr (out, name); */
|
||||
/* iobuf_writestr (out, " #"); */
|
||||
|
||||
rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a);
|
||||
assert (!rc);
|
||||
iobuf_writestr (out, buffer);
|
||||
iobuf_writestr (out, "#)");
|
||||
gcry_free (buffer);
|
||||
return 0;
|
||||
}
|
||||
/* rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a); */
|
||||
/* assert (!rc); */
|
||||
/* iobuf_writestr (out, buffer); */
|
||||
/* iobuf_writestr (out, "#)"); */
|
||||
/* gcry_free (buffer); */
|
||||
/* return 0; */
|
||||
/* } */
|
||||
|
||||
static int
|
||||
build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
|
||||
{
|
||||
PKT_secret_key *sk = pkt->pkt.secret_key;
|
||||
char tmpbuf[100];
|
||||
/* FIXME: Not yet implemented. */
|
||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
/* PKT_secret_key *sk = pkt->pkt.secret_key; */
|
||||
/* char tmpbuf[100]; */
|
||||
|
||||
if (pkt->pkttype == PKT_SECRET_KEY)
|
||||
{
|
||||
iobuf_writestr (out, "(openpgp-key\n");
|
||||
(*indent)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
iobuf_writestr (out, " (subkey\n");
|
||||
(*indent)++;
|
||||
}
|
||||
(*indent)++;
|
||||
write_sexp_line (out, indent, "(private-key\n");
|
||||
(*indent)++;
|
||||
if (is_RSA (sk->pubkey_algo) && !sk->is_protected)
|
||||
{
|
||||
write_sexp_line (out, indent, "(rsa\n");
|
||||
(*indent)++;
|
||||
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, "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, "q", sk->skey[4]); iobuf_put (out,'\n');
|
||||
write_sexp_keyparm (out, indent, "u", sk->skey[5]);
|
||||
iobuf_put (out,')'); iobuf_put (out,'\n');
|
||||
(*indent)--;
|
||||
}
|
||||
else if (sk->pubkey_algo == PUBKEY_ALGO_DSA && !sk->is_protected)
|
||||
{
|
||||
write_sexp_line (out, indent, "(dsa\n");
|
||||
(*indent)++;
|
||||
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, "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, "x", sk->skey[4]);
|
||||
iobuf_put (out,')'); iobuf_put (out,'\n');
|
||||
(*indent)--;
|
||||
}
|
||||
else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected)
|
||||
{
|
||||
write_sexp_line (out, indent, "(elg\n");
|
||||
(*indent)++;
|
||||
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, "y", sk->skey[3]); iobuf_put (out,'\n');
|
||||
write_sexp_keyparm (out, indent, "x", sk->skey[4]);
|
||||
iobuf_put (out,')'); iobuf_put (out,'\n');
|
||||
(*indent)--;
|
||||
}
|
||||
write_sexp_line (out, indent, "(attrib\n"); (*indent)++;
|
||||
sprintf (tmpbuf, "(created \"%lu\"", (unsigned long)sk->timestamp);
|
||||
write_sexp_line (out, indent, tmpbuf);
|
||||
iobuf_put (out,')'); (*indent)--; /* close created */
|
||||
iobuf_put (out,')'); (*indent)--; /* close attrib */
|
||||
iobuf_put (out,')'); (*indent)--; /* close private-key */
|
||||
if (pkt->pkttype != PKT_SECRET_KEY)
|
||||
iobuf_put (out,')'), (*indent)--; /* close subkey */
|
||||
iobuf_put (out,'\n');
|
||||
/* if (pkt->pkttype == PKT_SECRET_KEY) */
|
||||
/* { */
|
||||
/* iobuf_writestr (out, "(openpgp-key\n"); */
|
||||
/* (*indent)++; */
|
||||
/* } */
|
||||
/* else */
|
||||
/* { */
|
||||
/* iobuf_writestr (out, " (subkey\n"); */
|
||||
/* (*indent)++; */
|
||||
/* } */
|
||||
/* (*indent)++; */
|
||||
/* write_sexp_line (out, indent, "(private-key\n"); */
|
||||
/* (*indent)++; */
|
||||
/* if (is_RSA (sk->pubkey_algo) && !sk->is_protected) */
|
||||
/* { */
|
||||
/* write_sexp_line (out, indent, "(rsa\n"); */
|
||||
/* (*indent)++; */
|
||||
/* 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, "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, "q", sk->skey[4]); iobuf_put (out,'\n'); */
|
||||
/* write_sexp_keyparm (out, indent, "u", sk->skey[5]); */
|
||||
/* iobuf_put (out,')'); iobuf_put (out,'\n'); */
|
||||
/* (*indent)--; */
|
||||
/* } */
|
||||
/* else if (sk->pubkey_algo == PUBKEY_ALGO_DSA && !sk->is_protected) */
|
||||
/* { */
|
||||
/* write_sexp_line (out, indent, "(dsa\n"); */
|
||||
/* (*indent)++; */
|
||||
/* 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, "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, "x", sk->skey[4]); */
|
||||
/* iobuf_put (out,')'); iobuf_put (out,'\n'); */
|
||||
/* (*indent)--; */
|
||||
/* } */
|
||||
/* else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected) */
|
||||
/* { */
|
||||
/* write_sexp_line (out, indent, "(elg\n"); */
|
||||
/* (*indent)++; */
|
||||
/* 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, "y", sk->skey[3]); iobuf_put (out,'\n'); */
|
||||
/* write_sexp_keyparm (out, indent, "x", sk->skey[4]); */
|
||||
/* iobuf_put (out,')'); iobuf_put (out,'\n'); */
|
||||
/* (*indent)--; */
|
||||
/* } */
|
||||
/* write_sexp_line (out, indent, "(attrib\n"); (*indent)++; */
|
||||
/* sprintf (tmpbuf, "(created \"%lu\"", (unsigned long)sk->timestamp); */
|
||||
/* write_sexp_line (out, indent, tmpbuf); */
|
||||
/* iobuf_put (out,')'); (*indent)--; /\* close created *\/ */
|
||||
/* iobuf_put (out,')'); (*indent)--; /\* close attrib *\/ */
|
||||
/* iobuf_put (out,')'); (*indent)--; /\* close private-key *\/ */
|
||||
/* if (pkt->pkttype != PKT_SECRET_KEY) */
|
||||
/* iobuf_put (out,')'), (*indent)--; /\* close subkey *\/ */
|
||||
/* iobuf_put (out,'\n'); */
|
||||
|
||||
return 0;
|
||||
/* return 0; */
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* free-packet.c - cleanup stuff for packets
|
||||
* 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.
|
||||
*
|
||||
@ -76,37 +76,51 @@ free_seckey_enc( PKT_signature *sig )
|
||||
|
||||
|
||||
void
|
||||
release_public_key_parts( PKT_public_key *pk )
|
||||
release_public_key_parts (PKT_public_key *pk)
|
||||
{
|
||||
int n, 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;
|
||||
int n, i;
|
||||
|
||||
if (pk->seckey_info)
|
||||
n = pubkey_get_nskey (pk->pubkey_algo);
|
||||
else
|
||||
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;
|
||||
}
|
||||
if (pk->prefs) {
|
||||
xfree (pk->prefs);
|
||||
pk->prefs = NULL;
|
||||
if (pk->seckey_info)
|
||||
{
|
||||
xfree (pk->seckey_info);
|
||||
pk->seckey_info = NULL;
|
||||
}
|
||||
if (pk->user_id) {
|
||||
free_user_id (pk->user_id);
|
||||
pk->user_id = NULL;
|
||||
if (pk->prefs)
|
||||
{
|
||||
xfree (pk->prefs);
|
||||
pk->prefs = NULL;
|
||||
}
|
||||
if (pk->revkey) {
|
||||
xfree(pk->revkey);
|
||||
pk->revkey=NULL;
|
||||
pk->numrevkeys=0;
|
||||
if (pk->user_id)
|
||||
{
|
||||
free_user_id (pk->user_id);
|
||||
pk->user_id = NULL;
|
||||
}
|
||||
if (pk->revkey)
|
||||
{
|
||||
xfree(pk->revkey);
|
||||
pk->revkey=NULL;
|
||||
pk->numrevkeys=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
free_public_key( PKT_public_key *pk )
|
||||
free_public_key (PKT_public_key *pk)
|
||||
{
|
||||
release_public_key_parts( pk );
|
||||
xfree(pk);
|
||||
release_public_key_parts (pk);
|
||||
xfree(pk);
|
||||
}
|
||||
|
||||
|
||||
@ -150,55 +164,45 @@ 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 *
|
||||
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 )
|
||||
d = xmalloc(sizeof *d);
|
||||
memcpy( d, s, sizeof *d );
|
||||
d->user_id = scopy_user_id (s->user_id);
|
||||
d->prefs = copy_prefs (s->prefs);
|
||||
n = pubkey_get_npkey( s->pubkey_algo );
|
||||
if( !n )
|
||||
d->pkey[0] = mpi_copy(s->pkey[0]);
|
||||
else {
|
||||
for(i=0; i < n; i++ )
|
||||
d->pkey[i] = mpi_copy( s->pkey[i] );
|
||||
if (!d)
|
||||
d = xmalloc (sizeof *d);
|
||||
memcpy (d, s, sizeof *d);
|
||||
d->seckey_info = NULL;
|
||||
d->user_id = scopy_user_id (s->user_id);
|
||||
d->prefs = copy_prefs (s->prefs);
|
||||
|
||||
n = pubkey_get_npkey (s->pubkey_algo);
|
||||
i = 0;
|
||||
if (!n)
|
||||
d->pkey[i++] = mpi_copy (s->pkey[0]);
|
||||
else
|
||||
{
|
||||
for (; i < n; i++ )
|
||||
d->pkey[i] = mpi_copy( s->pkey[i] );
|
||||
}
|
||||
if( !s->revkey && s->numrevkeys )
|
||||
BUG();
|
||||
if( s->numrevkeys ) {
|
||||
d->revkey = xmalloc(sizeof(struct revocation_key)*s->numrevkeys);
|
||||
memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
|
||||
for (; i < PUBKEY_MAX_NSKEY; i++)
|
||||
d->pkey[i] = NULL;
|
||||
|
||||
if (!s->revkey && s->numrevkeys)
|
||||
BUG();
|
||||
if (s->numrevkeys)
|
||||
{
|
||||
d->revkey = xmalloc(sizeof(struct revocation_key)*s->numrevkeys);
|
||||
memcpy(d->revkey,s->revkey,sizeof(struct revocation_key)*s->numrevkeys);
|
||||
}
|
||||
else
|
||||
d->revkey = NULL;
|
||||
return d;
|
||||
else
|
||||
d->revkey = NULL;
|
||||
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 *
|
||||
@ -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
|
||||
free_comment( PKT_comment *rem )
|
||||
{
|
||||
@ -407,11 +369,9 @@ free_packet( PACKET *pkt )
|
||||
break;
|
||||
case PKT_PUBLIC_KEY:
|
||||
case PKT_PUBLIC_SUBKEY:
|
||||
free_public_key( pkt->pkt.public_key );
|
||||
break;
|
||||
case PKT_SECRET_KEY:
|
||||
case PKT_SECRET_SUBKEY:
|
||||
free_secret_key( pkt->pkt.secret_key );
|
||||
free_public_key (pkt->pkt.public_key);
|
||||
break;
|
||||
case PKT_COMMENT:
|
||||
free_comment( pkt->pkt.comment );
|
||||
@ -462,59 +422,6 @@ cmp_public_keys( PKT_public_key *a, PKT_public_key *b )
|
||||
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
|
||||
|
@ -2522,7 +2522,7 @@ found:
|
||||
* so that can free it's context.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
log_debug ("FIXME: Anonymous recipient does not yet work\n");
|
||||
|
442
g10/import.c
442
g10/import.c
@ -567,19 +567,16 @@ fix_bad_direct_key_sigs (kbnode_t keyblock, u32 *keyid)
|
||||
|
||||
|
||||
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;
|
||||
char buf[MAX_FINGERPRINT_LEN*2+30], *p;
|
||||
size_t i, n;
|
||||
|
||||
sprintf (buf, "%u ", reason);
|
||||
snprintf (buf, sizeof buf, "%u ", reason);
|
||||
p = buf + strlen (buf);
|
||||
|
||||
if (pk)
|
||||
fingerprint_from_pk (pk, array, &n);
|
||||
else
|
||||
fingerprint_from_sk (sk, array, &n);
|
||||
fingerprint_from_pk (pk, array, &n);
|
||||
s = array;
|
||||
for (i=0; i < n ; i++, s++, p += 2)
|
||||
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 );
|
||||
write_status_text( STATUS_IMPORTED, us );
|
||||
xfree(us);
|
||||
print_import_ok (pk,NULL, 1);
|
||||
print_import_ok (pk, 1);
|
||||
}
|
||||
stats->imported++;
|
||||
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;
|
||||
|
||||
if (is_status_enabled ())
|
||||
print_import_ok (pk, NULL,
|
||||
((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0)));
|
||||
print_import_ok (pk, ((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
same_key = 1;
|
||||
if (is_status_enabled ())
|
||||
print_import_ok (pk, NULL, 0);
|
||||
print_import_ok (pk, 0);
|
||||
|
||||
if( !opt.quiet )
|
||||
{
|
||||
@ -1092,7 +1088,8 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
|
||||
size_t keklen;
|
||||
kbnode_t ctx = NULL;
|
||||
kbnode_t node;
|
||||
PKT_secret_key *main_sk, *sk;
|
||||
PKT_public_key *main_pk, *pk;
|
||||
struct seckey_info *ski;
|
||||
int nskey;
|
||||
membuf_t mbuf;
|
||||
int i, j;
|
||||
@ -1126,21 +1123,25 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
|
||||
xfree (kek);
|
||||
kek = NULL;
|
||||
|
||||
main_sk = NULL;
|
||||
main_pk = NULL;
|
||||
while ((node = walk_kbnode (sec_keyblock, &ctx, 0)))
|
||||
{
|
||||
if (node->pkt->pkttype != PKT_SECRET_KEY
|
||||
&& node->pkt->pkttype != PKT_SECRET_SUBKEY)
|
||||
continue;
|
||||
sk = node->pkt->pkt.secret_key;
|
||||
if (!main_sk)
|
||||
main_sk = sk;
|
||||
pk = node->pkt->pkt.public_key;
|
||||
if (!main_pk)
|
||||
main_pk = pk;
|
||||
|
||||
ski = pk->seckey_info;
|
||||
if (!ski)
|
||||
BUG ();
|
||||
|
||||
stats->count++;
|
||||
stats->secret_read++;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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");
|
||||
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");
|
||||
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[j++] = format_args_buf_int + 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
|
||||
{
|
||||
put_membuf_str (&mbuf, " _ %m");
|
||||
format_args[j++] = sk->skey + i;
|
||||
format_args[j++] = pk->pkey + i;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (sk->is_protected)
|
||||
if (ski->is_protected)
|
||||
{
|
||||
char countbuf[35];
|
||||
|
||||
snprintf (countbuf, sizeof countbuf, "%lu",
|
||||
(unsigned long)sk->protect.s2k.count);
|
||||
(unsigned long)ski->s2k.count);
|
||||
err = gcry_sexp_build
|
||||
(&prot, NULL,
|
||||
" (protection %s %s %b %d %s %b %s)\n",
|
||||
sk->protect.sha1chk? "sha1":"sum",
|
||||
openpgp_cipher_algo_name (sk->protect.algo),
|
||||
(int)sk->protect.ivlen, sk->protect.iv,
|
||||
sk->protect.s2k.mode,
|
||||
openpgp_md_algo_name (sk->protect.s2k.hash_algo),
|
||||
(int)sizeof (sk->protect.s2k.salt), sk->protect.s2k.salt,
|
||||
ski->sha1chk? "sha1":"sum",
|
||||
openpgp_cipher_algo_name (ski->algo),
|
||||
(int)ski->ivlen, ski->iv,
|
||||
ski->s2k.mode,
|
||||
openpgp_md_algo_name (ski->s2k.hash_algo),
|
||||
(int)sizeof (ski->s2k.salt), ski->s2k.salt,
|
||||
countbuf);
|
||||
}
|
||||
else
|
||||
@ -1213,9 +1214,9 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
|
||||
" %S\n"
|
||||
" (csum %d)\n"
|
||||
" %S)\n",
|
||||
sk->version,
|
||||
openpgp_pk_algo_name (sk->pubkey_algo),
|
||||
skey, (int)(unsigned long)sk->csum, prot);
|
||||
pk->version,
|
||||
openpgp_pk_algo_name (pk->pubkey_algo),
|
||||
skey, (int)(unsigned long)ski->csum, prot);
|
||||
gcry_sexp_release (skey);
|
||||
gcry_sexp_release (prot);
|
||||
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. */
|
||||
{
|
||||
char *uid, *desc;
|
||||
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;
|
||||
}
|
||||
char *desc = gpg_format_keydesc (pk, 1, 1);
|
||||
err = agent_import_key (ctrl, desc, &cache_nonce,
|
||||
wrappedkey, wrappedkeylen);
|
||||
xfree (desc);
|
||||
@ -1282,23 +1253,23 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
|
||||
{
|
||||
if (opt.verbose)
|
||||
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++;
|
||||
}
|
||||
else if ( gpg_err_code (err) == GPG_ERR_EEXIST )
|
||||
{
|
||||
if (opt.verbose)
|
||||
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;
|
||||
stats->secret_dups++;
|
||||
}
|
||||
else
|
||||
{
|
||||
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));
|
||||
if (sk->protect.algo == GCRY_CIPHER_IDEA
|
||||
if (ski->algo == GCRY_CIPHER_IDEA
|
||||
&& gpg_err_code (err) == GPG_ERR_CIPHER_ALGO)
|
||||
{
|
||||
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
|
||||
|| secnode->pkt->pkttype == PKT_SECRET_SUBKEY)
|
||||
{
|
||||
/* Make a public key. We only need to convert enough to
|
||||
write the keyblock out. */
|
||||
/* Make a public key. */
|
||||
PACKET *pkt;
|
||||
PKT_secret_key *sk;
|
||||
PKT_public_key *pk;
|
||||
int n, i;
|
||||
|
||||
pkt = xcalloc (1, sizeof *pkt);
|
||||
sk = secnode->pkt->pkt.secret_key;
|
||||
pk = xcalloc (1, sizeof *pk);
|
||||
PKT_public_key *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)
|
||||
pkt->pkttype = PKT_PUBLIC_KEY;
|
||||
else
|
||||
pkt->pkttype = PKT_PUBLIC_SUBKEY;
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
@ -1393,10 +1348,10 @@ static int
|
||||
import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
||||
struct stats_s *stats, unsigned int options)
|
||||
{
|
||||
PKT_secret_key *sk;
|
||||
PKT_public_key *pk;
|
||||
struct seckey_info *ski;
|
||||
KBNODE node, uidnode;
|
||||
u32 keyid[2];
|
||||
int have_seckey;
|
||||
int rc = 0;
|
||||
|
||||
/* 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)
|
||||
BUG ();
|
||||
|
||||
sk = node->pkt->pkt.secret_key;
|
||||
keyid_from_sk (sk, keyid);
|
||||
pk = node->pkt->pkt.public_key;
|
||||
|
||||
keyid_from_pk (pk, keyid);
|
||||
uidnode = find_next_kbnode (keyblock, PKT_USER_ID);
|
||||
|
||||
if (opt.verbose)
|
||||
{
|
||||
log_info ("sec %4u%c/%s %s ",
|
||||
nbits_from_sk (sk),
|
||||
pubkey_letter (sk->pubkey_algo),
|
||||
keystr_from_sk (sk), datestr_from_sk (sk));
|
||||
nbits_from_pk (pk),
|
||||
pubkey_letter (pk->pubkey_algo),
|
||||
keystr_from_pk (pk), datestr_from_pk (pk));
|
||||
if (uidnode)
|
||||
print_utf8_buffer (log_get_stream (), uidnode->pkt->pkt.user_id->name,
|
||||
uidnode->pkt->pkt.user_id->len);
|
||||
@ -1423,16 +1379,24 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* A quick check to not import keys with an invalid protection
|
||||
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"
|
||||
" - skipped\n"),keystr_from_sk(sk),sk->protect.algo);
|
||||
" - skipped\n"), keystr_from_pk (pk), ski->algo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1447,9 +1411,9 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
|
||||
}
|
||||
#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. */
|
||||
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);
|
||||
if (!pub_keyblock)
|
||||
log_error ("key %s: failed to create public key from secret key\n",
|
||||
keystr_from_sk (sk));
|
||||
keystr_from_pk (pk));
|
||||
else
|
||||
{
|
||||
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);
|
||||
if (!node)
|
||||
log_error ("key %s: failed to re-lookup public key\n",
|
||||
keystr_from_sk (sk));
|
||||
keystr_from_pk (pk));
|
||||
else
|
||||
{
|
||||
if (!transfer_secret_keys (ctrl, stats, keyblock))
|
||||
{
|
||||
if (!opt.quiet)
|
||||
log_info (_("key %s: secret key imported\n"),
|
||||
keystr_from_sk (sk));
|
||||
keystr_from_pk (pk));
|
||||
if (is_status_enabled ())
|
||||
print_import_ok (NULL, sk, 1|16);
|
||||
print_import_ok (pk, 1|16);
|
||||
check_prefs (node);
|
||||
}
|
||||
release_kbnode (node);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (have_secret_key_with_kid (keyid))
|
||||
else
|
||||
{
|
||||
/* We don't want to merge the secret keys. */
|
||||
log_error( _("key %s: secret key part already available\n"),
|
||||
keystr_from_sk(sk));
|
||||
log_error (_("key %s: secret key part already available\n"),
|
||||
keystr_from_pk (pk));
|
||||
if (is_status_enabled ())
|
||||
print_import_ok (NULL, sk, 16);
|
||||
print_import_ok (pk, 16);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -2072,12 +2036,12 @@ collapse_uids( KBNODE *keyblock )
|
||||
{
|
||||
const char *key="???";
|
||||
|
||||
if( (uid1=find_kbnode( *keyblock, PKT_PUBLIC_KEY )) )
|
||||
key=keystr_from_pk(uid1->pkt->pkt.public_key);
|
||||
else if( (uid1 = find_kbnode( *keyblock, PKT_SECRET_KEY )) )
|
||||
key=keystr_from_sk(uid1->pkt->pkt.secret_key);
|
||||
if ((uid1 = find_kbnode (*keyblock, PKT_PUBLIC_KEY)) )
|
||||
key = keystr_from_pk (uid1->pkt->pkt.public_key);
|
||||
else if ((uid1 = find_kbnode( *keyblock, 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;
|
||||
@ -2308,8 +2272,8 @@ merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
|
||||
/* do we have this in the original keyblock? */
|
||||
for(onode=keyblock_orig->next; onode; onode=onode->next )
|
||||
if( onode->pkt->pkttype == PKT_SECRET_SUBKEY
|
||||
&& !cmp_secret_keys( onode->pkt->pkt.secret_key,
|
||||
node->pkt->pkt.secret_key ) )
|
||||
&& !cmp_public_keys (onode->pkt->pkt.public_key,
|
||||
node->pkt->pkt.public_key) )
|
||||
break;
|
||||
if( !onode ) { /* this is a new subkey: append */
|
||||
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) ) {
|
||||
/* find the subkey in the imported keyblock */
|
||||
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,
|
||||
node->pkt->pkt.public_key ) )
|
||||
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 */
|
||||
rc = merge_keysigs( onode, node, n_sigs, fname, keyid );
|
||||
@ -2497,8 +2458,9 @@ merge_keysigs (KBNODE dst, KBNODE src, int *n_sigs,
|
||||
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.
|
||||
*/
|
||||
static int
|
||||
@ -2530,233 +2492,3 @@ append_key (KBNODE keyblock, KBNODE node, int *n_sigs,
|
||||
|
||||
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;
|
||||
}
|
||||
|
17
g10/keydb.h
17
g10/keydb.h
@ -195,7 +195,7 @@ void set_next_passphrase( const char *s );
|
||||
char *get_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 --*/
|
||||
@ -241,8 +241,8 @@ void getkey_end (getkey_ctx_t ctx);
|
||||
int have_any_secret_key (ctrl_t ctrl, kbnode_t keyblock);
|
||||
|
||||
|
||||
int enum_secret_keys( void **context, PKT_secret_key *sk,
|
||||
int with_subkeys, int with_spm );
|
||||
//int enum_secret_keys( void **context, PKT_secret_key *sk,
|
||||
// int with_subkeys, int with_spm );
|
||||
void merge_keys_and_selfsig( KBNODE keyblock );
|
||||
char*get_user_id_string( 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_with_sub (PKT_public_key *main_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);
|
||||
u32 keyid_from_sk( PKT_secret_key *sk, u32 *keyid );
|
||||
u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid );
|
||||
u32 keyid_from_sig( PKT_signature *sig, u32 *keyid );
|
||||
u32 keyid_from_fingerprint(const byte *fprint, size_t fprint_len, u32 *keyid);
|
||||
byte *namehash_from_uid(PKT_user_id *uid);
|
||||
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_sk( PKT_secret_key *sk );
|
||||
const char *datestr_from_sig( PKT_signature *sig );
|
||||
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 *revokestr_from_pk( PKT_public_key *pk );
|
||||
const char *usagestr_from_pk( PKT_public_key *pk );
|
||||
const char *colon_strtime (u32 t);
|
||||
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_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 );
|
||||
char *serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
|
||||
PKT_secret_key *sk);
|
||||
gpg_error_t keygrip_from_pk (PKT_public_key *pk, unsigned char *array);
|
||||
gpg_error_t hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip);
|
||||
|
||||
|
@ -2924,7 +2924,9 @@ show_key_with_all_names (KBNODE keyblock, int only_marked, int with_revoker,
|
||||
|
||||
keyid_from_pk (pk, NULL);
|
||||
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) ? '*' : ' ',
|
||||
nbits_from_pk (pk),
|
||||
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 ("\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)
|
||||
{
|
||||
@ -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);
|
||||
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);
|
||||
@ -3035,14 +3031,17 @@ show_basic_key_info (KBNODE keyblock)
|
||||
/* The primary key */
|
||||
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;
|
||||
|
||||
/* Note, we use the same format string as in other show
|
||||
functions to make the translation job easier. */
|
||||
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),
|
||||
pubkey_letter (pk->pubkey_algo), keystr_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);
|
||||
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. */
|
||||
|
442
g10/keyid.c
442
g10/keyid.c
@ -38,24 +38,27 @@
|
||||
#define KEYID_STR_SIZE 19
|
||||
|
||||
|
||||
/* Return a letter describing the public key algorithms. */
|
||||
int
|
||||
pubkey_letter( int algo )
|
||||
{
|
||||
switch( algo ) {
|
||||
case PUBKEY_ALGO_RSA: return 'R' ;
|
||||
case PUBKEY_ALGO_RSA_E: return 'r' ;
|
||||
case PUBKEY_ALGO_RSA_S: return 's' ;
|
||||
case PUBKEY_ALGO_ELGAMAL_E: return 'g';
|
||||
case PUBKEY_ALGO_ELGAMAL: return 'G' ;
|
||||
case PUBKEY_ALGO_DSA: return 'D' ;
|
||||
default: return '?';
|
||||
switch (algo)
|
||||
{
|
||||
case PUBKEY_ALGO_RSA: return 'R' ;
|
||||
case PUBKEY_ALGO_RSA_E: return 'r' ;
|
||||
case PUBKEY_ALGO_RSA_S: return 's' ;
|
||||
case PUBKEY_ALGO_ELGAMAL_E: return 'g';
|
||||
case PUBKEY_ALGO_ELGAMAL: return 'G' ;
|
||||
case PUBKEY_ALGO_DSA: return 'D' ;
|
||||
default: return '?';
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
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 nn[PUBKEY_MAX_NPKEY];
|
||||
@ -77,17 +80,19 @@ hash_public_key( gcry_md_hd_t md, PKT_public_key *pk )
|
||||
n+=nn[0];
|
||||
}
|
||||
else
|
||||
for(i=0; i < npkey; i++ )
|
||||
{
|
||||
if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i]))
|
||||
BUG ();
|
||||
pp[i] = xmalloc (nbytes);
|
||||
if (gcry_mpi_print (GCRYMPI_FMT_PGP, pp[i], nbytes,
|
||||
&nbytes, pk->pkey[i]))
|
||||
BUG ();
|
||||
nn[i] = nbytes;
|
||||
n += nn[i];
|
||||
}
|
||||
{
|
||||
for(i=0; i < npkey; i++ )
|
||||
{
|
||||
if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i]))
|
||||
BUG ();
|
||||
pp[i] = xmalloc (nbytes);
|
||||
if (gcry_mpi_print (GCRYMPI_FMT_PGP, pp[i], nbytes,
|
||||
&nbytes, pk->pkey[i]))
|
||||
BUG ();
|
||||
nn[i] = nbytes;
|
||||
n += nn[i];
|
||||
}
|
||||
}
|
||||
|
||||
gcry_md_putc ( md, 0x99 ); /* ctb */
|
||||
/* 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
|
||||
do_fingerprint_md( PKT_public_key *pk )
|
||||
{
|
||||
@ -138,27 +144,9 @@ do_fingerprint_md( PKT_public_key *pk )
|
||||
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
|
||||
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 *
|
||||
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
|
||||
* if this is not NULL. Return the 32 low bits of the keyid.
|
||||
*/
|
||||
u32
|
||||
keyid_from_pk( PKT_public_key *pk, u32 *keyid )
|
||||
keyid_from_pk (PKT_public_key *pk, u32 *keyid)
|
||||
{
|
||||
u32 lowbits;
|
||||
u32 dummy_keyid[2];
|
||||
|
||||
if( !keyid )
|
||||
if (!keyid)
|
||||
keyid = dummy_keyid;
|
||||
|
||||
if( pk->keyid[0] || pk->keyid[1] )
|
||||
@ -442,61 +358,66 @@ keyid_from_pk( PKT_public_key *pk, u32 *keyid )
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
/*
|
||||
* Get the keyid from the fingerprint. This function is simple for most
|
||||
* keys, but has to do a keylookup for old stayle keys.
|
||||
*/
|
||||
u32
|
||||
keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
|
||||
{
|
||||
u32 dummy_keyid[2];
|
||||
u32 dummy_keyid[2];
|
||||
|
||||
if( !keyid )
|
||||
keyid = dummy_keyid;
|
||||
if( !keyid )
|
||||
keyid = dummy_keyid;
|
||||
|
||||
if( fprint_len != 20 ) {
|
||||
/* This is special as we have to lookup the key first */
|
||||
PKT_public_key pk;
|
||||
int rc;
|
||||
if (fprint_len != 20)
|
||||
{
|
||||
/* This is special as we have to lookup the key first. */
|
||||
PKT_public_key pk;
|
||||
int rc;
|
||||
|
||||
memset( &pk, 0, sizeof pk );
|
||||
rc = get_pubkey_byfprint( &pk, fprint, fprint_len );
|
||||
if( rc ) {
|
||||
log_error("Oops: keyid_from_fingerprint: no pubkey\n");
|
||||
keyid[0] = 0;
|
||||
keyid[1] = 0;
|
||||
}
|
||||
else
|
||||
keyid_from_pk( &pk, keyid );
|
||||
memset (&pk, 0, sizeof pk);
|
||||
rc = get_pubkey_byfprint (&pk, fprint, fprint_len);
|
||||
if( rc )
|
||||
{
|
||||
log_error("Oops: keyid_from_fingerprint: no pubkey\n");
|
||||
keyid[0] = 0;
|
||||
keyid[1] = 0;
|
||||
}
|
||||
else
|
||||
keyid_from_pk (&pk, keyid);
|
||||
}
|
||||
else {
|
||||
const byte *dp = fprint;
|
||||
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] ;
|
||||
else
|
||||
{
|
||||
const byte *dp = fprint;
|
||||
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] ;
|
||||
}
|
||||
|
||||
return keyid[1];
|
||||
return keyid[1];
|
||||
}
|
||||
|
||||
|
||||
u32
|
||||
keyid_from_sig( PKT_signature *sig, u32 *keyid )
|
||||
keyid_from_sig (PKT_signature *sig, u32 *keyid)
|
||||
{
|
||||
if( keyid ) {
|
||||
keyid[0] = sig->keyid[0];
|
||||
keyid[1] = sig->keyid[1];
|
||||
if( keyid )
|
||||
{
|
||||
keyid[0] = sig->keyid[0];
|
||||
keyid[1] = sig->keyid[1];
|
||||
}
|
||||
return sig->keyid[1];
|
||||
return sig->keyid[1];
|
||||
}
|
||||
|
||||
|
||||
byte *
|
||||
namehash_from_uid(PKT_user_id *uid)
|
||||
namehash_from_uid (PKT_user_id *uid)
|
||||
{
|
||||
if (!uid->namehash)
|
||||
{
|
||||
uid->namehash = xmalloc (20);
|
||||
|
||||
if(uid->attrib_data)
|
||||
if (uid->attrib_data)
|
||||
rmd160_hash_buffer (uid->namehash, uid->attrib_data, uid->attrib_len);
|
||||
else
|
||||
rmd160_hash_buffer (uid->namehash, uid->name, uid->len);
|
||||
@ -505,117 +426,95 @@ namehash_from_uid(PKT_user_id *uid)
|
||||
return uid->namehash;
|
||||
}
|
||||
|
||||
/****************
|
||||
* return the number of bits used in the pk
|
||||
|
||||
/*
|
||||
* Return the number of bits used in PK.
|
||||
*/
|
||||
unsigned
|
||||
nbits_from_pk( PKT_public_key *pk )
|
||||
unsigned int
|
||||
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 *
|
||||
mk_datestr (char *buffer, time_t atime)
|
||||
{
|
||||
struct tm *tp;
|
||||
struct tm *tp;
|
||||
|
||||
if ( atime < 0 ) /* 32 bit time_t and after 2038-01-19 */
|
||||
strcpy (buffer, "????" "-??" "-??"); /* mark this as invalid */
|
||||
else {
|
||||
tp = gmtime (&atime);
|
||||
sprintf (buffer,"%04d-%02d-%02d",
|
||||
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
if ( atime < 0 ) /* 32 bit time_t and after 2038-01-19 */
|
||||
strcpy (buffer, "????" "-??" "-??"); /* mark this as invalid */
|
||||
else
|
||||
{
|
||||
tp = gmtime (&atime);
|
||||
sprintf (buffer,"%04d-%02d-%02d",
|
||||
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
}
|
||||
return buffer;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/****************
|
||||
|
||||
/*
|
||||
* return a string with the creation date of the pk
|
||||
* Note: this is alloced in a static buffer.
|
||||
* Format is: yyyy-mm-dd
|
||||
*/
|
||||
const char *
|
||||
datestr_from_pk( PKT_public_key *pk )
|
||||
datestr_from_pk (PKT_public_key *pk)
|
||||
{
|
||||
static char buffer[11+5];
|
||||
time_t atime = pk->timestamp;
|
||||
static char buffer[11+5];
|
||||
time_t atime = pk->timestamp;
|
||||
|
||||
return mk_datestr (buffer, atime);
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
datestr_from_sk( PKT_secret_key *sk )
|
||||
datestr_from_sig (PKT_signature *sig )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
time_t atime = sk->timestamp;
|
||||
static char buffer[11+5];
|
||||
time_t atime = sig->timestamp;
|
||||
|
||||
return mk_datestr (buffer, atime);
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
datestr_from_sig( PKT_signature *sig )
|
||||
expirestr_from_pk (PKT_public_key *pk)
|
||||
{
|
||||
static char buffer[11+5];
|
||||
time_t atime = sig->timestamp;
|
||||
static char buffer[11+5];
|
||||
time_t atime;
|
||||
|
||||
return mk_datestr (buffer, atime);
|
||||
if (!pk->expiredate)
|
||||
return _("never ");
|
||||
atime = pk->expiredate;
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
expirestr_from_pk( PKT_public_key *pk )
|
||||
expirestr_from_sig (PKT_signature *sig)
|
||||
{
|
||||
static char buffer[11+5];
|
||||
time_t atime;
|
||||
static char buffer[11+5];
|
||||
time_t atime;
|
||||
|
||||
if( !pk->expiredate )
|
||||
return _("never ");
|
||||
atime = pk->expiredate;
|
||||
return mk_datestr (buffer, atime);
|
||||
if (!sig->expiredate)
|
||||
return _("never ");
|
||||
atime=sig->expiredate;
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
const char *
|
||||
expirestr_from_sk( PKT_secret_key *sk )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
time_t atime;
|
||||
|
||||
if( !sk->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 ");
|
||||
atime=sig->expiredate;
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
const char *
|
||||
revokestr_from_pk( PKT_public_key *pk )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
time_t atime;
|
||||
static char buffer[11+5];
|
||||
time_t atime;
|
||||
|
||||
if(!pk->revoked.date)
|
||||
return _("never ");
|
||||
atime=pk->revoked.date;
|
||||
return mk_datestr (buffer, atime);
|
||||
if(!pk->revoked.date)
|
||||
return _("never ");
|
||||
atime=pk->revoked.date;
|
||||
return mk_datestr (buffer, atime);
|
||||
}
|
||||
|
||||
|
||||
@ -666,14 +565,6 @@ colon_datestr_from_pk (PKT_public_key *pk)
|
||||
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 *
|
||||
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
|
||||
* The length of the array is returned in ret_len. Caller must free
|
||||
* the array or provide an array of length MAX_FINGERPRINT_LEN.
|
||||
*/
|
||||
|
||||
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;
|
||||
const byte *dp;
|
||||
@ -771,105 +661,7 @@ fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
146
g10/keylist.c
146
g10/keylist.c
@ -44,7 +44,7 @@
|
||||
static void list_all (int);
|
||||
static void list_one (strlist_t names, int secret);
|
||||
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
|
||||
{
|
||||
@ -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
|
||||
number information. */
|
||||
void
|
||||
print_card_key_info (estream_t fp, KBNODE keyblock)
|
||||
print_card_key_info (estream_t fp, kbnode_t keyblock)
|
||||
{
|
||||
KBNODE node;
|
||||
int i;
|
||||
/* KBNODE node; */
|
||||
/* int i; */
|
||||
|
||||
for (node = keyblock; node; node = node->next)
|
||||
{
|
||||
if (node->pkt->pkttype == PKT_SECRET_KEY
|
||||
|| (node->pkt->pkttype == PKT_SECRET_SUBKEY))
|
||||
{
|
||||
PKT_secret_key *sk = node->pkt->pkt.secret_key;
|
||||
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)) */
|
||||
/* { */
|
||||
/* PKT_public_key *pk = node->pkt->pkt.public_key; */
|
||||
|
||||
tty_fprintf (fp, "%s%c %4u%c/%s ",
|
||||
node->pkt->pkttype == PKT_SECRET_KEY ? "sec" : "ssb",
|
||||
(sk->protect.s2k.mode == 1001) ? '#' :
|
||||
(sk->protect.s2k.mode == 1002) ? '>' : ' ',
|
||||
nbits_from_sk (sk),
|
||||
pubkey_letter (sk->pubkey_algo), keystr_from_sk (sk));
|
||||
tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk));
|
||||
tty_fprintf (fp, " ");
|
||||
tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk));
|
||||
if (sk->is_protected && sk->protect.s2k.mode == 1002)
|
||||
{
|
||||
tty_fprintf (fp, "\n ");
|
||||
tty_fprintf (fp, _("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_fprintf (fp, " ");
|
||||
tty_fprintf (fp, "%02X", sk->protect.iv[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something is wrong: Print all. */
|
||||
for (i = 0; i < sk->protect.ivlen; i++)
|
||||
tty_fprintf (fp, "%02X", sk->protect.iv[i]);
|
||||
}
|
||||
}
|
||||
tty_fprintf (fp, "\n");
|
||||
}
|
||||
}
|
||||
/* tty_fprintf (fp, "%s%c %4u%c/%s ", */
|
||||
/* node->pkt->pkttype == PKT_SECRET_KEY ? "sec" : "ssb", */
|
||||
/* (sk->protect.s2k.mode == 1001) ? '#' : */
|
||||
/* (sk->protect.s2k.mode == 1002) ? '>' : ' ', */
|
||||
/* nbits_from_sk (sk), */
|
||||
/* pubkey_letter (sk->pubkey_algo), keystr_from_sk (sk)); */
|
||||
/* tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk)); */
|
||||
/* tty_fprintf (fp, " "); */
|
||||
/* tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk)); */
|
||||
/* if (sk->is_protected && sk->protect.s2k.mode == 1002) */
|
||||
/* { */
|
||||
/* tty_fprintf (fp, "\n "); */
|
||||
/* tty_fprintf (fp, _("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_fprintf (fp, " "); */
|
||||
/* tty_fprintf (fp, "%02X", sk->protect.iv[i]); */
|
||||
/* } */
|
||||
/* } */
|
||||
/* else */
|
||||
/* { */
|
||||
/* /\* Something is wrong: Print all. *\/ */
|
||||
/* for (i = 0; i < sk->protect.ivlen; i++) */
|
||||
/* tty_fprintf (fp, "%02X", sk->protect.iv[i]); */
|
||||
/* } */
|
||||
/* } */
|
||||
/* 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. */
|
||||
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)
|
||||
return;
|
||||
if (!sk->is_protected || sk->protect.s2k.mode != 1002)
|
||||
return; /* Not a card. */
|
||||
if (opt.with_colons)
|
||||
return; /* Handled elsewhere. */
|
||||
/* if (!sk) */
|
||||
/* return; */
|
||||
/* if (!sk->is_protected || sk->protect.s2k.mode != 1002) */
|
||||
/* return; /\* Not a card. *\/ */
|
||||
/* if (opt.with_colons) */
|
||||
/* return; /\* Handled elsewhere. *\/ */
|
||||
|
||||
es_fputs (_(" Card serial no. ="), es_stdout);
|
||||
es_putc (' ', es_stdout);
|
||||
if (sk->protect.ivlen == 16
|
||||
&& !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6))
|
||||
{
|
||||
/* This is an OpenPGP card. Just print the relevant part. */
|
||||
for (i = 8; i < 14; i++)
|
||||
{
|
||||
if (i == 10)
|
||||
es_putc (' ', es_stdout);
|
||||
es_fprintf (es_stdout, "%02X", sk->protect.iv[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something is wrong: Print all. */
|
||||
for (i = 0; i < sk->protect.ivlen; i++)
|
||||
es_fprintf (es_stdout, "%02X", sk->protect.iv[i]);
|
||||
}
|
||||
es_putc ('\n', es_stdout);
|
||||
/* es_fputs (_(" Card serial no. ="), es_stdout); */
|
||||
/* es_putc (' ', es_stdout); */
|
||||
/* if (sk->protect.ivlen == 16 */
|
||||
/* && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) */
|
||||
/* { */
|
||||
/* /\* This is an OpenPGP card. Just print the relevant part. *\/ */
|
||||
/* for (i = 8; i < 14; i++) */
|
||||
/* { */
|
||||
/* if (i == 10) */
|
||||
/* es_putc (' ', es_stdout); */
|
||||
/* es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
|
||||
/* } */
|
||||
/* } */
|
||||
/* else */
|
||||
/* { */
|
||||
/* /\* Something is wrong: Print all. *\/ */
|
||||
/* for (i = 0; i < sk->protect.ivlen; i++) */
|
||||
/* es_fprintf (es_stdout, "%02X", sk->protect.iv[i]); */
|
||||
/* } */
|
||||
/* es_putc ('\n', es_stdout); */
|
||||
}
|
||||
|
||||
|
||||
|
@ -899,7 +899,6 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
|
||||
int use_offtbl;
|
||||
PKT_user_id *uid = NULL;
|
||||
PKT_public_key *pk = NULL;
|
||||
PKT_secret_key *sk = NULL;
|
||||
u32 aki[2];
|
||||
|
||||
/* figure out what information we need */
|
||||
@ -1017,10 +1016,11 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
|
||||
}
|
||||
|
||||
pk = NULL;
|
||||
sk = NULL;
|
||||
uid = NULL;
|
||||
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_no;
|
||||
@ -1041,21 +1041,6 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
|
||||
uid = pkt.pkt.user_id;
|
||||
++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++)
|
||||
{
|
||||
@ -1076,29 +1061,29 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
|
||||
break;
|
||||
|
||||
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;
|
||||
break;
|
||||
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])
|
||||
goto found;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_FPR20:
|
||||
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;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_FIRST:
|
||||
if (pk||sk)
|
||||
if (pk)
|
||||
goto found;
|
||||
break;
|
||||
case KEYDB_SEARCH_MODE_NEXT:
|
||||
if (pk||sk)
|
||||
if (pk)
|
||||
goto found;
|
||||
break;
|
||||
default:
|
||||
@ -1128,7 +1113,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
|
||||
{
|
||||
hd->found.offset = main_offset;
|
||||
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;
|
||||
}
|
||||
else if (rc == -1)
|
||||
|
@ -277,10 +277,6 @@ void import_print_stats (void *hd);
|
||||
|
||||
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 --*/
|
||||
int parse_export_options(char *str,unsigned int *options,int noisy);
|
||||
|
@ -58,7 +58,6 @@ struct mainproc_context
|
||||
{
|
||||
struct mainproc_context *anchor; /* May be useful in the future. */
|
||||
PKT_public_key *last_pubkey;
|
||||
PKT_secret_key *last_seckey;
|
||||
PKT_user_id *last_user_id;
|
||||
md_filter_context_t mfx;
|
||||
int sigs_only; /* Process only signatures and reject all other stuff. */
|
||||
@ -1118,15 +1117,13 @@ list_node( CTX c, KBNODE node )
|
||||
u32 keyid[2];
|
||||
|
||||
if( c->list->pkt->pkttype == PKT_PUBLIC_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 );
|
||||
else
|
||||
keyid_from_sk( c->list->pkt->pkt.secret_key, keyid );
|
||||
|| c->list->pkt->pkttype == PKT_SECRET_KEY )
|
||||
{
|
||||
keyid_from_pk (c->list->pkt->pkt.public_key, keyid);
|
||||
|
||||
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
|
||||
is_selfsig = 1;
|
||||
}
|
||||
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
|
||||
is_selfsig = 1;
|
||||
}
|
||||
}
|
||||
if( opt.with_colons ) {
|
||||
putchar(':');
|
||||
|
87
g10/packet.h
87
g10/packet.h
@ -53,11 +53,12 @@ typedef struct {
|
||||
byte value;
|
||||
} prefitem_t;
|
||||
|
||||
typedef struct {
|
||||
int mode;
|
||||
byte hash_algo;
|
||||
byte salt[8];
|
||||
u32 count;
|
||||
typedef struct
|
||||
{
|
||||
int mode; /* Must be an integer due to the GNU modes 1001 et al. */
|
||||
byte hash_algo;
|
||||
byte salt[8];
|
||||
u32 count;
|
||||
} STRING2KEY;
|
||||
|
||||
typedef struct {
|
||||
@ -204,11 +205,35 @@ struct revoke_info
|
||||
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
|
||||
* has the same elements as the public key at the begin of the array, so
|
||||
* that npkey < nskey and it is possible to compare the secret and
|
||||
* public keys by comparing the first npkey elements of pkey againts skey.
|
||||
* We assume that secret keys have the same number of parameters as
|
||||
* the public key and that the public parameters are the first items
|
||||
* in the PKEY array. Thus NPKEY is always less than NSKEY and it is
|
||||
* 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 {
|
||||
u32 timestamp; /* key made */
|
||||
@ -243,44 +268,16 @@ typedef struct {
|
||||
byte trust_depth;
|
||||
byte trust_value;
|
||||
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;
|
||||
|
||||
/* Evaluates as true if the pk is disabled, and false if it isn't. If
|
||||
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))))
|
||||
|
||||
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 {
|
||||
int len; /* length of data */
|
||||
@ -339,7 +336,7 @@ struct packet_struct {
|
||||
PKT_onepass_sig *onepass_sig; /* PKT_ONEPASS_SIG */
|
||||
PKT_signature *signature; /* PKT_SIGNATURE */
|
||||
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_user_id *user_id; /* PKT_USER_ID */
|
||||
PKT_compressed *compressed; /* PKT_COMPRESSED */
|
||||
@ -452,22 +449,16 @@ void free_seckey_enc( PKT_signature *enc );
|
||||
int digest_algo_from_sig( PKT_signature *sig );
|
||||
void release_public_key_parts( PKT_public_key *pk );
|
||||
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_user_id( PKT_user_id *uid );
|
||||
void free_comment( PKT_comment *rem );
|
||||
void free_packet( PACKET *pkt );
|
||||
prefitem_t *copy_prefs (const prefitem_t *prefs);
|
||||
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_user_id *scopy_user_id (PKT_user_id *sd );
|
||||
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_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk );
|
||||
int cmp_user_ids( PKT_user_id *a, PKT_user_id *b );
|
||||
|
||||
|
||||
|
@ -565,12 +565,9 @@ parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
|
||||
{
|
||||
case PKT_PUBLIC_KEY:
|
||||
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_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);
|
||||
break;
|
||||
case PKT_SYMKEY_ENC:
|
||||
@ -627,6 +624,7 @@ parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
|
||||
}
|
||||
|
||||
leave:
|
||||
/* FIXME: Do we leak in case of an error? */
|
||||
if (!rc && iobuf_error (inp))
|
||||
rc = G10ERR_INV_KEYRING;
|
||||
return rc;
|
||||
@ -1815,6 +1813,7 @@ static int
|
||||
parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
byte * hdr, int hdrlen, PACKET * pkt)
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
int i, version, algorithm;
|
||||
unsigned n;
|
||||
unsigned long timestamp, expiredate, max_expiredate;
|
||||
@ -1822,9 +1821,12 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
int is_v4 = 0;
|
||||
int rc = 0;
|
||||
u32 keyid[2];
|
||||
PKT_public_key *pk;
|
||||
|
||||
(void) hdr;
|
||||
|
||||
pk = pkt->pkt.public_key; /* PK has been cleared. */
|
||||
|
||||
version = iobuf_get_noeof (inp);
|
||||
pktlen--;
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (pktlen < 11)
|
||||
{
|
||||
log_error ("packet(%d) too short\n", pkttype);
|
||||
rc = gpg_error (GPG_ERR_INV_PACKET);
|
||||
err = gpg_error (GPG_ERR_INV_PACKET);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
@ -1894,38 +1896,14 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
pkttype == PKT_SECRET_SUBKEY ? "secret sub" : "??",
|
||||
version, algorithm, timestamp, expiredate);
|
||||
|
||||
if (pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY)
|
||||
{
|
||||
PKT_secret_key *sk = pkt->pkt.secret_key;
|
||||
pk->timestamp = timestamp;
|
||||
pk->expiredate = expiredate;
|
||||
pk->max_expiredate = max_expiredate;
|
||||
pk->hdrbytes = hdrlen;
|
||||
pk->version = version;
|
||||
pk->is_primary = (pkttype == PKT_PUBLIC_KEY || pkttype == PKT_SECRET_KEY);
|
||||
pk->pubkey_algo = algorithm;
|
||||
|
||||
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->expiredate = expiredate;
|
||||
pk->max_expiredate = max_expiredate;
|
||||
pk->hdrbytes = hdrlen;
|
||||
pk->version = version;
|
||||
pk->is_primary = pkttype == PKT_PUBLIC_KEY;
|
||||
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);
|
||||
npkey = pubkey_get_npkey (algorithm);
|
||||
if (!npkey)
|
||||
@ -1936,62 +1914,77 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
}
|
||||
|
||||
|
||||
if (pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY)
|
||||
if (!npkey)
|
||||
{
|
||||
PKT_secret_key *sk = pkt->pkt.secret_key;
|
||||
byte temp[16];
|
||||
size_t snlen = 0;
|
||||
|
||||
if (!npkey)
|
||||
{
|
||||
sk->skey[0] = gcry_mpi_set_opaque (NULL, read_rest (inp, pktlen, 0),
|
||||
pktlen * 8);
|
||||
pktlen = 0;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Unknown algorithm - put data into an opaque MPI. */
|
||||
pk->pkey[0] = gcry_mpi_set_opaque (NULL,
|
||||
read_rest (inp, pktlen, 0),
|
||||
pktlen * 8);
|
||||
pktlen = 0;
|
||||
goto leave;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fill in public key parameters. */
|
||||
for (i = 0; i < npkey; i++)
|
||||
{
|
||||
n = pktlen;
|
||||
sk->skey[i] = mpi_read (inp, &n, 0);
|
||||
pk->pkey[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_fprintf (listfp, "\tpkey[%d]: ", i);
|
||||
mpi_print (listfp, pk->pkey[i], mpi_print_mode);
|
||||
es_putc ('\n', listfp);
|
||||
}
|
||||
if (!sk->skey[i])
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
if (!pk->pkey[i])
|
||||
err = gpg_error (GPG_ERR_INV_PACKET);
|
||||
}
|
||||
if (rc) /* One of the MPIs were bad. */
|
||||
if (err)
|
||||
goto leave;
|
||||
sk->protect.algo = iobuf_get_noeof (inp);
|
||||
}
|
||||
|
||||
if (list_mode)
|
||||
keyid_from_pk (pk, keyid);
|
||||
|
||||
if (pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY)
|
||||
{
|
||||
struct seckey_info *ski;
|
||||
byte temp[16];
|
||||
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--;
|
||||
sk->protect.sha1chk = 0;
|
||||
if (sk->protect.algo)
|
||||
if (ski->algo)
|
||||
{
|
||||
sk->is_protected = 1;
|
||||
sk->protect.s2k.count = 0;
|
||||
if (sk->protect.algo == 254 || sk->protect.algo == 255)
|
||||
ski->is_protected = 1;
|
||||
ski->s2k.count = 0;
|
||||
if (ski->algo == 254 || ski->algo == 255)
|
||||
{
|
||||
if (pktlen < 3)
|
||||
{
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
err = gpg_error (GPG_ERR_INV_PACKET);
|
||||
goto leave;
|
||||
}
|
||||
sk->protect.sha1chk = (sk->protect.algo == 254);
|
||||
sk->protect.algo = iobuf_get_noeof (inp);
|
||||
ski->sha1chk = (ski->algo == 254);
|
||||
ski->algo = iobuf_get_noeof (inp);
|
||||
pktlen--;
|
||||
/* Note that a sk->protect.algo > 110 is illegal, but
|
||||
I'm not erroring on it here as otherwise there would
|
||||
be no way to delete such a key. */
|
||||
sk->protect.s2k.mode = iobuf_get_noeof (inp);
|
||||
/* Note that a ski->algo > 110 is illegal, but I'm not
|
||||
erroring on it here as otherwise there would be no
|
||||
way to delete such a key. */
|
||||
ski->s2k.mode = iobuf_get_noeof (inp);
|
||||
pktlen--;
|
||||
sk->protect.s2k.hash_algo = iobuf_get_noeof (inp);
|
||||
ski->s2k.hash_algo = iobuf_get_noeof (inp);
|
||||
pktlen--;
|
||||
/* check for the special GNU extension */
|
||||
if (is_v4 && sk->protect.s2k.mode == 101)
|
||||
/* Check for the special GNU extension. */
|
||||
if (is_v4 && ski->s2k.mode == 101)
|
||||
{
|
||||
for (i = 0; i < 4 && pktlen; i++, pktlen--)
|
||||
temp[i] = iobuf_get_noeof (inp);
|
||||
@ -1999,26 +1992,30 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
{
|
||||
if (list_mode)
|
||||
es_fprintf (listfp, "\tunknown S2K %d\n",
|
||||
sk->protect.s2k.mode);
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
ski->s2k.mode);
|
||||
err = gpg_error (GPG_ERR_INV_PACKET);
|
||||
goto leave;
|
||||
}
|
||||
/* Here we know that it is a GNU extension. What
|
||||
* follows is the GNU protection mode: All values
|
||||
* have special meanings and they are mapped to MODE
|
||||
* 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 3:
|
||||
for (i = 0; i < 8 && pktlen; i++, pktlen--)
|
||||
temp[i] = iobuf_get_noeof (inp);
|
||||
memcpy (sk->protect.s2k.salt, temp, 8);
|
||||
memcpy (ski->s2k.salt, temp, 8);
|
||||
break;
|
||||
}
|
||||
switch (sk->protect.s2k.mode)
|
||||
|
||||
/* Check the mode. */
|
||||
switch (ski->s2k.mode)
|
||||
{
|
||||
case 0:
|
||||
if (list_mode)
|
||||
@ -2043,202 +2040,163 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
default:
|
||||
if (list_mode)
|
||||
es_fprintf (listfp, "\tunknown %sS2K %d\n",
|
||||
sk->protect.s2k.mode < 1000 ? "" : "GNU ",
|
||||
sk->protect.s2k.mode);
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
ski->s2k.mode < 1000 ? "" : "GNU ",
|
||||
ski->s2k.mode);
|
||||
err = gpg_error (GPG_ERR_INV_PACKET);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Print some info. */
|
||||
if (list_mode)
|
||||
{
|
||||
es_fprintf (listfp, ", algo: %d,%s hash: %d",
|
||||
sk->protect.algo,
|
||||
sk->protect.sha1chk ? " SHA1 protection,"
|
||||
: " simple checksum,", sk->protect.s2k.hash_algo);
|
||||
if (sk->protect.s2k.mode == 1 || sk->protect.s2k.mode == 3)
|
||||
ski->algo,
|
||||
ski->sha1chk ? " SHA1 protection,"
|
||||
: " simple checksum,", ski->s2k.hash_algo);
|
||||
if (ski->s2k.mode == 1 || ski->s2k.mode == 3)
|
||||
{
|
||||
es_fprintf (listfp, ", salt: ");
|
||||
es_write_hexstring (listfp, sk->protect.s2k.salt, 8,
|
||||
0, NULL);
|
||||
es_write_hexstring (listfp, ski->s2k.salt, 8, 0, NULL);
|
||||
}
|
||||
es_putc ('\n', listfp);
|
||||
}
|
||||
|
||||
if (sk->protect.s2k.mode == 3)
|
||||
/* Read remaining protection parameters. */
|
||||
if (ski->s2k.mode == 3)
|
||||
{
|
||||
if (pktlen < 1)
|
||||
{
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
err = gpg_error (GPG_ERR_INV_PACKET);
|
||||
goto leave;
|
||||
}
|
||||
sk->protect.s2k.count = iobuf_get (inp);
|
||||
ski->s2k.count = iobuf_get (inp);
|
||||
pktlen--;
|
||||
if (list_mode)
|
||||
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. */
|
||||
if (pktlen < 1)
|
||||
{
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
err = gpg_error (GPG_ERR_INV_PACKET);
|
||||
goto leave;
|
||||
}
|
||||
snlen = iobuf_get (inp);
|
||||
pktlen--;
|
||||
if (pktlen < snlen || snlen == -1)
|
||||
{
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
err = gpg_error (GPG_ERR_INV_PACKET);
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Old version; no S2K, so we set mode to 0, hash MD5. */
|
||||
{
|
||||
/* Note that a sk->protect.algo > 110 is illegal, but
|
||||
I'm not erroring on it here as otherwise there would
|
||||
be no way to delete such a key. */
|
||||
sk->protect.s2k.mode = 0;
|
||||
sk->protect.s2k.hash_algo = DIGEST_ALGO_MD5;
|
||||
/* Note that a ski->algo > 110 is illegal, but I'm not
|
||||
erroring on it here as otherwise there would be no
|
||||
way to delete such a key. */
|
||||
ski->s2k.mode = 0;
|
||||
ski->s2k.hash_algo = DIGEST_ALGO_MD5;
|
||||
if (list_mode)
|
||||
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
|
||||
* of the IV here in cases we are not aware of the algorithm.
|
||||
* 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.
|
||||
* NOTE: if you change the ivlen above 16, don't forget to
|
||||
* enlarge temp. */
|
||||
sk->protect.ivlen = openpgp_cipher_blocklen (sk->protect.algo);
|
||||
assert (sk->protect.ivlen <= sizeof (temp));
|
||||
ski->ivlen = openpgp_cipher_blocklen (ski->algo);
|
||||
assert (ski->ivlen <= sizeof (temp));
|
||||
|
||||
if (sk->protect.s2k.mode == 1001)
|
||||
sk->protect.ivlen = 0;
|
||||
else if (sk->protect.s2k.mode == 1002)
|
||||
sk->protect.ivlen = snlen < 16 ? snlen : 16;
|
||||
if (ski->s2k.mode == 1001)
|
||||
ski->ivlen = 0;
|
||||
else if (ski->s2k.mode == 1002)
|
||||
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;
|
||||
}
|
||||
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);
|
||||
if (list_mode)
|
||||
{
|
||||
es_fprintf (listfp,
|
||||
sk->protect.s2k.mode == 1002 ? "\tserial-number: "
|
||||
: "\tprotect IV: ");
|
||||
for (i = 0; i < sk->protect.ivlen; i++)
|
||||
ski->s2k.mode == 1002 ? "\tserial-number: "
|
||||
: "\tprotect IV: ");
|
||||
for (i = 0; i < ski->ivlen; i++)
|
||||
es_fprintf (listfp, " %02x", temp[i]);
|
||||
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.
|
||||
* If the user is so careless, not to protect his secret key,
|
||||
* we can assume, that he operates an open system :=(.
|
||||
* 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. */
|
||||
sk->skey[npkey] = gcry_mpi_set_opaque (NULL,
|
||||
pk->pkey[npkey] = gcry_mpi_set_opaque (NULL,
|
||||
xstrdup ("dummydata"),
|
||||
10 * 8);
|
||||
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
|
||||
* up to the end of the packet into the first SKEY
|
||||
* element. */
|
||||
sk->skey[npkey] = gcry_mpi_set_opaque (NULL,
|
||||
pk->pkey[npkey] = gcry_mpi_set_opaque (NULL,
|
||||
read_rest (inp, pktlen, 0),
|
||||
pktlen * 8);
|
||||
pktlen = 0;
|
||||
if (list_mode)
|
||||
{
|
||||
es_fprintf (listfp, "\tencrypted stuff follows\n");
|
||||
}
|
||||
es_fprintf (listfp, "\tskey[%d]: [v4 protected]\n", npkey);
|
||||
}
|
||||
else /* The v3 method: The mpi length is not encrypted. */
|
||||
else
|
||||
{
|
||||
/* The v3 method: The mpi length is not encrypted. */
|
||||
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)
|
||||
es_fprintf (listfp, "\tskey[%d]: [encrypted]\n", i);
|
||||
es_fprintf (listfp, "\tskey[%d]: [v3 protected]\n", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = pktlen;
|
||||
sk->skey[i] = mpi_read (inp, &n, 0);
|
||||
pk->pkey[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);
|
||||
mpi_print (listfp, pk->pkey[i], mpi_print_mode);
|
||||
es_putc ('\n', listfp);
|
||||
}
|
||||
}
|
||||
|
||||
if (!sk->skey[i])
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
if (!pk->pkey[i])
|
||||
err = gpg_error (GPG_ERR_INV_PACKET);
|
||||
}
|
||||
if (rc)
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
sk->csum = read_16 (inp);
|
||||
ski->csum = read_16 (inp);
|
||||
pktlen -= 2;
|
||||
if (list_mode)
|
||||
{
|
||||
es_fprintf (listfp, "\tchecksum: %04hx\n", sk->csum);
|
||||
}
|
||||
es_fprintf (listfp, "\tchecksum: %04hx\n", ski->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;
|
||||
pk->pkey[i] = mpi_read (inp, &n, 0);
|
||||
pktlen -= n;
|
||||
if (list_mode)
|
||||
{
|
||||
es_fprintf (listfp, "\tpkey[%d]: ", i);
|
||||
mpi_print (listfp, pk->pkey[i], mpi_print_mode);
|
||||
es_putc ('\n', listfp);
|
||||
}
|
||||
if (!pk->pkey[i])
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
}
|
||||
if (rc)
|
||||
goto leave;
|
||||
if (list_mode)
|
||||
keyid_from_pk (pk, keyid);
|
||||
}
|
||||
|
||||
if (list_mode)
|
||||
|
@ -686,10 +686,10 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
|
||||
|
||||
|
||||
/* Return an allocated utf-8 string describing the key PK. IF ESCAPED
|
||||
is true spaces and control characters are percent or plus
|
||||
escaped. */
|
||||
is true spaces and control characters are percent or plus escaped.
|
||||
MODE 0 is for the common prompt, MODE 1 for the import prompt. */
|
||||
char *
|
||||
gpg_format_keydesc (PKT_public_key *pk, int escaped)
|
||||
gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped)
|
||||
{
|
||||
char *uid;
|
||||
size_t uidlen;
|
||||
@ -698,6 +698,7 @@ gpg_format_keydesc (PKT_public_key *pk, int escaped)
|
||||
char *orig_codeset;
|
||||
char *maink;
|
||||
char *desc;
|
||||
const char *prompt;
|
||||
|
||||
algo_name = gcry_pk_algo_name (pk->pubkey_algo);
|
||||
timestr = strtimestamp (pk->timestamp);
|
||||
@ -712,11 +713,26 @@ gpg_format_keydesc (PKT_public_key *pk, int escaped)
|
||||
else
|
||||
maink = NULL;
|
||||
|
||||
desc = xtryasprintf (_("Please enter the passphrase to unlock the"
|
||||
" secret key for the OpenPGP certificate:\n"
|
||||
switch (mode)
|
||||
{
|
||||
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"
|
||||
"%u-bit %s key, ID %s,\n"
|
||||
"created %s%s.\n"),
|
||||
prompt,
|
||||
(int)uidlen, uid,
|
||||
nbits_from_pk (pk), algo_name,
|
||||
keystr (pk->keyid), timestr,
|
||||
|
@ -196,7 +196,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
|
||||
goto leave;
|
||||
|
||||
/* Decrypt. */
|
||||
desc = gpg_format_keydesc (sk, 1);
|
||||
desc = gpg_format_keydesc (sk, 0, 1);
|
||||
err = agent_pkdecrypt (NULL, keygrip, desc, s_data, &frame, &nframe);
|
||||
xfree (desc);
|
||||
gcry_sexp_release (s_data);
|
||||
|
@ -314,7 +314,7 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
|
||||
char *desc;
|
||||
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,
|
||||
dp, gcry_md_get_algo_dlen (mdalgo), mdalgo,
|
||||
&s_sigval);
|
||||
|
Loading…
x
Reference in New Issue
Block a user