aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--agent/ChangeLog101
-rw-r--r--agent/cvt-openpgp.c86
-rw-r--r--common/util.h24
-rw-r--r--configure.ac16
-rw-r--r--g10/ChangeLog15
-rw-r--r--g10/ecdh.c81
-rw-r--r--g10/export.c148
-rw-r--r--g10/gpg.c3
-rw-r--r--g10/import.c250
-rw-r--r--g10/keygen.c57
-rw-r--r--g10/keyid.c97
-rw-r--r--g10/main.h1
-rw-r--r--g10/passphrase.c104
-rw-r--r--include/ChangeLog5
-rw-r--r--include/cipher.h4
-rw-r--r--tests/openpgp/samplekeys/README3
-rw-r--r--tests/openpgp/samplekeys/ecc-sample-1-pub.asc22
-rw-r--r--tests/openpgp/samplekeys/ecc-sample-1-sec.asc25
19 files changed, 691 insertions, 355 deletions
diff --git a/ChangeLog b/ChangeLog
index d3e7eb1a7..d79108648 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2011-02-01 Werner Koch <[email protected]>
+
+ * configure.ac (HAVE_GCRY_PK_GET_CURVE): Define if availabale.
+
2011-01-20 Werner Koch <[email protected]>
* configure.ac (AC_CONFIG_FILES): Remove keyserver/.
diff --git a/agent/ChangeLog b/agent/ChangeLog
index 6338c56c5..d4a0de3a8 100644
--- a/agent/ChangeLog
+++ b/agent/ChangeLog
@@ -1,5 +1,12 @@
+2011-02-02 Werner Koch <[email protected]>
+
+ * cvt-openpgp.c (convert_secret_key): Remove algo mapping.
+
2011-01-31 Werner Koch <[email protected]>
+ * cvt-openpgp.c (convert_to_openpgp): Adjust to reverted Libgcrypt
+ ABI.
+
* protect.c (protect_info): Adjust ECDSA and ECDH parameter names.
Add "ecc".
* findkey.c (key_parms_from_sexp): Ditto.
@@ -522,7 +529,7 @@
* genkey.c (agent_protect_and_store): Return RC and not 0.
* protect.c (do_encryption): Fix ignored error code from malloc.
Reported by Fabian Keil.
-
+
2009-06-17 Werner Koch <[email protected]>
* call-pinentry.c (agent_get_confirmation): Add arg WITH_CANCEL.
@@ -546,7 +553,7 @@
* trustlist.c: Include estream.h.
(agent_marktrusted): Replace stdio stream by estream functions.
- * protect-tool.c (store_private_key): Use bin2hex.
+ * protect-tool.c (store_private_key): Use bin2hex.
2009-06-02 Werner Koch <[email protected]>
@@ -560,7 +567,7 @@
2009-05-15 Werner Koch <[email protected]>
Fix bug #1053.
-
+
* agent.h (lookup_ttl_t): New.
* findkey.c (unprotect): Add arg LOOKUP_TTL.
(agent_key_from_file): Ditto.
@@ -638,7 +645,7 @@
(agent_istrusted): Add arg R_DISABLED. Change all callers.
(agent_marktrusted): Do not ask if flagged as disabled. Reverse
the order of the questions. Store the disabled flag.
-
+
* gpg-agent.c (main): Save signal mask and open fds. Restore mask
and close all fds prior to the exec. Fixes bug#1013.
@@ -749,11 +756,11 @@
* command.c (cmd_geteventcounter): Mark unused arg.
(cmd_listtrusted, cmd_pksign, cmd_pkdecrypt, cmd_genkey): Ditto.
(cmd_updatestartuptty, post_cmd_notify): Ditto.
- * command-ssh.c (add_control_entry)
- (ssh_handler_request_identities, ssh_handler_remove_identity)
- (ssh_handler_remove_all_identities, ssh_handler_lock)
+ * command-ssh.c (add_control_entry)
+ (ssh_handler_request_identities, ssh_handler_remove_identity)
+ (ssh_handler_remove_all_identities, ssh_handler_lock)
(ssh_handler_unlock): Ditto.
- * call-pinentry.c (pinentry_active_p, popup_message_thread)
+ * call-pinentry.c (pinentry_active_p, popup_message_thread)
(agent_popup_message_stop): Ditto.
* findkey.c (agent_public_key_from_file): Ditto.
* genkey.c (check_passphrase_pattern): Ditto.
@@ -872,7 +879,7 @@
* agent.h (struct server_control_s): Add XAUTHORITY and
PINENTRY_USER_DATA.
* gpg-agent.c: New option --xauthority.
- (main, agent_init_default_ctrl)
+ (main, agent_init_default_ctrl)
(agent_deinit_default_ctrl): Implemented
* command.c (cmd_updatestartuptty): Ditto.
* command-ssh.c (start_command_handler_ssh): Ditto.
@@ -1032,7 +1039,7 @@
2007-06-21 Werner Koch <[email protected]>
- * agent.h (ctrl_t): Remove. It is now declared in ../common/util.h.
+ * agent.h (ctrl_t): Remove. It is now declared in ../common/util.h.
* gpg-agent.c (check_for_running_agent): New arg SILENT. Changed
all callers.
@@ -1065,7 +1072,7 @@
* preset-passphrase.c (main): Setup default socket name for
simple-pwquery.
(map_spwq_error): Remove.
- (MAP_SPWQ_ERROR_IMPL): New.
+ (MAP_SPWQ_ERROR_IMPL): New.
* call-pinentry.c (start_pinentry): Use gnupg_module_name.
* call-scd.c (start_scd): Ditto.
@@ -1127,7 +1134,7 @@
(main): Call the setup_libgcrypt_logging helper.
* protect-tool.c (my_gcry_logger): Removed.
(main): Call the setup_libgcrypt_logging helper.
-
+
2007-04-03 Werner Koch <[email protected]>
* trustlist.c (read_trustfiles): Take a missing trustlist as an
@@ -1135,7 +1142,7 @@
2007-03-20 Werner Koch <[email protected]>
- * protect-tool.c: New option --p12-charset.
+ * protect-tool.c: New option --p12-charset.
* minip12.c (p12_build): Implement it.
2007-03-19 Werner Koch <[email protected]>
@@ -1170,7 +1177,7 @@
2007-01-31 Werner Koch <[email protected]>
- * command-ssh.c (start_command_handler_ssh):
+ * command-ssh.c (start_command_handler_ssh):
* Makefile.am (t_common_ldadd): Add LIBICONV.
@@ -1298,7 +1305,7 @@
(agent_pksign_do): Use it here for the TLS algo.
* agent.h (GCRY_MD_USER_TLS_MD5SHA1): New.
* divert-scd.c (pksign): Add case for tls-md5sha1.
-
+
* divert-scd.c (encode_md_for_card): Check that the algo is valid.
2006-10-04 Werner Koch <[email protected]>
@@ -1368,7 +1375,7 @@
Replaced all Assuan error codes by libgpg-error codes. Removed
all map_to_assuan_status and map_assuan_err.
-
+
* gpg-agent.c (main): Call assuan_set_assuan_err_source to have Assuan
switch to gpg-error codes.
* command.c (set_error): Adjusted.
@@ -1412,7 +1419,7 @@
* minip12.c (oid_pkcs_12_keyBag): New.
(parse_bag_encrypted_data): New arg R_RESULT. Support keybags and
- return the key object.
+ return the key object.
(p12_parse): Take new arg into account. Free RESULT on error.
2006-06-26 Werner Koch <[email protected]>
@@ -1480,7 +1487,7 @@
* call-scd.c (inq_needpin): Reworked to support the new KEYPADINFO.
* query.c (start_pinentry): Keep track of the owner.
- (popup_message_thread, agent_popup_message_start)
+ (popup_message_thread, agent_popup_message_start)
(agent_popup_message_stop, agent_reset_query): New.
* command.c (start_command_handler): Make sure a popup window gets
closed.
@@ -1531,7 +1538,7 @@
2005-06-21 Werner Koch <[email protected]>
- * minip12.c (create_final): Cast size_t to ulong for printf.
+ * minip12.c (create_final): Cast size_t to ulong for printf.
(build_key_bag, build_cert_bag, build_cert_sequence): Ditto.
2005-06-16 Werner Koch <[email protected]>
@@ -1546,7 +1553,7 @@
* protect.c (do_encryption): Ditto.
(do_encryption): Made arg PROTBEGIN unsigned. Initialize RESULT
and RESULTLEN even on error.
- (merge_lists): Need to cast unsigned char * for strcpy. Initialize
+ (merge_lists): Need to cast unsigned char * for strcpy. Initialize
RESULTand RESULTLEN even on error.
(agent_unprotect): Likewise for strtoul.
(make_shadow_info): Made P and INFO plain char.
@@ -1606,7 +1613,7 @@
* command.c (cmd_updatestartuptty): New.
* gpg-agent.c: New option --write-env-file.
-
+
* gpg-agent.c (handle_connections): Make sure that the signals we
are handling are not blocked.Block signals while creating new
threads.
@@ -1876,8 +1883,8 @@
(make_cstring): Ditto.
(data_sign): Don't use a variable for the passphrase prompt, make
it translatable.
- (ssh_request_process):
-
+ (ssh_request_process):
+
* findkey.c (modify_description): Renamed arguments for clarity,
polished documentation. Make comment a C-string. Fixed case of
@@ -2003,7 +2010,7 @@
2004-12-21 Werner Koch <[email protected]>
* gpg-agent.c (main): Use default_homedir().
- * protect-tool.c (main): Ditto.
+ * protect-tool.c (main): Ditto.
2004-12-20 Werner Koch <[email protected]>
@@ -2029,7 +2036,7 @@
* query.c (initialize_module_query): New.
* call-scd.c (initialize_module_call_scd): New.
* gpg-agent.c (main): Call them.
-
+
2004-12-18 Werner Koch <[email protected]>
* gpg-agent.c (main): Remove special Pth initialize.
@@ -2081,10 +2088,10 @@
to Moritz for pointing this out.
2004-09-25 Moritz Schulte <[email protected]>
-
+
* agent.h: Declare: agent_pksign_do.
(struct server_control_s): New member: raw_value.
-
+
* pksign.c (do_encode_md): New argument: raw_value; support
generation of raw (non-pkcs1) data objects; adjust callers.
(agent_pksign_do): New function, based on code ripped
@@ -2092,7 +2099,7 @@
(agent_pksign): Use agent_pksign_do.
* command.c (start_command_handler): Set ctrl.digest.raw_value.
-
+
2004-09-09 Werner Koch <[email protected]>
* gpg-agent.c (check_for_running_agent): New.
@@ -2133,14 +2140,14 @@
* gpg-agent.c (handle_signal): Reload the trustlist on SIGHUP.
(start_connection_thread): Hack to simulate a ticker.
- * trustlist.c (agent_trustlist_housekeeping)
+ * trustlist.c (agent_trustlist_housekeeping)
(agent_reload_trustlist): New. Protected all global functions
here with a simple counter which is sufficient for Pth.
2004-05-03 Werner Koch <[email protected]>
* gpg-agent.c: Remove help texts for options lile --lc-ctype.
- (main): New option --allow-mark-trusted.
+ (main): New option --allow-mark-trusted.
* trustlist.c (agent_marktrusted): Use it here.
2004-04-30 Werner Koch <[email protected]>
@@ -2213,7 +2220,7 @@
string. Changed all callers.
* minip12.c: Revamped the build part.
- (p12_build): New args CERT and CERTLEN.
+ (p12_build): New args CERT and CERTLEN.
2004-02-18 Werner Koch <[email protected]>
@@ -2307,7 +2314,7 @@
* findkey.c (agent_key_from_file): Now return an error code so
that we have more detailed error messages in the upper layers.
- This fixes the handling of pinentry's cancel button.
+ This fixes the handling of pinentry's cancel button.
* pksign.c (agent_pksign): Changed accordingly.
* pkdecrypt.c (agent_pkdecrypt): Ditto.
* command.c (cmd_passwd): Ditto.
@@ -2334,12 +2341,12 @@
* pksign.c (do_encode_md): Allocate enough space. Cast md
byte to unsigned char to prevent sign extension.
-
+
2003-08-14 Timo Schulz <[email protected]>
* pksign.c (do_encode_md): Due to the fact pkcs#1 padding
is now in Libgcrypt, use the new interface.
-
+
2003-07-31 Werner Koch <[email protected]>
* Makefile.am (gpg_agent_LDADD): Added INTLLIBS.
@@ -2389,7 +2396,7 @@
* gpg-agent.c (handle_connections): Adjusted for Pth 2.0
Adjusted for changes in the libgcrypt API. Some more fixes for the
- libgpg-error stuff.
+ libgpg-error stuff.
2003-06-04 Werner Koch <[email protected]>
@@ -2468,11 +2475,11 @@
(agent_askpin,agent_get_passphrase,agent_get_confirmation): Add
CTRL arg and pass it ot start_pinentry.
* command.c (cmd_get_passphrase): Pass CTRL argument.
- * trustlist.c (agent_marktrusted): Add CTRL argument
+ * trustlist.c (agent_marktrusted): Add CTRL argument
* command.c (cmd_marktrusted): Pass CTRL argument
- * divert-scd.c (ask_for_card): Add CTRL arg.
+ * divert-scd.c (ask_for_card): Add CTRL arg.
(divert_pksign,divert_pkdecrypt): Ditto. Changed caller.
- (getpin_cb): Use OPAQUE to pass the CTRL variable. Changed both
+ (getpin_cb): Use OPAQUE to pass the CTRL variable. Changed both
users.
* findkey.c (unprotect): Add CTRL arg.
(agent_key_from_file): Ditto.
@@ -2707,7 +2714,7 @@
convert it to hex here.
* findkey.c (agent_write_private_key): New.
* genkey.c (store_key): And use it here.
-
+
* pkdecrypt.c (agent_pkdecrypt): Changed the way the diversion is done.
* divert-scd.c (divert_pkdecrypt): Changed interface and
implemented it.
@@ -2737,7 +2744,7 @@
* protect.c (snext,sskip,smatch): Moved to
* sexp-parse.h: New file.
* divert-scd.c: New.
-
+
2002-02-27 Werner Koch <[email protected]>
* protect.c (agent_shadow_key): New.
@@ -2765,7 +2772,7 @@
* gpg-agent.c: New option --default-cache-ttl.
* cache.c (agent_put_cache): Use it.
-
+
* cache.c: Add a few debug outputs.
* protect.c (agent_private_key_type): New.
@@ -2773,10 +2780,10 @@
* findkey.c (agent_key_from_file): Use it to decide whether we
have to unprotect a key.
(unprotect): Cache the passphrase.
-
+
* findkey.c (agent_key_from_file,agent_key_available): The key
files do now require a ".key" suffix to make a script's life
- easier.
+ easier.
* genkey.c (store_key): Ditto.
2002-01-31 Werner Koch <[email protected]>
@@ -2784,11 +2791,11 @@
* genkey.c (store_key): Protect the key.
(agent_genkey): Ask for the passphrase.
* findkey.c (unprotect): Actually unprotect the key.
- * query.c (agent_askpin): Add an optional start_err_text.
+ * query.c (agent_askpin): Add an optional start_err_text.
2002-01-30 Werner Koch <[email protected]>
- * protect.c: New.
+ * protect.c: New.
(hash_passphrase): Based on the GnuPG 1.0.6 version.
* protect-tool.c: New
@@ -2842,10 +2849,10 @@
* command.c (rc_to_assuan_status): Removed and changed all callers
to use map_to_assuan_status.
-
+
2001-12-19 Werner Koch <[email protected]>
- * keyformat.txt: New.
+ * keyformat.txt: New.
2001-12-19 Marcus Brinkmann <[email protected]>
diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c
index 02c2bc841..690459330 100644
--- a/agent/cvt-openpgp.c
+++ b/agent/cvt-openpgp.c
@@ -37,7 +37,7 @@
/* Helper to pass data via the callback to do_unprotect. */
-struct try_do_unprotect_arg_s
+struct try_do_unprotect_arg_s
{
int is_v4;
int is_protected;
@@ -87,10 +87,12 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip)
"(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
break;
- case GCRY_PK_ECDSA:
- case GCRY_PK_ECDH:
+ case GCRY_PK_ECDSA:
+ case GCRY_PK_ECDH:
err = gcry_sexp_build (&s_pkey, NULL,
- "(public-key(ecc(c%m)(q%m)))", pkey[0], pkey[1]);
+ "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))",
+ pkey[0], pkey[1], pkey[2], pkey[3], pkey[4],
+ pkey[5]);
break;
default:
@@ -108,8 +110,7 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip)
/* Convert a secret key given as algorithm id and an array of key
parameters into our s-expression based format. Note that
- PUBKEY_ALGO is a standard id and not an OpenPGP id.
- */
+ PUBKEY_ALGO has an gcrypt algorithm number. */
static gpg_error_t
convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
{
@@ -118,9 +119,6 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
*r_key = NULL;
- /* FIXME: This is not consistent with the above comment. */
- pubkey_algo = map_pk_openpgp_to_gcry (pubkey_algo);
-
switch (pubkey_algo)
{
case GCRY_PK_DSA:
@@ -147,15 +145,15 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey)
break;
case GCRY_PK_ECDSA:
- err = gcry_sexp_build (&s_skey, NULL,
- "(private-key(ecdsa(c%m)(q%m)(d%m)))",
- skey[0], skey[1], skey[2]);
- break;
-
case GCRY_PK_ECDH:
+ /* Although our code would work with "ecc" we explicitly use
+ "ecdh" or "ecdsa" to implicitly set the key capabilities. */
err = gcry_sexp_build (&s_skey, NULL,
- "(private-key(ecdh(c%m)(q%m)(p%m)(d%m)))",
- skey[0], skey[1], skey[2], skey[3]);
+ "(private-key(%s(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)"
+ "(d%m)))",
+ pubkey_algo == GCRY_PK_ECDSA?"ecdsa":"ecdh",
+ skey[0], skey[1], skey[2], skey[3], skey[4],
+ skey[5], skey[6]);
break;
default:
@@ -184,7 +182,7 @@ hash_passphrase_and_set_key (const char *passphrase,
keylen = gcry_cipher_get_algo_keylen (protect_algo);
if (!keylen)
return gpg_error (GPG_ERR_INTERNAL);
-
+
key = xtrymalloc_secure (keylen);
if (!key)
return gpg_error_from_syserror ();
@@ -204,7 +202,7 @@ static u16
checksum (const unsigned char *p, unsigned int n)
{
u16 a;
-
+
for (a=0; n; n-- )
a += *p++;
return a;
@@ -272,7 +270,7 @@ do_unprotect (const char *passphrase,
return gpg_error (GPG_ERR_MISSING_VALUE);
if (nskey+1 >= skeysize)
return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
-
+
/* Check whether SKEY is at all protected. If it is not protected
merely verify the checksum. */
if (!is_protected)
@@ -284,7 +282,7 @@ do_unprotect (const char *passphrase,
{
if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
return gpg_error (GPG_ERR_BAD_SECKEY);
-
+
err = gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, skey[i]);
if (!err)
{
@@ -301,7 +299,7 @@ do_unprotect (const char *passphrase,
if (err)
return err;
}
-
+
if (actual_csum != desired_csum)
return gpg_error (GPG_ERR_CHECKSUM);
return 0;
@@ -324,7 +322,7 @@ do_unprotect (const char *passphrase,
s2k_algo, gcry_md_algo_name (s2k_algo));
return gpg_error (GPG_ERR_DIGEST_ALGO);
}
-
+
err = gcry_cipher_open (&cipher_hd, protect_algo,
GCRY_CIPHER_MODE_CFB,
(GCRY_CIPHER_SECURE
@@ -343,10 +341,10 @@ do_unprotect (const char *passphrase,
{
gcry_cipher_close (cipher_hd);
return err;
- }
+ }
gcry_cipher_setiv (cipher_hd, protect_iv, protect_ivlen);
-
+
actual_csum = 0;
if (pkt_version >= 4)
{
@@ -379,15 +377,15 @@ do_unprotect (const char *passphrase,
{
/* This is the new SHA1 checksum method to detect tampering
with the key as used by the Klima/Rosa attack. */
- desired_csum = 0;
+ desired_csum = 0;
actual_csum = 1; /* Default to bad checksum. */
- if (ndata < 20)
+ if (ndata < 20)
log_error ("not enough bytes for SHA-1 checksum\n");
- else
+ else
{
gcry_md_hd_t h;
-
+
if (gcry_md_open (&h, GCRY_MD_SHA1, 1))
BUG(); /* Algo not available. */
gcry_md_write (h, data, ndata - 20);
@@ -397,13 +395,13 @@ do_unprotect (const char *passphrase,
gcry_md_close (h);
}
}
- else
+ else
{
/* Old 16 bit checksum method. */
if (ndata < 2)
{
log_error ("not enough bytes for checksum\n");
- desired_csum = 0;
+ desired_csum = 0;
actual_csum = 1; /* Mark checksum bad. */
}
else
@@ -417,7 +415,7 @@ do_unprotect (const char *passphrase,
}
}
}
-
+
/* Better check it here. Otherwise the gcry_mpi_scan would fail
because the length may have an arbitrary value. */
if (desired_csum == actual_csum)
@@ -468,7 +466,7 @@ do_unprotect (const char *passphrase,
gcry_cipher_close (cipher_hd);
return gpg_error (GPG_ERR_BAD_SECKEY);
}
-
+
buffer = xtrymalloc_secure (ndata);
if (!buffer)
{
@@ -476,7 +474,7 @@ do_unprotect (const char *passphrase,
gcry_cipher_close (cipher_hd);
return err;
}
-
+
gcry_cipher_sync (cipher_hd);
buffer[0] = p[0];
buffer[1] = p[1];
@@ -557,7 +555,7 @@ try_do_unprotect_cb (struct pin_entry_info_s *pi)
pointed to by GRIP. On error NULL is stored at all return
arguments. */
gpg_error_t
-convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
+convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
unsigned char *grip, const char *prompt,
const char *cache_nonce,
unsigned char **r_key, char **r_passphrase)
@@ -625,7 +623,7 @@ convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
if (!protect_algo && !!strcmp (string, "IDEA"))
protect_algo = GCRY_CIPHER_IDEA;
xfree (string);
-
+
value = gcry_sexp_nth_data (list, 3, &valuelen);
if (!value || !valuelen || valuelen > sizeof iv)
goto bad_seckey;
@@ -848,7 +846,7 @@ convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp,
bad_seckey:
err = gpg_error (GPG_ERR_BAD_SECKEY);
goto leave;
-
+
outofmem:
err = gpg_error (GPG_ERR_ENOMEM);
goto leave;
@@ -874,13 +872,13 @@ key_from_sexp (gcry_sexp_t sexp, const char *elems, gcry_mpi_t *array)
}
array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l2);
- if (!array[idx])
+ if (!array[idx])
{
err = gpg_error (GPG_ERR_INV_OBJ); /* Required parameter invalid. */
goto leave;
}
}
-
+
leave:
if (err)
{
@@ -1028,7 +1026,7 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
gcry_sexp_release (list);
return gpg_error (GPG_ERR_INV_OBJ); /* Invalid structure of object. */
}
-
+
algo = gcry_pk_map_name (name);
xfree (name);
@@ -1038,8 +1036,8 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
case GCRY_PK_ELG: algoname = "elg"; npkey = 3; elems = "pgyx"; break;
case GCRY_PK_ELG_E: algoname = "elg"; npkey = 3; elems = "pgyx"; break;
case GCRY_PK_DSA: algoname = "dsa"; npkey = 4; elems = "pqgyx"; break;
- case GCRY_PK_ECDSA: algoname = "ecdsa"; npkey = 2; elems = "cqd"; break;
- case GCRY_PK_ECDH: algoname = "ecdh"; npkey = 3; elems = "cqpd"; break;
+ case GCRY_PK_ECDSA: algoname = "ecdsa"; npkey = 6; elems = "pabgnqd"; break;
+ case GCRY_PK_ECDH: algoname = "ecdh"; npkey = 6; elems = "pabgnqd"; break;
default: algoname = ""; npkey = 0; elems = NULL; break;
}
assert (!elems || strlen (elems) < DIM (array) );
@@ -1070,9 +1068,9 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
void *format_args[10+2];
size_t n;
gcry_sexp_t tmpkey, tmpsexp = NULL;
-
+
snprintf (countbuf, sizeof countbuf, "%lu", s2k_count);
-
+
init_membuf (&mbuf, 50);
put_membuf_str (&mbuf, "(skey");
for (i=j=0; i < npkey; i++)
@@ -1105,7 +1103,7 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
" %S\n"
" (protection sha1 aes %b 1:3 sha1 %b %s))\n",
algoname,
- tmpkey,
+ tmpkey,
(int)sizeof protect_iv, protect_iv,
(int)sizeof salt, salt,
countbuf);
diff --git a/common/util.h b/common/util.h
index cf38ad4f8..fc3dd02df 100644
--- a/common/util.h
+++ b/common/util.h
@@ -42,6 +42,12 @@
#ifndef GPG_ERR_FULLY_CANCELED
#define GPG_ERR_FULLY_CANCELED 198
#endif
+#ifndef GPG_ERR_INV_CURVE
+#define GPG_ERR_INV_CURVE 187
+#endif
+#ifndef GPG_ERR_UNKNOWN_CURVE
+#define GPG_ERR_UNKNOWN_CURVE 188
+#endif
/* Hash function used with libksba. */
@@ -75,10 +81,10 @@
/* GCC attributes. */
-#if __GNUC__ >= 4
+#if __GNUC__ >= 4
# define GNUPG_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a)))
#else
-# define GNUPG_GCC_A_SENTINEL(a)
+# define GNUPG_GCC_A_SENTINEL(a)
#endif
@@ -132,14 +138,14 @@ int answer_is_yes_no_quit (const char *s);
int answer_is_okay_cancel (const char *s, int def_answer);
/*-- xreadline.c --*/
-ssize_t read_line (FILE *fp,
+ssize_t read_line (FILE *fp,
char **addr_of_buffer, size_t *length_of_buffer,
size_t *max_length);
/*-- b64enc.c and b64dec.c --*/
-struct b64state
-{
+struct b64state
+{
unsigned int flags;
int idx;
int quad_count;
@@ -184,9 +190,9 @@ unsigned char *make_canon_sexp_from_rsa_pk (const void *m, size_t mlen,
size_t *r_len);
gpg_error_t get_rsa_pk_from_canon_sexp (const unsigned char *keydata,
size_t keydatalen,
- unsigned char const **r_n,
+ unsigned char const **r_n,
size_t *r_nlen,
- unsigned char const **r_e,
+ unsigned char const **r_e,
size_t *r_elen);
gpg_error_t get_pk_algo_from_canon_sexp (const unsigned char *keydata,
size_t keydatalen,
@@ -231,7 +237,7 @@ const char *dirmngr_socket_name (void);
gpgconf. */
#define GNUPG_MODULE_NAME_AGENT 1
#define GNUPG_MODULE_NAME_PINENTRY 2
-#define GNUPG_MODULE_NAME_SCDAEMON 3
+#define GNUPG_MODULE_NAME_SCDAEMON 3
#define GNUPG_MODULE_NAME_DIRMNGR 4
#define GNUPG_MODULE_NAME_PROTECT_TOOL 5
#define GNUPG_MODULE_NAME_CHECK_PATTERN 6
@@ -286,7 +292,7 @@ int gnupg_compare_version (const char *a, const char *b);
#ifndef HAVE_TTYNAME
/* Systems without ttyname (W32) will merely return NULL. */
static inline char *
-ttyname (int fd)
+ttyname (int fd)
{
(void)fd;
return NULL;
diff --git a/configure.ac b/configure.ac
index e24117b28..1081b2d3c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -742,6 +742,7 @@ AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION",
AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION",
have_libgcrypt=yes,have_libgcrypt=no)
+# fixme: We can remove the next two checks if we require libgcrypt 1.5.
AC_CACHE_CHECK([whether Libgcrypt support ECDH], gnupg_cv_gcry_pk_ecdh,
[ _gnupg_gcry_save_cflags=$CFLAGS
CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS"
@@ -756,6 +757,21 @@ if test "$gnupg_cv_gcry_pk_ecdh" = yes; then
[Define if gcrypt.h has the enum value for ECDH.])
fi
+AC_CACHE_CHECK([whether Libgcrypt has gcry_pk_get_curve],
+ gnupg_cv_gcry_pk_get_curve,
+ [ _gnupg_gcry_save_cflags=$CFLAGS
+ CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS"
+ AC_TRY_COMPILE(
+ [#include <gcrypt.h>],
+ [ return gcry_pk_get_curve (NULL, 0, NULL); ],
+ gnupg_cv_gcry_pk_get_curve=yes,
+ gnupg_cv_gcry_pk_get_curve=no)
+ CFLAGS=$_gnupg_gcry_save_cflags])
+if test "$gnupg_cv_gcry_pk_get_curve" = yes; then
+ AC_DEFINE([HAVE_GCRY_PK_GET_CURVE], 1,
+ [Define if gcrypt.h has gcry_pk_get_curve.])
+fi
+
#
# libassuan is used for IPC
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 2a284e765..bb55ff85f 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,18 @@
+2011-02-02 Werner Koch <[email protected]>
+
+ * import.c (transfer_secret_keys): Make sure keyids are available.
+
+ * keyid.c (hash_public_key): Adjust for the ECC case.
+
+2011-02-01 Werner Koch <[email protected]>
+
+ * import.c (transfer_secret_keys): Implement ECC case.
+
+ * gpg.c (main): Call setup_libgcrypt_logging.
+
+ * keygen.c (gpg_curve_to_oid): New.
+ (ecckey_from_sexp): Factor curve name mapping out to new function.
+
2011-01-31 Werner Koch <[email protected]>
* misc.c (make_flagged_int, openpgp_oid_from_str)
diff --git a/g10/ecdh.c b/g10/ecdh.c
index 09ab3ed16..f97667ae3 100644
--- a/g10/ecdh.c
+++ b/g10/ecdh.c
@@ -36,7 +36,7 @@ static const struct
unsigned int qbits;
int openpgp_hash_id; /* KEK digest algorithm. */
int openpgp_cipher_id; /* KEK cipher algorithm. */
-} kek_params_table[] =
+} kek_params_table[] =
/* Note: Must be sorted by ascending values for QBITS. */
{
{ 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES },
@@ -60,8 +60,8 @@ pk_ecdh_default_params (unsigned int qbits)
if (!kek_params)
return NULL;
kek_params[0] = 3; /* Number of bytes to follow. */
- kek_params[1] = 1; /* Version for KDF+AESWRAP. */
-
+ kek_params[1] = 1; /* Version for KDF+AESWRAP. */
+
/* Search for matching KEK parameter. Defaults to the strongest
possible choices. Performance is not an issue here, only
interoperability. */
@@ -78,7 +78,7 @@ pk_ecdh_default_params (unsigned int qbits)
assert (i < DIM (kek_params_table));
if (DBG_CIPHER)
log_printhex ("ECDH KEK params are", kek_params, sizeof(kek_params) );
-
+
return gcry_mpi_set_opaque (NULL, kek_params, 4 * 8);
}
@@ -88,16 +88,16 @@ pk_ecdh_default_params (unsigned int qbits)
key_derivation+key_wrapping. If IS_ENCRYPT is true the function
encrypts; if false, it decrypts. On success the result is stored
at R_RESULT; on failure NULL is stored at R_RESULT and an error
- code returned.
+ code returned.
FIXME: explain PKEY and PK_FP.
*/
-
+
/*
TODO: memory leaks (x_secret).
*/
gpg_error_t
-pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
+pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
const byte pk_fp[MAX_FINGERPRINT_LEN],
gcry_mpi_t data, gcry_mpi_t *pkey,
gcry_mpi_t *r_result)
@@ -106,8 +106,8 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
byte *secret_x;
int secret_x_size;
unsigned int nbits;
- const unsigned char *kdf_params;
- size_t kdf_params_size;
+ const unsigned char *kek_params;
+ size_t kek_params_size;
int kdf_hash_algo;
int kdf_encr_algo;
unsigned char message[256];
@@ -139,11 +139,11 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
return err;
}
- secret_x_size = (nbits+7)/8;
+ secret_x_size = (nbits+7)/8;
assert (nbytes > secret_x_size);
memmove (secret_x, secret_x+1, secret_x_size);
memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
-
+
if (DBG_CIPHER)
log_printhex ("ECDH shared secret X is:", secret_x, secret_x_size );
}
@@ -158,24 +158,24 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
*/
if (!gcry_mpi_get_flag (pkey[2], GCRYMPI_FLAG_OPAQUE))
return GPG_ERR_BUG;
- kdf_params = gcry_mpi_get_opaque (pkey[2], &nbits);
- kdf_params_size = (nbits+7)/8;
-
+ kek_params = gcry_mpi_get_opaque (pkey[2], &nbits);
+ kek_params_size = (nbits+7)/8;
+
if (DBG_CIPHER)
- log_printhex ("ecdh KDF params:", kdf_params, kdf_params_size);
-
+ log_printhex ("ecdh KDF params:", kek_params, kek_params_size);
+
/* Expect 4 bytes 03 01 hash_alg symm_alg. */
- if (kdf_params_size != 4 || kdf_params[0] != 3 || kdf_params[1] != 1)
+ if (kek_params_size != 4 || kek_params[0] != 3 || kek_params[1] != 1)
return GPG_ERR_BAD_PUBKEY;
-
- kdf_hash_algo = kdf_params[2];
- kdf_encr_algo = kdf_params[3];
-
+
+ kdf_hash_algo = kek_params[2];
+ kdf_encr_algo = kek_params[3];
+
if (DBG_CIPHER)
log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n",
openpgp_md_algo_name (kdf_hash_algo),
openpgp_cipher_algo_name (kdf_encr_algo));
-
+
if (kdf_hash_algo != GCRY_MD_SHA256
&& kdf_hash_algo != GCRY_MD_SHA384
&& kdf_hash_algo != GCRY_MD_SHA512)
@@ -199,7 +199,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
/* fixed-length field 4 */
iobuf_write (obuf, "Anonymous Sender ", 20);
/* fixed-length field 5, recipient fp */
- iobuf_write (obuf, pk_fp, 20);
+ iobuf_write (obuf, pk_fp, 20);
message_size = iobuf_temp_to_buffer (obuf, message, sizeof message);
iobuf_close (obuf);
@@ -207,11 +207,10 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
return err;
if(DBG_CIPHER)
- log_printhex ("ecdh KDF message params are:",
- kdf_params, kdf_params_size );
+ log_printhex ("ecdh KDF message params are:", message, message_size);
}
- /* Derive a KEK (key wrapping key) using kdf_params and secret_x. */
+ /* Derive a KEK (key wrapping key) using MESSAGE and SECRET_X. */
{
gcry_md_hd_t h;
int old_size;
@@ -222,7 +221,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
kdf_hash_algo, gpg_strerror (err));
gcry_md_write(h, "\x00\x00\x00\x01", 4); /* counter = 1 */
gcry_md_write(h, secret_x, secret_x_size); /* x of the point X */
- gcry_md_write(h, kdf_params, kdf_params_size);/* KDF parameters */
+ gcry_md_write(h, message, message_size);/* KDF parameters */
gcry_md_final (h);
@@ -242,7 +241,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
if (DBG_CIPHER)
log_printhex ("ecdh KEK is:", secret_x, secret_x_size );
}
-
+
/* And, finally, aeswrap with key secret_x. */
{
gcry_cipher_hd_t hd;
@@ -284,7 +283,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
if (is_encrypt)
{
byte *in = data_buf+1+data_buf_size+8;
-
+
/* Write data MPI into the end of data_buf. data_buf is size
aeswrap data. */
err = gcry_mpi_print (GCRYMPI_FMT_USG, in,
@@ -296,7 +295,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
xfree (data_buf);
return err;
}
-
+
if (DBG_CIPHER)
log_printhex ("ecdh encrypting :", in, data_buf_size );
@@ -325,14 +324,14 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
gpg_strerror (err));
return err;
}
-
+
*r_result = result;
}
else
{
byte *in;
const void *p;
-
+
p = gcry_mpi_get_opaque (data, &nbits);
nbytes = (nbits+7)/8;
if (!p || nbytes > data_buf_size || !nbytes)
@@ -349,10 +348,10 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
}
in = data_buf+data_buf_size;
data_buf_size = data_buf[0];
-
+
if (DBG_CIPHER)
log_printhex ("ecdh decrypting :", data_buf+1, data_buf_size);
-
+
err = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1,
data_buf_size);
gcry_cipher_close (hd);
@@ -363,12 +362,12 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
xfree (data_buf);
return err;
}
-
+
data_buf_size -= 8;
-
+
if (DBG_CIPHER)
log_printhex ("ecdh decrypted to :", in, data_buf_size);
-
+
/* Padding is removed later. */
/* if (in[data_buf_size-1] > 8 ) */
/* { */
@@ -376,7 +375,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
/* in[data_buf_size-1] ); */
/* return GPG_ERR_BAD_KEY; */
/* } */
-
+
err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, in, data_buf_size, NULL);
xfree (data_buf);
if (err)
@@ -385,11 +384,11 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi,
gpg_strerror (err));
return err;
}
-
+
*r_result = result;
}
}
-
+
return err;
}
@@ -453,5 +452,3 @@ pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN],
sk_fp, data/*encr data as an MPI*/,
skey, result);
}
-
-
diff --git a/g10/export.c b/g10/export.c
index 1eb0baa8b..91a6c87f1 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -107,7 +107,7 @@ export_pubkeys_stream (ctrl_t ctrl, iobuf_t out, strlist_t users,
kbnode_t *keyblock_out, unsigned int options )
{
int any, rc;
-
+
rc = do_export_stream (ctrl, out, users, 0, keyblock_out, options, &any);
if (!rc && !any)
rc = -1;
@@ -197,9 +197,9 @@ do_export (ctrl_t ctrl, strlist_t users, int secret, unsigned int options )
int any, rc;
armor_filter_context_t *afx = NULL;
compress_filter_context_t zfx;
-
+
memset( &zfx, 0, sizeof zfx);
-
+
rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out );
if (rc)
return rc;
@@ -251,7 +251,7 @@ subkey_in_list_p (subkey_list_t list, KBNODE node)
u32 kid[2];
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])
return 1;
@@ -293,17 +293,17 @@ exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
case KEYDB_SEARCH_MODE_LONG_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:
fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
break;
-
+
default:
break;
}
-
+
switch(desc->mode)
{
case KEYDB_SEARCH_MODE_SHORT_KID:
@@ -346,7 +346,7 @@ canon_pubkey_algo (int algo)
case GCRY_PK_RSA:
case GCRY_PK_RSA_E:
case GCRY_PK_RSA_S: return GCRY_PK_RSA;
- case GCRY_PK_ELG:
+ case GCRY_PK_ELG:
case GCRY_PK_ELG_E: return GCRY_PK_ELG;
default: return algo;
}
@@ -354,7 +354,7 @@ canon_pubkey_algo (int algo)
/* Use the key transfer format given in S_PGP to create the secinfo
- structure in PK and chnage the parameter array in PK to include the
+ structure in PK and change the parameter array in PK to include the
secret parameters. */
static gpg_error_t
transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
@@ -415,7 +415,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
goto bad_seckey;
protect_algo = gcry_cipher_map_name (string);
xfree (string);
-
+
value = gcry_sexp_nth_data (list, 3, &valuelen);
if (!value || !valuelen || valuelen > sizeof iv)
goto bad_seckey;
@@ -460,6 +460,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
|| gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &nskey)
|| !npkey || npkey >= nskey || nskey > PUBKEY_MAX_NSKEY)
goto bad_seckey;
+ pubkey_algo = map_pk_gcry_to_openpgp (pubkey_algo);
gcry_sexp_release (list);
list = gcry_sexp_find_token (top_list, "skey", 0);
@@ -557,6 +558,77 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
goto leave;
}
+ /* We need to change the received parameters for ECC algorithms.
+ The transfer format has all parameters but OpenPGP defines that
+ only the OID of the curve is to be used. */
+ if (pubkey_algo == PUBKEY_ALGO_ECDSA || pubkey_algo == PUBKEY_ALGO_ECDH)
+ {
+ gcry_sexp_t s_pubkey;
+ const char *curvename, *curveoidstr;
+ gcry_mpi_t mpi;
+
+ /* We build an S-expression with the public key parameters and
+ ask Libgcrypt to return the matching curve name. */
+ if (npkey != 6 || !skey[0] || !skey[1] || !skey[2]
+ || !skey[3] || !skey[4] || !skey[5]
+ || !skey[6] || skey[7])
+ {
+ err = gpg_error (GPG_ERR_INTERNAL);
+ goto leave;
+ }
+ err = gcry_sexp_build (&s_pubkey, NULL,
+ "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))",
+ skey[0], skey[1], skey[2], skey[3], skey[4]);
+ if (err)
+ goto leave;
+#ifdef HAVE_GCRY_PK_GET_CURVE
+ curvename = gcry_pk_get_curve (s_pubkey, 0, NULL);
+#else
+ curvename = "?";
+#endif
+ gcry_sexp_release (s_pubkey);
+ curveoidstr = gpg_curve_to_oid (curvename, NULL);
+ if (!curveoidstr)
+ {
+ log_error ("no OID known for curve `%s'\n", curvename);
+ err = gpg_error (GPG_ERR_UNKNOWN_NAME);
+ goto leave;
+ }
+ err = openpgp_oid_from_str (curveoidstr, &mpi);
+ if (err)
+ goto leave;
+
+ /* Now replace the curve parameters by the OID and shift the
+ rest of the parameters. */
+ gcry_mpi_release (skey[0]);
+ skey[0] = mpi;
+ for (idx=1; idx <= 4; idx++)
+ gcry_mpi_release (skey[idx]);
+ skey[1] = skey[5];
+ skey[2] = skey[6];
+ for (idx=3; idx <= 6; idx++)
+ skey[idx] = NULL;
+
+ /* Fixup the NPKEY and NSKEY to match OpenPGP reality. */
+ npkey = 2;
+ nskey = 3;
+
+ /* for (idx=0; skey[idx]; idx++) */
+ /* { */
+ /* log_info ("YYY skey[%d]:", idx); */
+ /* if (gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE)) */
+ /* { */
+ /* void *p; */
+ /* unsigned int nbits; */
+ /* p = gcry_mpi_get_opaque (skey[idx], &nbits); */
+ /* log_printhex (NULL, p, (nbits+7)/8); */
+ /* } */
+ /* else */
+ /* gcry_mpi_dump (skey[idx]); */
+ /* log_printf ("\n"); */
+ /* } */
+ }
+
/* Do some sanity checks. */
if (s2k_count <= 1024)
{
@@ -576,11 +648,17 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
err = openpgp_md_test_algo (s2k_algo);
if (err)
goto leave;
-
- /* Check that the public key parameters match. */
+
+ /* Check that the public key parameters match. Since Libgcrypt 1.5
+ and the gcry_pk_get_curve function, gcry_mpi_cmp handles opaque
+ MPI correctly and thus we don't need to to do the extra
+ opaqueness checks. */
for (idx=0; idx < npkey; idx++)
- if (gcry_mpi_get_flag (pk->pkey[idx], GCRYMPI_FLAG_OPAQUE)
+ if (0
+#ifndef HAVE_GCRY_PK_GET_CURVE
+ gcry_mpi_get_flag (pk->pkey[idx], GCRYMPI_FLAG_OPAQUE)
|| gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE)
+#endif
|| gcry_mpi_cmp (pk->pkey[idx], skey[idx]))
{
err = gpg_error (GPG_ERR_BAD_PUBKEY);
@@ -607,7 +685,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
err = gpg_error_from_syserror ();
goto leave;
}
-
+
ski->is_protected = 1;
ski->sha1chk = 1;
ski->algo = protect_algo;
@@ -636,7 +714,7 @@ transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
bad_seckey:
err = gpg_error (GPG_ERR_BAD_SECKEY);
goto leave;
-
+
outofmem:
err = gpg_error (GPG_ERR_ENOMEM);
goto leave;
@@ -671,7 +749,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
init_packet (&pkt);
kdbhd = keydb_new ();
- if (!users)
+ if (!users)
{
ndesc = 1;
desc = xcalloc (ndesc, sizeof *desc);
@@ -679,10 +757,10 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
}
else
{
- for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
+ for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
;
desc = xmalloc ( ndesc * sizeof *desc);
-
+
for (ndesc=0, sl=users; sl; sl = sl->next)
{
if (!(err=classify_user_id (sl->d, desc+ndesc)))
@@ -708,7 +786,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
goto leave;
}
#endif
-
+
/* For secret key export we need to setup a decryption context. */
if (secret)
{
@@ -721,7 +799,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
log_error ("error getting the KEK: %s\n", gpg_strerror (err));
goto leave;
}
-
+
/* Prepare a cipher context. */
err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
GCRY_CIPHER_MODE_AESWRAP, 0);
@@ -737,20 +815,20 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
kek = NULL;
}
- while (!(err = keydb_search2 (kdbhd, desc, ndesc, &descindex)))
+ while (!(err = keydb_search2 (kdbhd, desc, ndesc, &descindex)))
{
int skip_until_subkey = 0;
u32 keyid[2];
PKT_public_key *pk;
- if (!users)
+ if (!users)
desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
/* Read the keyblock. */
release_kbnode (keyblock);
keyblock = NULL;
err = keydb_get_keyblock (kdbhd, &keyblock);
- if (err)
+ if (err)
{
log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
goto leave;
@@ -802,7 +880,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
clean_key (keyblock, opt.verbose, (options&EXPORT_MINIMAL), NULL, NULL);
/* And write it. */
- for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
+ for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
{
if (skip_until_subkey)
{
@@ -835,7 +913,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
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.
@@ -843,7 +921,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
function of GnuPG < 2.1 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))
+ if (subkey_in_list_p (subkey_list, node))
skip_until_subkey = 1; /* Already processed this one. */
else
{
@@ -854,7 +932,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
&& exact_subkey_match_p (desc+j, node))
break;
if (!(j < ndesc))
- skip_until_subkey = 1; /* No other one matching. */
+ skip_until_subkey = 1; /* No other one matching. */
}
}
@@ -885,7 +963,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
&& 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;
@@ -904,7 +982,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
or a signature on an attrib */
while (kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE)
kbctx = kbctx->next;
-
+
continue;
}
@@ -913,7 +991,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
{
u32 subkidbuf[2], *subkid;
char *hexgrip, *serialno;
-
+
pk = node->pkt->pkt.public_key;
if (node->pkt->pkttype == PKT_PUBLIC_KEY)
subkid = NULL;
@@ -930,7 +1008,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
skip_until_subkey = 1;
continue;
}
-
+
err = hexkeygrip_from_pk (pk, &hexgrip);
if (err)
{
@@ -970,7 +1048,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
/* Create a key stub. */
struct seckey_info *ski;
const char *s;
-
+
pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
if (!ski)
{
@@ -989,7 +1067,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
ski->ivlen++, s += 2)
ski->iv[ski->ivlen] = xtoi_2 (s);
}
-
+
if ((options&EXPORT_SEXP_FORMAT))
err = build_sexp (out, node->pkt, &indent);
else
@@ -1032,7 +1110,7 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
if (!realkeylen)
goto unwraperror; /* Invalid csexp. */
-
+
err = gcry_sexp_sscan (&s_skey, NULL, key, realkeylen);
xfree (key);
key = NULL;
@@ -1252,7 +1330,7 @@ build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
/* For some packet types we write them in a S-expression format. This
is still EXPERIMENTAL and subject to change. */
-static int
+static int
build_sexp (iobuf_t out, PACKET *pkt, int *indent)
{
int rc;
diff --git a/g10/gpg.c b/g10/gpg.c
index 47e8b361f..6daa144be 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -1959,6 +1959,9 @@ main (int argc, char **argv)
NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
}
+ /* Use our own logging handler for Libcgrypt. */
+ setup_libgcrypt_logging ();
+
/* Put random number into secure memory */
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
diff --git a/g10/import.c b/g10/import.c
index 88abafd6a..99398c762 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -1,6 +1,6 @@
/* import.c - import a key into our key storage.
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2010 Free Software Foundation, Inc.
+ * 2007, 2010, 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -200,7 +200,7 @@ import_keys_internal (ctrl_t ctrl, iobuf_t inp, char **fnames, int nnames,
rc = import (ctrl, inp2, fname, stats, fpr, fpr_len, options);
iobuf_close(inp2);
/* Must invalidate that ugly cache to actually close it. */
- iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE,
+ iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE,
0, (char*)fname);
if( rc )
log_error("import from `%s' failed: %s\n", fname,
@@ -294,7 +294,7 @@ import (ctrl_t ctrl, IOBUF inp, const char* fname,struct stats_s *stats,
if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
rc = import_one (ctrl, fname, keyblock,
stats, fpr, fpr_len, options, 0);
- else if( keyblock->pkt->pkttype == PKT_SECRET_KEY )
+ else if( keyblock->pkt->pkttype == PKT_SECRET_KEY )
rc = import_secret_one (ctrl, fname, keyblock, stats, options);
else if( keyblock->pkt->pkttype == PKT_SIGNATURE
&& keyblock->pkt->pkt.signature->sig_class == 0x20 )
@@ -647,7 +647,7 @@ check_prefs (ctrl_t ctrl, kbnode_t keyblock)
kbnode_t node;
PKT_public_key *pk;
int problem=0;
-
+
merge_keys_and_selfsig(keyblock);
pk=keyblock->pkt->pkt.public_key;
@@ -672,9 +672,9 @@ check_prefs (ctrl_t ctrl, kbnode_t keyblock)
{
if (openpgp_cipher_test_algo (prefs->value))
{
- const char *algo =
+ const char *algo =
(openpgp_cipher_test_algo (prefs->value)
- ? num
+ ? num
: openpgp_cipher_algo_name (prefs->value));
if(!problem)
check_prefs_warning(pk);
@@ -689,7 +689,7 @@ check_prefs (ctrl_t ctrl, kbnode_t keyblock)
{
const char *algo =
(gcry_md_test_algo (prefs->value)
- ? num
+ ? num
: gcry_md_algo_name (prefs->value));
if(!problem)
check_prefs_warning(pk);
@@ -801,7 +801,7 @@ import_one (ctrl_t ctrl,
log_error( _("key %s: no user ID\n"), keystr_from_pk(pk));
return 0;
}
-
+
if (opt.interactive) {
if(is_status_enabled())
print_import_check (pk, uidnode->pkt->pkt.user_id);
@@ -938,7 +938,7 @@ import_one (ctrl_t ctrl,
size_t an;
fingerprint_from_pk (pk_orig, afp, &an);
- while (an < MAX_FINGERPRINT_LEN)
+ while (an < MAX_FINGERPRINT_LEN)
afp[an++] = 0;
rc = keydb_search_fpr (hd, afp);
}
@@ -962,7 +962,7 @@ import_one (ctrl_t ctrl,
n_sigs_cleaned = fix_bad_direct_key_sigs (keyblock_orig, keyid);
if (n_sigs_cleaned)
commit_kbnode (&keyblock_orig);
-
+
/* and try to merge the block */
clear_kbnode_flags( keyblock_orig );
clear_kbnode_flags( keyblock );
@@ -1032,13 +1032,13 @@ import_one (ctrl_t ctrl,
stats->n_sigs_cleaned +=n_sigs_cleaned;
stats->n_uids_cleaned +=n_uids_cleaned;
- if (is_status_enabled ())
+ if (is_status_enabled ())
print_import_ok (pk, ((n_uids?2:0)|(n_sigs?4:0)|(n_subk?8:0)));
}
else
{
same_key = 1;
- if (is_status_enabled ())
+ if (is_status_enabled ())
print_import_ok (pk, 0);
if( !opt.quiet )
@@ -1107,6 +1107,37 @@ import_one (ctrl_t ctrl,
}
+/* Extract one MPI value from the S-expression PKEY which is expected
+ to hold a "public-key". Returns NULL on error. */
+static gcry_mpi_t
+one_mpi_from_pkey (gcry_sexp_t pkey, const char *name, size_t namelen)
+{
+ gcry_sexp_t list, l2;
+ gcry_mpi_t a;
+
+ list = gcry_sexp_find_token (pkey, "public-key", 0);
+ if (!list)
+ return NULL;
+ l2 = gcry_sexp_cadr (list);
+ gcry_sexp_release (list);
+ list = l2;
+ if (!list)
+ return NULL;
+
+ l2 = gcry_sexp_find_token (list, name, namelen);
+ if (!l2)
+ {
+ gcry_sexp_release (list);
+ return NULL;
+ }
+ a = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
+ gcry_sexp_release (l2);
+ gcry_sexp_release (list);
+
+ return a;
+}
+
+
/* Transfer all the secret keys in SEC_KEYBLOCK to the gpg-agent. The
function prints diagnostics and returns an error code. */
static gpg_error_t
@@ -1133,6 +1164,7 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
unsigned char *wrappedkey = NULL;
size_t wrappedkeylen;
char *cache_nonce = NULL;
+ gcry_mpi_t ecc_params[5] = {NULL, NULL, NULL, NULL, NULL};
/* Get the current KEK. */
err = agent_keywrap_key (ctrl, 0, &kek, &keklen);
@@ -1148,7 +1180,8 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
if (!err)
err = gcry_cipher_setkey (cipherhd, kek, keklen);
if (err)
- goto leave; xfree (kek);
+ goto leave;
+ xfree (kek);
kek = NULL;
main_pk = NULL;
@@ -1161,6 +1194,20 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
if (!main_pk)
main_pk = pk;
+ /* Make sure the keyids are available. */
+ keyid_from_pk (pk, NULL);
+ if (node->pkt->pkttype == PKT_SECRET_KEY)
+ {
+ pk->main_keyid[0] = pk->keyid[0];
+ pk->main_keyid[1] = pk->keyid[1];
+ }
+ else
+ {
+ pk->main_keyid[0] = main_pk->keyid[0];
+ pk->main_keyid[1] = main_pk->keyid[1];
+ }
+
+
ski = pk->seckey_info;
if (!ski)
BUG ();
@@ -1191,34 +1238,109 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
init_membuf (&mbuf, 50);
put_membuf_str (&mbuf, "(skey");
- for (i=j=0; i < nskey; i++)
+ if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
+ || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
{
- if (!pk->pkey[i])
- ; /* Protected keys only have NPKEY+1 elements. */
- else if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE))
+ /* We need special treatment for ECC algorithms. OpenPGP
+ stores only the curve name but the agent expects a full
+ key. This is so that we can keep all curve name
+ validation code out of gpg-agent. */
+#if PUBKEY_MAX_NSKEY < 7
+#error PUBKEY_MAX_NSKEY too low for ECC
+#endif
+ char *curve = openpgp_oid_to_str (pk->pkey[0]);
+ if (!curve)
+ err = gpg_error_from_syserror ();
+ else
{
- put_membuf_str (&mbuf, " e %b");
- 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;
+#ifdef HAVE_GCRY_PK_GET_CURVE /* Also ensures availability of get_param. */
+ gcry_sexp_t cparam = gcry_pk_get_param (GCRY_PK_ECDSA, curve);
+#else
+ gcry_sexp_t cparam = NULL;
+#endif
+ xfree (curve);
+ if (!cparam)
+ err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
+ else
+ {
+ const char *s;
+
+ /* Append the curve parameters P, A, B, G and N. */
+ for (i=j=0; !err && *(s = "pabgn"+i); i++)
+ {
+ ecc_params[i] = one_mpi_from_pkey (cparam, s, 1);
+ if (!ecc_params[i])
+ err = gpg_error (GPG_ERR_INV_CURVE);
+ else
+ {
+ put_membuf_str (&mbuf, " _ %m");
+ format_args[j++] = ecc_params+i;
+ }
+ }
+ gcry_sexp_release (cparam);
+ if (!err)
+ {
+ /* Append the public key element Q. */
+ put_membuf_str (&mbuf, " _ %m");
+ format_args[j++] = pk->pkey + 1;
+
+ /* Append the secret key element D. Note that
+ for ECDH we need to skip PKEY[2] because this
+ holds the KEK which is not needed. */
+ i = pk->pubkey_algo == PUBKEY_ALGO_ECDH? 3 : 2;
+ 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 (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;
+ }
+ else
+ {
+ put_membuf_str (&mbuf, " _ %m");
+ format_args[j++] = pk->pkey + i;
+ }
+ }
+ }
}
- else
+ }
+ else
+ {
+ /* Standard case for the old (non-ECC) algorithms. */
+ for (i=j=0; i < nskey; i++)
{
- put_membuf_str (&mbuf, " _ %m");
- format_args[j++] = pk->pkey + i;
+ if (!pk->pkey[i])
+ ; /* Protected keys only have NPKEY+1 elements. */
+ else 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 (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;
+ }
+ else
+ {
+ put_membuf_str (&mbuf, " _ %m");
+ format_args[j++] = pk->pkey + i;
+ }
}
}
put_membuf_str (&mbuf, ")\n");
put_membuf (&mbuf, "", 1);
- {
- char *format = get_membuf (&mbuf, NULL);
- if (!format)
- err = gpg_error_from_syserror ();
- else
- err = gcry_sexp_build_array (&skey, NULL, format, format_args);
- xfree (format);
- }
+ if (err)
+ xfree (get_membuf (&mbuf, NULL));
+ else
+ {
+ char *format = get_membuf (&mbuf, NULL);
+ if (!format)
+ err = gpg_error_from_syserror ();
+ else
+ err = gcry_sexp_build_array (&skey, NULL, format, format_args);
+ xfree (format);
+ }
if (err)
{
log_error ("error building skey array: %s\n", gpg_strerror (err));
@@ -1228,7 +1350,7 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
if (ski->is_protected)
{
char countbuf[35];
-
+
/* Note that the IVLEN may be zero if we are working on a
dummy key. We can't express that in an S-expression and
thus we send dummy data for the IV. */
@@ -1289,9 +1411,9 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
transferkey = NULL;
/* Send the wrapped key to the agent. */
- {
+ {
char *desc = gpg_format_keydesc (pk, 1, 1);
- err = agent_import_key (ctrl, desc, &cache_nonce,
+ err = agent_import_key (ctrl, desc, &cache_nonce,
wrappedkey, wrappedkeylen);
xfree (desc);
}
@@ -1328,6 +1450,8 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock)
}
leave:
+ for (i=0; i < DIM (ecc_params); i++)
+ gcry_mpi_release (ecc_params[i]);
xfree (cache_nonce);
xfree (wrappedkey);
xfree (transferkey);
@@ -1392,7 +1516,7 @@ sec_to_pub_keyblock (kbnode_t sec_keyblock)
* with the trust calculation.
*/
static int
-import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
+import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
struct stats_s *stats, unsigned int options)
{
PKT_public_key *pk;
@@ -1400,17 +1524,17 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
KBNODE node, uidnode;
u32 keyid[2];
int rc = 0;
-
+
/* Get the key and print some info about it */
node = find_kbnode (keyblock, PKT_SECRET_KEY);
if (!node)
BUG ();
-
+
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 ",
@@ -1423,7 +1547,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
log_printf ("\n");
}
stats->secret_read++;
-
+
if (!uidnode)
{
log_error( _("key %s: no user ID\n"), keystr_from_pk (pk));
@@ -1456,10 +1580,10 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
log_error (_("importing secret keys not allowed\n"));
return 0;
}
-#endif
-
+#endif
+
clear_kbnode_flags (keyblock);
-
+
if (!(options&IMPORT_MERGE_ONLY) || !have_secret_key_with_kid (keyid) )
{
/* We don't have this key, insert as a new key. */
@@ -1477,7 +1601,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
/* Fixme: We should check for an invalid keyblock and
cancel the secret key import in this case. */
release_kbnode (pub_keyblock);
-
+
/* Read the keyblock again to get the effects of a merge. */
/* Fixme: we should do this based on the fingerprint or
even better let import_one return the merged
@@ -1493,7 +1617,7 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
if (!opt.quiet)
log_info (_("key %s: secret key imported\n"),
keystr_from_pk (pk));
- if (is_status_enabled ())
+ if (is_status_enabled ())
print_import_ok (pk, 1|16);
check_prefs (ctrl, node);
}
@@ -1502,11 +1626,11 @@ import_secret_one (ctrl_t ctrl, const char *fname, KBNODE keyblock,
}
}
else
- {
+ {
/* We don't want to merge the secret keys. */
log_error (_("key %s: secret key part already available\n"),
keystr_from_pk (pk));
- if (is_status_enabled ())
+ if (is_status_enabled ())
print_import_ok (pk, 16);
}
@@ -1556,9 +1680,9 @@ import_revoke_cert( const char *fname, KBNODE node, struct stats_s *stats )
{
byte afp[MAX_FINGERPRINT_LEN];
size_t an;
-
+
fingerprint_from_pk (pk, afp, &an);
- while (an < MAX_FINGERPRINT_LEN)
+ while (an < MAX_FINGERPRINT_LEN)
afp[an++] = 0;
rc = keydb_search_fpr (hd, afp);
}
@@ -1654,11 +1778,11 @@ chk_self_sigs (const char *fname, kbnode_t keyblock,
int rc;
u32 bsdate=0, rsdate=0;
kbnode_t bsnode = NULL, rsnode = NULL;
-
+
(void)fname;
(void)pk;
- for (n=keyblock; (n = find_next_kbnode (n, 0)); )
+ for (n=keyblock; (n = find_next_kbnode (n, 0)); )
{
if (n->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
@@ -1672,7 +1796,7 @@ chk_self_sigs (const char *fname, kbnode_t keyblock,
if ( n->pkt->pkttype != PKT_SIGNATURE )
continue;
-
+
sig = n->pkt->pkt.signature;
if ( keyid[0] != sig->keyid[0] || keyid[1] != sig->keyid[1] )
{
@@ -1684,7 +1808,7 @@ chk_self_sigs (const char *fname, kbnode_t keyblock,
import a fully-cached key which speeds things up. */
if (!opt.no_sig_cache)
check_key_signature (keyblock, n, NULL);
-
+
if ( IS_UID_SIG(sig) || IS_UID_REV(sig) )
{
KBNODE unode = find_prev_kbnode( keyblock, n, PKT_USER_ID );
@@ -1694,16 +1818,16 @@ chk_self_sigs (const char *fname, kbnode_t keyblock,
keystr(keyid));
return -1; /* The complete keyblock is invalid. */
}
-
+
/* If it hasn't been marked valid yet, keep trying. */
- if (!(unode->flag&1))
+ if (!(unode->flag&1))
{
rc = check_key_signature (keyblock, n, NULL);
if ( rc )
{
if ( opt.verbose )
{
- char *p = utf8_to_native
+ char *p = utf8_to_native
(unode->pkt->pkt.user_id->name,
strlen (unode->pkt->pkt.user_id->name),0);
log_info (gpg_err_code(rc) == G10ERR_PUBKEY_ALGO ?
@@ -1732,7 +1856,7 @@ chk_self_sigs (const char *fname, kbnode_t keyblock,
n->flag |= 4;
}
}
- else if ( IS_SUBKEY_SIG (sig) )
+ else if ( IS_SUBKEY_SIG (sig) )
{
/* Note that this works based solely on the timestamps like
the rest of gpg. If the standard gets revocation
@@ -1761,19 +1885,19 @@ chk_self_sigs (const char *fname, kbnode_t keyblock,
else
{
/* It's valid, so is it newer? */
- if (sig->timestamp >= bsdate)
+ if (sig->timestamp >= bsdate)
{
knode->flag |= 1; /* The subkey is valid. */
if (bsnode)
{
/* Delete the last binding sig since this
one is newer */
- bsnode->flag |= 4;
+ bsnode->flag |= 4;
if (opt.verbose)
log_info (_("key %s: removed multiple subkey"
" binding\n"),keystr(keyid));
}
-
+
bsnode = n;
bsdate = sig->timestamp;
}
@@ -1818,12 +1942,12 @@ chk_self_sigs (const char *fname, kbnode_t keyblock,
{
/* Delete the last revocation sig since
this one is newer. */
- rsnode->flag |= 4;
+ rsnode->flag |= 4;
if (opt.verbose)
log_info (_("key %s: removed multiple subkey"
" revocation\n"),keystr(keyid));
}
-
+
rsnode = n;
rsdate = sig->timestamp;
}
diff --git a/g10/keygen.c b/g10/keygen.c
index 4d911f0b9..d8535fa61 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1080,6 +1080,40 @@ write_keybinding (KBNODE root, PKT_public_key *pri_psk, PKT_public_key *sub_psk,
return err;
}
+/* Map the Libgcrypt ECC curve NAME to an OID. If R_NBITS is not NULL
+ store the bit size of the curve there. Returns NULL for unknown
+ curve names. */
+const char *
+gpg_curve_to_oid (const char *name, unsigned int *r_nbits)
+{
+ unsigned int nbits = 0;
+ const char *oidstr;
+
+ if (!name)
+ oidstr = NULL;
+ else if (!strcmp (name, "NIST P-256"))
+ {
+ oidstr = "1.2.840.10045.3.1.7";
+ nbits = 256;
+ }
+ else if (!strcmp (name, "NIST P-384"))
+ {
+ oidstr = "1.3.132.0.34";
+ nbits = 384;
+ }
+ else if (!strcmp (name, "NIST P-521"))
+ {
+ oidstr = "1.3.132.0.35";
+ nbits = 521;
+ }
+ else
+ oidstr = NULL;
+
+ if (r_nbits)
+ *r_nbits = nbits;
+ return oidstr;
+}
+
static gpg_error_t
ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, int algo)
@@ -1117,23 +1151,11 @@ ecckey_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, int algo)
goto leave;
}
gcry_sexp_release (l2);
- if (!strcmp (curve, "NIST P-256"))
- {
- oidstr = "1.2.840.10045.3.1.7";
- nbits = 256;
- }
- else if (!strcmp (curve, "NIST P-384"))
- {
- oidstr = "1.3.132.0.34";
- nbits = 384;
- }
- else if (!strcmp (curve, "NIST P-521"))
- {
- oidstr = "1.3.132.0.35";
- nbits = 521;
- }
- else
+ oidstr = gpg_curve_to_oid (curve, &nbits);
+ if (!oidstr)
{
+ /* That can't happen because we used one of the curves
+ gpg_curve_to_oid knows about. */
err = gpg_error (GPG_ERR_INV_OBJ);
goto leave;
}
@@ -1445,7 +1467,8 @@ gen_ecc (int algo, unsigned int nbits, kbnode_t pub_root,
assert (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH);
- /* For now we may only use one of the 3 NISY curves. */
+ /* For now we may only use one of the 3 NIST curves. See also
+ gpg_curve_to_oid. */
if (nbits <= 256)
curve = "NIST P-256";
else if (nbits <= 384)
diff --git a/g10/keyid.c b/g10/keyid.c
index 6571a51c0..cbcc971c3 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -39,7 +39,7 @@
#ifdef HAVE_UNSIGNED_TIME_T
# define IS_INVALID_TIME_T(a) ((a) == (time_t)(-1))
-#else
+#else
/* Error or 32 bit time_t and value after 2038-01-19. */
# define IS_INVALID_TIME_T(a) ((a) < 0)
#endif
@@ -81,6 +81,11 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
if(pk->version<4)
n+=2;
+ /* FIXME: We can avoid the extra malloc by calling only the first
+ mpi_print here which computes the required length and calling the
+ real mpi_print only at the end. The speed advantage would only be
+ for ECC (opaque MPIs) or if we could implement an mpi_print
+ variant with a callback handler to do the hashing. */
if (npkey==0 && pk->pkey[0]
&& gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE))
{
@@ -92,25 +97,32 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
{
for (i=0; i < npkey; i++ )
{
- enum gcry_mpi_format fmt;
-
- if ((pk->pubkey_algo == PUBKEY_ALGO_ECDSA
- || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
- && (i == 0 || i == 2))
- fmt = GCRYMPI_FMT_USG; /* Name of OID or KEK parms. */
+ if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE))
+ {
+ size_t nbits;
+ const void *p;
+
+ p = gcry_mpi_get_opaque (pk->pkey[i], &nbits);
+ pp[i] = xmalloc ((nbits+7)/8);
+ memcpy (pp[i], p, (nbits+7)/8);
+ nn[i] = (nbits+7)/8;
+ n += nn[i];
+ }
else
- fmt = GCRYMPI_FMT_PGP;
-
- if (gcry_mpi_print (fmt, NULL, 0, &nbytes, pk->pkey[i]))
- BUG ();
- pp[i] = xmalloc (nbytes);
- if (gcry_mpi_print (fmt, pp[i], nbytes, &nbytes, pk->pkey[i]))
- BUG ();
- nn[i] = nbytes;
- n += nn[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 ? */
gcry_md_putc ( md, n >> 8 ); /* 2 byte length header */
@@ -127,7 +139,7 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk)
u16 days=0;
if(pk->expiredate)
days=(u16)((pk->expiredate - pk->timestamp) / 86400L);
-
+
gcry_md_putc ( md, days >> 8 );
gcry_md_putc ( md, days );
}
@@ -178,7 +190,7 @@ v3_keyid (gcry_mpi_t a, u32 *ki)
BUG ();
if (nbytes < 8) /* oops */
ki[0] = ki[1] = 0;
- else
+ else
{
p = buffer + nbytes - 8;
ki[0] = (p[0] << 24) | (p[1] <<16) | (p[2] << 8) | p[3];
@@ -215,7 +227,7 @@ keystrlen(void)
const char *
keystr (u32 *keyid)
-{
+{
static char keyid_str[KEYID_STR_SIZE];
switch (opt.keyid_format)
@@ -226,7 +238,7 @@ keystr (u32 *keyid)
case KF_LONG:
if (keyid[0])
- snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX",
+ snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX",
(ulong)keyid[0], (ulong)keyid[1]);
else
snprintf (keyid_str, sizeof keyid_str, "%08lX", (ulong)keyid[1]);
@@ -238,12 +250,12 @@ keystr (u32 *keyid)
case KF_0xLONG:
if(keyid[0])
- snprintf (keyid_str, sizeof keyid_str, "0x%08lX%08lX",
+ snprintf (keyid_str, sizeof keyid_str, "0x%08lX%08lX",
(ulong)keyid[0],(ulong)keyid[1]);
else
snprintf (keyid_str, sizeof keyid_str, "0x%08lX", (ulong)keyid[1]);
break;
-
+
default:
BUG();
}
@@ -254,7 +266,7 @@ keystr (u32 *keyid)
const char *
keystr_with_sub (u32 *main_kid, u32 *sub_kid)
-{
+{
static char buffer[KEYID_STR_SIZE+1+KEYID_STR_SIZE];
char *p;
@@ -408,7 +420,7 @@ keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
else
keyid_from_pk (&pk, keyid);
}
- else
+ else
{
const byte *dp = fprint;
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
@@ -422,7 +434,7 @@ keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
u32
keyid_from_sig (PKT_signature *sig, u32 *keyid)
{
- if( keyid )
+ if( keyid )
{
keyid[0] = sig->keyid[0];
keyid[1] = sig->keyid[1];
@@ -437,13 +449,13 @@ namehash_from_uid (PKT_user_id *uid)
if (!uid->namehash)
{
uid->namehash = xmalloc (20);
-
+
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);
}
-
+
return uid->namehash;
}
@@ -465,7 +477,7 @@ mk_datestr (char *buffer, time_t atime)
if (IS_INVALID_TIME_T (atime))
strcpy (buffer, "????" "-??" "-??"); /* Mark this as invalid. */
- else
+ else
{
tp = gmtime (&atime);
sprintf (buffer,"%04d-%02d-%02d",
@@ -485,7 +497,7 @@ datestr_from_pk (PKT_public_key *pk)
{
static char buffer[11+5];
time_t atime = pk->timestamp;
-
+
return mk_datestr (buffer, atime);
}
@@ -518,7 +530,7 @@ expirestr_from_sig (PKT_signature *sig)
{
static char buffer[11+5];
time_t atime;
-
+
if (!sig->expiredate)
return _("never ");
atime=sig->expiredate;
@@ -591,7 +603,7 @@ const char *
colon_datestr_from_sig (PKT_signature *sig)
{
static char buf[20];
-
+
snprintf (buf, sizeof buf, "%lu", (ulong)sig->timestamp);
return buf;
}
@@ -621,21 +633,21 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
const byte *dp;
size_t len, nbytes;
int i;
-
+
if ( pk->version < 4 )
{
if ( is_RSA(pk->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 (pk->pubkey_algo) > 1 )
+ if ( pubkey_get_npkey (pk->pubkey_algo) > 1 )
{
for (i=0; i < 2; i++)
{
- if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0,
+ if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0,
&nbytes, pk->pkey[i]))
BUG ();
/* fixme: Better allocate BUF on the stack */
@@ -662,10 +674,10 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
memset (array,0,16);
}
}
- else
+ else
{
gcry_md_hd_t md;
-
+
md = do_fingerprint_md(pk);
dp = gcry_md_read( md, 0 );
len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
@@ -677,7 +689,7 @@ fingerprint_from_pk (PKT_public_key *pk, byte *array, size_t *ret_len)
pk->keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
gcry_md_close( md);
}
-
+
*ret_len = len;
return array;
}
@@ -694,7 +706,7 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
{
gpg_error_t err;
gcry_sexp_t s_pkey;
-
+
if (DBG_PACKET)
log_debug ("get_keygrip for public key\n");
@@ -742,7 +754,7 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
break;
}
-
+
if (err)
return err;
@@ -758,7 +770,7 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array)
/* FIXME: Save the keygrip in PK. */
}
gcry_sexp_release (s_pkey);
-
+
return 0;
}
@@ -786,4 +798,3 @@ hexkeygrip_from_pk (PKT_public_key *pk, char **r_grip)
}
return err;
}
-
diff --git a/g10/main.h b/g10/main.h
index d70c16901..920d82c97 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -236,6 +236,7 @@ void keyedit_passwd (ctrl_t ctrl, const char *username);
void show_basic_key_info (KBNODE keyblock);
/*-- keygen.c --*/
+const char *gpg_curve_to_oid (const char *name, unsigned int *r_nbits);
u32 parse_expire_string(const char *string);
u32 ask_expire_interval(int object,const char *def_expire);
u32 ask_expiredate(void);
diff --git a/g10/passphrase.c b/g10/passphrase.c
index f29fca72f..8065810c9 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -74,7 +74,7 @@ encode_s2k_iterations (int iterations)
if (err && gpg_err_code (err) != GPG_ERR_ASS_PARAMETER)
log_error (_("problem with the agent: %s\n"), gpg_strerror (err));
/* Default to 65536 which we used up to 2.0.13. */
- return 96;
+ return 96;
}
else if (mycnt >= 65011712)
return 255; /* Largest possible value. */
@@ -87,7 +87,7 @@ encode_s2k_iterations (int iterations)
if (iterations >= 65011712)
return 255;
-
+
/* Need count to be in the range 16-31 */
for (count=iterations>>6; count>=32; count>>=1)
c++;
@@ -96,13 +96,13 @@ encode_s2k_iterations (int iterations)
if (S2K_DECODE_COUNT(result) < iterations)
result++;
-
+
return result;
}
-/* Hash a passphrase using the supplied s2k.
+/* Hash a passphrase using the supplied s2k.
Always needs: dek->algo, s2k->mode, s2k->hash_algo. */
static void
hash_passphrase ( DEK *dek, char *pw, STRING2KEY *s2k)
@@ -119,20 +119,20 @@ hash_passphrase ( DEK *dek, char *pw, STRING2KEY *s2k)
if (gcry_md_open (&md, s2k->hash_algo, 1))
BUG ();
- for (pass=0; used < dek->keylen ; pass++ )
+ for (pass=0; used < dek->keylen ; pass++ )
{
- if ( pass )
+ if ( pass )
{
gcry_md_reset (md);
for (i=0; i < pass; i++ ) /* Preset the hash context. */
gcry_md_putc (md, 0 );
}
- if ( s2k->mode == 1 || s2k->mode == 3 )
+ if ( s2k->mode == 1 || s2k->mode == 3 )
{
int len2 = pwlen + 8;
ulong count = len2;
-
+
if ( s2k->mode == 3 )
{
count = S2K_DECODE_COUNT(s2k->count);
@@ -146,7 +146,7 @@ hash_passphrase ( DEK *dek, char *pw, STRING2KEY *s2k)
/* A little bit complicated because we need a ulong for count. */
while ( count > len2 ) /* maybe iterated+salted */
- {
+ {
gcry_md_write ( md, s2k->salt, 8 );
gcry_md_write ( md, pw, pwlen );
count -= len2;
@@ -231,7 +231,7 @@ read_passphrase_from_fd( int fd )
int i, len;
char *pw;
- if ( !opt.batch )
+ if ( !opt.batch )
{ /* Not used but we have to do a dummy read, so that it won't end
up at the begin of the message if the quite usual trick to
prepend the passphtrase to the message is used. */
@@ -240,12 +240,12 @@ read_passphrase_from_fd( int fd )
while (!(read (fd, buf, 1) != 1 || *buf == '\n' ))
;
*buf = 0;
- return;
+ return;
}
- for (pw = NULL, i = len = 100; ; i++ )
+ for (pw = NULL, i = len = 100; ; i++ )
{
- if (i >= len-1 )
+ if (i >= len-1 )
{
char *pw2 = pw;
len += 100;
@@ -311,35 +311,35 @@ passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat,
if( keyid && get_pubkey( pk, keyid ) )
{
if (pk)
- free_public_key( pk );
+ free_public_key( pk );
pk = NULL; /* oops: no key for some reason */
}
-
+
orig_codeset = i18n_switchto_utf8 ();
if (custom_description)
atext = native_to_utf8 (custom_description);
else if ( !mode && pk && keyid )
- {
+ {
char *uid;
size_t uidlen;
const char *algo_name = openpgp_pk_algo_name ( pk->pubkey_algo );
const char *timestr;
char *maink;
-
+
if ( !algo_name )
algo_name = "?";
#define KEYIDSTRING _(" (main key ID %s)")
maink = xmalloc ( strlen (KEYIDSTRING) + keystrlen() + 20 );
- if( keyid[2] && keyid[3] && keyid[0] != keyid[2]
+ if( keyid[2] && keyid[3] && keyid[0] != keyid[2]
&& keyid[1] != keyid[3] )
sprintf( maink, KEYIDSTRING, keystr(&keyid[2]) );
else
*maink = 0;
-
- uid = get_user_id ( keyid, &uidlen );
+
+ uid = get_user_id ( keyid, &uidlen );
timestr = strtimestamp (pk->timestamp);
#undef KEYIDSTRING
@@ -350,7 +350,7 @@ passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat,
"%u-bit %s key, ID %s,\n" \
"created %s%s.\n" )
- atext = xmalloc ( 100 + strlen (PROMPTSTRING)
+ atext = xmalloc ( 100 + strlen (PROMPTSTRING)
+ uidlen + 15 + strlen(algo_name) + keystrlen()
+ strlen (timestr) + strlen (maink) );
sprintf (atext, PROMPTSTRING,
@@ -362,16 +362,16 @@ passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat,
#undef PROMPTSTRING
- {
+ {
size_t dummy;
fingerprint_from_pk( pk, fpr, &dummy );
have_fpr = 1;
}
-
+
}
else
atext = xstrdup ( _("Enter passphrase\n") );
-
+
if (!mode && cacheid)
my_cacheid = cacheid;
@@ -387,7 +387,7 @@ passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat,
rc = agent_get_passphrase (my_cacheid, tryagain_text, my_prompt, atext,
repeat, check, &pw);
-
+
xfree (my_prompt);
xfree (atext); atext = NULL;
@@ -396,14 +396,14 @@ passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat,
if (!rc)
;
- else if (gpg_err_code (rc) == GPG_ERR_CANCELED
+ else if (gpg_err_code (rc) == GPG_ERR_CANCELED
|| gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
{
log_info (_("cancelled by user\n") );
if (canceled)
*canceled = 1;
}
- else
+ else
{
log_error (_("problem with the agent: %s\n"), gpg_strerror (rc));
/* Due to limitations in the API of the upper layers they
@@ -412,7 +412,7 @@ passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat,
definitely not happen and let it continue without requiring a
passphrase. Given that now all the upper layers handle a
cancel correctly, we simply set the cancel flag now for all
- errors from the agent. */
+ errors from the agent. */
if (canceled)
*canceled = 1;
@@ -440,7 +440,7 @@ passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo )
int rc;
(void)algo;
-
+
if (!cacheid)
{
PKT_public_key *pk;
@@ -450,7 +450,7 @@ passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo )
byte fpr[MAX_FINGERPRINT_LEN];
char hexfprbuf[2*20+1];
size_t dummy;
-
+
pk = xcalloc (1, sizeof *pk);
if ( !keyid || get_pubkey( pk, keyid ) )
{
@@ -478,7 +478,7 @@ passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo )
NULL, sets it to true.
MODE 0: Allow cached passphrase
- 1: Ignore cached passphrase
+ 1: Ignore cached passphrase
2: Ditto, but create a new key
3: Allow cached passphrase; use the S2K salt as the cache ID
4: Ditto, but create a new key
@@ -486,7 +486,7 @@ passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo )
DEK *
passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
int cipher_algo, STRING2KEY *s2k, int mode,
- const char *tryagain_text,
+ const char *tryagain_text,
const char *custdesc, const char *custprompt,
int *canceled)
{
@@ -499,11 +499,11 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
if (!canceled)
canceled = &dummy_canceled;
*canceled = 0;
-
+
if ( !s2k )
{
assert (mode != 3 && mode != 4);
- /* This is used for the old rfc1991 mode
+ /* This is used for the old rfc1991 mode
* Note: This must match the code in encode.c with opt.rfc1991 set */
s2k = &help_s2k;
s2k->mode = 0;
@@ -529,16 +529,16 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
/* If we do not have a passphrase available in NEXT_PW and status
information are request, we print them now. */
- if ( !next_pw && is_status_enabled() )
+ if ( !next_pw && is_status_enabled() )
{
char buf[50];
-
+
if ( keyid )
{
u32 used_kid[2];
char *us;
-
- if ( keyid[2] && keyid[3] )
+
+ if ( keyid[2] && keyid[3] )
{
used_kid[0] = keyid[2];
used_kid[1] = keyid[3];
@@ -548,16 +548,16 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
used_kid[0] = keyid[0];
used_kid[1] = keyid[1];
}
-
+
us = get_long_user_id_string ( keyid );
write_status_text ( STATUS_USERID_HINT, us );
xfree(us);
-
+
snprintf (buf, sizeof buf -1, "%08lX%08lX %08lX%08lX %d 0",
(ulong)keyid[0], (ulong)keyid[1],
(ulong)used_kid[0], (ulong)used_kid[1],
pubkey_algo );
-
+
write_status_text ( STATUS_NEED_PASSPHRASE, buf );
}
else
@@ -576,7 +576,7 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
{
PKT_public_key *pk = xmalloc_clear( sizeof *pk );
char *p;
-
+
p = get_user_id_native(keyid);
tty_printf ("\n");
tty_printf (_("You need a passphrase to unlock the secret key for\n"
@@ -586,7 +586,7 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
if ( !get_pubkey( pk, keyid ) )
{
const char *s = openpgp_pk_algo_name ( pk->pubkey_algo );
-
+
tty_printf (_("%u-bit %s key, ID %s, created %s"),
nbits_from_pk( pk ), s?s:"?", keystr(keyid),
strtimestamp(pk->timestamp) );
@@ -610,19 +610,19 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
free_public_key( pk );
}
- if ( next_pw )
+ if ( next_pw )
{
/* Simply return the passphrase we already have in NEXT_PW. */
pw = next_pw;
next_pw = NULL;
}
- else if ( have_static_passphrase () )
+ else if ( have_static_passphrase () )
{
/* Return the passphrase we have stored in FD_PASSWD. */
pw = xmalloc_secure ( strlen(fd_passwd)+1 );
strcpy ( pw, fd_passwd );
}
- else
+ else
{
if ((mode == 3 || mode == 4) && (s2k->mode == 1 || s2k->mode == 3))
{
@@ -643,7 +643,7 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
return NULL;
}
}
-
+
if ( !pw || !*pw )
write_status( STATUS_MISSING_PASSPHRASE );
@@ -689,15 +689,15 @@ gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped)
char *maink;
char *desc;
const char *prompt;
-
+
algo_name = openpgp_pk_algo_name (pk->pubkey_algo);
timestr = strtimestamp (pk->timestamp);
- uid = get_user_id (pk->keyid, &uidlen);
+ uid = get_user_id (pk->keyid, &uidlen);
orig_codeset = i18n_switchto_utf8 ();
if (pk->main_keyid[0] && pk->main_keyid[1]
- && pk->keyid[0] != pk->main_keyid[0]
+ && pk->keyid[0] != pk->main_keyid[0]
&& pk->keyid[1] != pk->main_keyid[1])
maink = xtryasprintf (_(" (main key ID %s)"), keystr (pk->main_keyid));
else
@@ -724,7 +724,7 @@ gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped)
"created %s%s.\n"),
prompt,
(int)uidlen, uid,
- nbits_from_pk (pk), algo_name,
+ nbits_from_pk (pk), algo_name,
keystr (pk->keyid), timestr,
maink?maink:"" );
xfree (maink);
@@ -735,7 +735,7 @@ gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped)
if (escaped)
{
char *tmp = percent_plus_escape (desc);
- xfree (desc);
+ xfree (desc);
desc = tmp;
}
diff --git a/include/ChangeLog b/include/ChangeLog
index 8dd88ffbb..81ba48bab 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@
+2011-02-01 Werner Koch <[email protected]>
+
+ * cipher.h (PUBKEY_MAX_NPKEY, PUBKEY_MAX_NSKEY): Bump up to
+ accommodate gcrypt ECC keys.
+
2011-01-21 Werner Koch <[email protected]>
* cipher.h (GCRY_PK_USAGE_CERT): Remove compatibility macros
diff --git a/include/cipher.h b/include/cipher.h
index 311020857..4667e8043 100644
--- a/include/cipher.h
+++ b/include/cipher.h
@@ -100,8 +100,8 @@ typedef struct
/* Constants to allocate static MPI arrays. */
-#define PUBKEY_MAX_NPKEY 4
-#define PUBKEY_MAX_NSKEY 6
+#define PUBKEY_MAX_NPKEY 5
+#define PUBKEY_MAX_NSKEY 7
#define PUBKEY_MAX_NSIG 2
#define PUBKEY_MAX_NENC 2
diff --git a/tests/openpgp/samplekeys/README b/tests/openpgp/samplekeys/README
index d38616990..fd05aa3a4 100644
--- a/tests/openpgp/samplekeys/README
+++ b/tests/openpgp/samplekeys/README
@@ -1,4 +1,5 @@
no-creation-time.gpg A key with a zero creation time.
-
+ecc-sample-1-pub.asc The first ECC sample key.
+ecc-sample-1-sec.asc The first ECC sample key (secret).
diff --git a/tests/openpgp/samplekeys/ecc-sample-1-pub.asc b/tests/openpgp/samplekeys/ecc-sample-1-pub.asc
new file mode 100644
index 000000000..478fc3aac
--- /dev/null
+++ b/tests/openpgp/samplekeys/ecc-sample-1-pub.asc
@@ -0,0 +1,22 @@
+The key has been generated by the first GnuPG ECC version at
+http://code.google.com/p/gnupg-ecc.
+
+The sample key has ECDSA top key 0xBAA59D9C and a single ECDH
+encryption subkey 0x4089AB73. ECDH subkey uses SHA-256 and AES-128
+with KDF.
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2.1.0-ecc (GNU/Linux)
+
+mFIETJPQrRMIKoZIzj0DAQcCAwQLx6e669XwjHTHe3HuROe7C1oYMXuZbaU5PjOs
+xSkyxtL2D00e/jWgufuNN4ftS+6XygEtB7j1g1vnCTVF1TLmtCRlY19kc2FfZGhf
+MjU2IDxvcGVucGdwQGJyYWluaHViLm9yZz6IegQTEwgAIgUCTJPQrQIbAwYLCQgH
+AwIGFQgCCQoLBBYCAwECHgECF4AACgkQC6Ut8LqlnZzmXQEAiKgiSzPSpUOJcX9d
+JtLJ5As98Alit2oFwzhxG7mSVmQA/RP67yOeoUtdsK6bwmRA95cwf9lBIusNjehx
+XDfpHj+/uFYETJPQrRIIKoZIzj0DAQcCAwR/cMCoGEzcrqXbILqP7Rfke977dE1X
+XsRJEwrzftreZYrn7jXSDoiXkRyfVkvjPZqUvB5cknsaoH/3UNLRHClxAwEIB4hh
+BBgTCAAJBQJMk9CtAhsMAAoJEAulLfC6pZ2c1yYBAOSUmaQ8rkgihnepbnpK7tNz
+3QEocsLEtsTCDUBGNYGyAQDclifYqsUChXlWKaw3md+yHJPcWZXzHt37c4q/MhIm
+oQ==
+=hMzp
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/openpgp/samplekeys/ecc-sample-1-sec.asc b/tests/openpgp/samplekeys/ecc-sample-1-sec.asc
new file mode 100644
index 000000000..5ff5555f2
--- /dev/null
+++ b/tests/openpgp/samplekeys/ecc-sample-1-sec.asc
@@ -0,0 +1,25 @@
+The key has been generated by the first GnuPG ECC version at
+http://code.google.com/p/gnupg-ecc.
+
+The sample key has ECDSA top key 0xBAA59D9C and a single ECDH
+encryption subkey 0x4089AB73. ECDH subkey uses SHA-256 and AES-128
+with KDF. The password for the key is "ecc".
+
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v2.1.0-ecc (GNU/Linux)
+
+lJ0ETJPQrRMIKoZIzj0DAQcCAwQLx6e669XwjHTHe3HuROe7C1oYMXuZbaU5PjOs
+xSkyxtL2D00e/jWgufuNN4ftS+6XygEtB7j1g1vnCTVF1TLm/gMDAmHomSLb9NbE
+oyWUoqgKTbZzbFR/SWmiCcuiQEhREcTyvyU1hAglj7FsBJoQ6/pbeAEQZ3bVzlNM
+8F0nF8KPLPuEADF1+4CntCRlY19kc2FfZGhfMjU2IDxvcGVucGdwQGJyYWluaHVi
+Lm9yZz6IegQTEwgAIgUCTJPQrQIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
+CgkQC6Ut8LqlnZzmXQEAiKgiSzPSpUOJcX9dJtLJ5As98Alit2oFwzhxG7mSVmQA
+/RP67yOeoUtdsK6bwmRA95cwf9lBIusNjehxXDfpHj+/nKEETJPQrRIIKoZIzj0D
+AQcCAwR/cMCoGEzcrqXbILqP7Rfke977dE1XXsRJEwrzftreZYrn7jXSDoiXkRyf
+VkvjPZqUvB5cknsaoH/3UNLRHClxAwEIB/4DAwJh6Jki2/TWxKO7gHKWIcOcxYZp
+CRWjlUghbKb6Q83p8GLPjKRN0USl/U1tObWdksqMXhUO0ePLWUnrbwoWYfYXg9Er
+ADTgCYhhBBgTCAAJBQJMk9CtAhsMAAoJEAulLfC6pZ2c1yYA/3eJRirPQZmBno+Z
+P/HOBSFWmFt4cUBGUx3oqiUd5loOAP480pb+vXx9ipljJWCJDSl/boRSuqB4hePP
+qt9Rd5gNdQ==
+=O8Dg
+-----END PGP PRIVATE KEY BLOCK-----