diff options
-rw-r--r-- | g10/ChangeLog | 50 | ||||
-rw-r--r-- | g10/build-packet.c | 257 | ||||
-rw-r--r-- | g10/card-util.c | 294 | ||||
-rw-r--r-- | g10/delkey.c | 38 | ||||
-rw-r--r-- | g10/export.c | 837 | ||||
-rw-r--r-- | g10/free-packet.c | 233 | ||||
-rw-r--r-- | g10/getkey.c | 2 | ||||
-rw-r--r-- | g10/import.c | 444 | ||||
-rw-r--r-- | g10/keydb.h | 17 | ||||
-rw-r--r-- | g10/keyedit.c | 94 | ||||
-rw-r--r-- | g10/keyid.c | 452 | ||||
-rw-r--r-- | g10/keylist.c | 154 | ||||
-rw-r--r-- | g10/keyring.c | 35 | ||||
-rw-r--r-- | g10/main.h | 4 | ||||
-rw-r--r-- | g10/mainproc.c | 17 | ||||
-rw-r--r-- | g10/packet.h | 87 | ||||
-rw-r--r-- | g10/parse-packet.c | 300 | ||||
-rw-r--r-- | g10/passphrase.c | 26 | ||||
-rw-r--r-- | g10/pubkey-enc.c | 2 | ||||
-rw-r--r-- | g10/sign.c | 2 |
20 files changed, 1353 insertions, 1992 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog index eede33667..70e471e12 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -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. diff --git a/g10/build-packet.c b/g10/build-packet.c index 37922d90c..354afece7 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -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,198 +239,162 @@ 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(); - - if ( !pk->version ) - iobuf_put( a, 3 ); - else - iobuf_put( a, pk->version ); - write_32(a, pk->timestamp ); - if ( pk->version < 4 ) - { - u16 ndays; - if ( pk->expiredate ) - 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 ) +do_key (iobuf_t out, int ctb, PKT_public_key *pk) { - int rc = 0; + gpg_error_t err = 0; int i, nskey, npkey; - IOBUF a = iobuf_temp(); /* Build in a self-enlarging buffer. */ + iobuf_t a = iobuf_temp(); /* Build in a self-enlarging buffer. */ /* Write the version number - if none is specified, use 3 */ - if ( !sk->version ) + if ( !pk->version ) iobuf_put ( a, 3 ); else - iobuf_put ( a, sk->version ); - write_32 (a, sk->timestamp ); + iobuf_put ( a, pk->version ); + write_32 (a, pk->timestamp ); /* v3 needs the expiration time. */ - if ( sk->version < 4 ) + if ( pk->version < 4 ) { u16 ndays; - if ( sk->expiredate ) - ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L); + if ( pk->expiredate ) + ndays = (u16)((pk->expiredate - pk->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 ) - { - /* The simple rfc1991 (v3) way. */ - iobuf_put (a, sk->protect.algo ); - iobuf_write (a, sk->protect.iv, sk->protect.ivlen ); - } - else + /* 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) { - /* 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 ); - } - else + /* 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 ); - - if ( sk->protect.s2k.mode == 3 ) - iobuf_put (a, sk->protect.s2k.count ); - - /* 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 ( 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; - - 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++ ) + /* 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 (ski->s2k.mode == 1 || ski->s2k.mode == 3) + iobuf_write (a, ski->s2k.salt, 8); + + if (ski->s2k.mode == 3) + iobuf_put (a, ski->s2k.count); + + /* For our special modes 1001, 1002 we do not need an IV. */ + if (ski->s2k.mode != 1001 && ski->s2k.mode != 1002) + iobuf_write (a, ski->iv, ski->ivlen); + } + } + else /* Not protected. */ + iobuf_put (a, 0 ); + + 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 (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 (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[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 diff --git a/g10/card-util.c b/g10/card-util.c index 4b537bcb3..1dd7a9219 100644 --- a/g10/card-util.c +++ b/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; - - - 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 (!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); - - 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; - } - - 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")); - - 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")); - } - - 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; - } - -#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 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; - - leave: - if (copied_sk) - free_secret_key (copied_sk); - agent_release_card_info (&info); - return okay; +/* 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; */ + +/* 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; */ +/* } */ + +/* show_card_key_info (&info); */ + +/* 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; */ +/* } */ + +/* 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")); */ + +/* 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")); */ +/* } */ + +/* 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; */ +/* } */ + +/* #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 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; */ + +/* leave: */ +/* if (copied_sk) */ +/* free_secret_key (copied_sk); */ +/* agent_release_card_info (&info); */ +/* return okay; */ + return -1; } diff --git a/g10/delkey.c b/g10/delkey.c index 2361d8323..62c75632b 100644 --- a/g10/delkey.c +++ b/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 ) + pk = node->pkt->pkt.public_key; + keyid_from_pk( pk, keyid ); + + if (!force) { - sk = node->pkt->pkt.secret_key; - keyid_from_sk( sk, keyid ); - } - else - { - /* public */ - 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 (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" diff --git a/g10/export.c b/g10/export.c index e5a0d9d95..bea798e47 100644 --- a/g10/export.c +++ b/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; - - *any = 0; - init_packet( &pkt ); - kdbhd = keydb_new (); - - if (!users) { - ndesc = 1; - desc = xcalloc ( ndesc, sizeof *desc ); - desc[0].mode = KEYDB_SEARCH_MODE_FIRST; + 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 (); + + 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; - - keyid_from_sk(sk,sk_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; + if ((node=find_kbnode(keyblock, PKT_SECRET_KEY))) + { + PKT_public_key *pk = node->pkt->pkt.public_key; + + keyid_from_pk (pk, keyid); + + /* 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; + } - /* Make sure that ring_trust packets never get exported. */ - if (node->pkt->pkttype == PKT_RING_TRUST) + /* 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; + } + + /* 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); + } - /* 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. + /* 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) + 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. - 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(skip_until_subkey) - continue; - - /* Mark this one as processed. */ + 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(skip_until_subkey) + continue; + + /* Mark this one as processed. */ + { + subkey_list_t tmp = new_subkey_list_item (node); + tmp->next = subkey_list; + subkey_list = tmp; + } + } + + 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 */ + + /* 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) { - subkey_list_t tmp = new_subkey_list_item (node); - tmp->next = subkey_list; - subkey_list = tmp; + int i; + + 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; } - } - - 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 */ - - /* 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; - - 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 ) { + } + + /* 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; - - 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; - } - - if ((options&EXPORT_SEXP_FORMAT)) - rc = build_sexp (out, node->pkt, &indent); - else - rc = 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)); - - sha1_warned=1; - } - - if ((options&EXPORT_SEXP_FORMAT)) - rc = build_sexp (out, node->pkt, &indent); - else - rc = build_packet (out, node->pkt); - } - - if( rc ) { - log_error("build_packet(%d) failed: %s\n", - node->pkt->pkttype, g10_errstr(rc) ); - goto leave; + 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; */ + + /* 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)) */ + /* 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.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; + } + + if ((options&EXPORT_SEXP_FORMAT)) + err = build_sexp (out, node->pkt, &indent); + else + err = build_packet (out, node->pkt); + } + + 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'); - } - - ++*any; - if(keyblock_out) - { - *keyblock_out=keyblock; - break; - } + if ((options&EXPORT_SEXP_FORMAT) && indent) + { + for (; indent; indent--) + iobuf_put (out, ')'); + iobuf_put (out, '\n'); + } + + ++*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; - - 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; + 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 (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]; - - 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; + /* 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'); */ + + /* return 0; */ } diff --git a/g10/free-packet.c b/g10/free-packet.c index 5da7fc0ac..47d89eed5 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -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->user_id) + { + free_user_id (pk->user_id); + pk->user_id = NULL; } - if (pk->revkey) { - xfree(pk->revkey); - pk->revkey=NULL; - pk->numrevkeys=0; + 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; - - 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] ); + int n, 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 * @@ -257,48 +261,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 ) { xfree(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 diff --git a/g10/getkey.c b/g10/getkey.c index 4929974a3..401e66879 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -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"); diff --git a/g10/import.c b/g10/import.c index b1834655b..e3e7824a2 100644 --- a/g10/import.c +++ b/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; -} diff --git a/g10/keydb.h b/g10/keydb.h index ca6b901c2..63f42a572 100644 --- a/g10/keydb.h +++ b/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); diff --git a/g10/keyedit.c b/g10/keyedit.c index a0864577a..86dacfff5 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -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. */ diff --git a/g10/keyid.c b/g10/keyid.c index a6e8b3728..1d0972649 100644 --- a/g10/keyid.c +++ b/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]; - - 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; - - 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 ); + u32 dummy_keyid[2]; + + 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; + + 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 - */ -unsigned -nbits_from_pk( PKT_public_key *pk ) -{ - return pubkey_nbits( pk->pubkey_algo, pk->pkey ); -} -/**************** - * return the number of bits used in the sk +/* + * Return the number of bits used in PK. */ -unsigned -nbits_from_sk( PKT_secret_key *sk ) +unsigned int +nbits_from_pk (PKT_public_key *pk) { - return pubkey_nbits( sk->pubkey_algo, sk->skey ); + return pubkey_nbits (pk->pubkey_algo, pk->pkey); } + static const char * mk_datestr (char *buffer, time_t atime) { - 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 ); + 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 ); } - 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; - - return mk_datestr (buffer, atime); + static char buffer[11+5]; + time_t atime = pk->timestamp; + + return mk_datestr (buffer, atime); } -const char * -datestr_from_sk( PKT_secret_key *sk ) -{ - static char buffer[11+5]; - time_t atime = sk->timestamp; - - return mk_datestr (buffer, atime); -} const char * -datestr_from_sig( PKT_signature *sig ) +datestr_from_sig (PKT_signature *sig ) { - static char buffer[11+5]; - time_t atime = sig->timestamp; + static char buffer[11+5]; + time_t atime = sig->timestamp; - return mk_datestr (buffer, atime); + return mk_datestr (buffer, atime); } -const char * -expirestr_from_pk( PKT_public_key *pk ) -{ - static char buffer[11+5]; - time_t atime; - - if( !pk->expiredate ) - return _("never "); - atime = pk->expiredate; - return mk_datestr (buffer, atime); -} const char * -expirestr_from_sk( PKT_secret_key *sk ) +expirestr_from_pk (PKT_public_key *pk) { - static char buffer[11+5]; - time_t atime; + static char buffer[11+5]; + time_t atime; - if( !sk->expiredate ) - return _("never "); - atime = sk->expiredate; - return mk_datestr (buffer, atime); + if (!pk->expiredate) + return _("never "); + atime = pk->expiredate; + return mk_datestr (buffer, atime); } + const char * -expirestr_from_sig( PKT_signature *sig ) +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); + 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,106 +661,8 @@ 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; -} - /* Return the so called KEYGRIP which is the SHA-1 hash of the public diff --git a/g10/keylist.c b/g10/keylist.c index b99047b70..2d3574a6d 100644 --- a/g10/keylist.c +++ b/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; - - 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; - - 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"); - } - } + /* KBNODE node; */ + /* int i; */ + + 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"); */ + /* } */ + /* } */ } @@ -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; - - 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); + 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. *\/ */ + + /* 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); */ } diff --git a/g10/keyring.c b/g10/keyring.c index 5277db989..d069b1397 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -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) diff --git a/g10/main.h b/g10/main.h index e84d5d05f..ba8afbafa 100644 --- a/g10/main.h +++ b/g10/main.h @@ -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); diff --git a/g10/mainproc.c b/g10/mainproc.c index 87e99126a..02ffae92e 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -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 ); - - if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) - is_selfsig = 1; - } + || 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( opt.with_colons ) { putchar(':'); diff --git a/g10/packet.h b/g10/packet.h index d124f4c1d..02674a039 100644 --- a/g10/packet.h +++ b/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 ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 2065c22ef..c83524016 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -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) diff --git a/g10/passphrase.c b/g10/passphrase.c index b934cb349..60560123f 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -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, diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index d90559d32..74bdc7655 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -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); diff --git a/g10/sign.c b/g10/sign.c index d5b6a5118..eeb4549ca 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -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); |